mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-17 06:26:55 +00:00
GAI logic on stable too
This commit is contained in:
parent
9b0d1c1166
commit
9a2856837c
@ -1868,62 +1868,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// We defer checking whether the element type is `Copy` as it is possible to have
|
||||
// an inference variable as a repeat count and it seems unlikely that `Copy` would
|
||||
// have inference side effects required for type checking to succeed.
|
||||
if tcx.features().generic_arg_infer() {
|
||||
self.deferred_repeat_expr_checks.borrow_mut().push((element, element_ty, count));
|
||||
// If the length is 0, we don't create any elements, so we don't copy any.
|
||||
// If the length is 1, we don't copy that one element, we move it. Only check
|
||||
// for `Copy` if the length is larger, or unevaluated.
|
||||
} else if count.try_to_target_usize(self.tcx).is_none_or(|x| x > 1) {
|
||||
self.enforce_repeat_element_needs_copy_bound(element, element_ty);
|
||||
}
|
||||
self.deferred_repeat_expr_checks.borrow_mut().push((element, element_ty, count));
|
||||
|
||||
let ty = Ty::new_array_with_const_len(tcx, t, count);
|
||||
self.register_wf_obligation(ty.into(), expr.span, ObligationCauseCode::WellFormed(None));
|
||||
ty
|
||||
}
|
||||
|
||||
/// Requires that `element_ty` is `Copy` (unless it's a const expression itself).
|
||||
pub(super) fn enforce_repeat_element_needs_copy_bound(
|
||||
&self,
|
||||
element: &hir::Expr<'_>,
|
||||
element_ty: Ty<'tcx>,
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
// Actual constants as the repeat element get inserted repeatedly instead of getting copied via Copy.
|
||||
match &element.kind {
|
||||
hir::ExprKind::ConstBlock(..) => return,
|
||||
hir::ExprKind::Path(qpath) => {
|
||||
let res = self.typeck_results.borrow().qpath_res(qpath, element.hir_id);
|
||||
if let Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::AnonConst, _) = res
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
// If someone calls a const fn or constructs a const value, they can extract that
|
||||
// out into a separate constant (or a const block in the future), so we check that
|
||||
// to tell them that in the diagnostic. Does not affect typeck.
|
||||
let is_constable = match element.kind {
|
||||
hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
|
||||
ty::FnDef(def_id, _) if tcx.is_stable_const_fn(def_id) => traits::IsConstable::Fn,
|
||||
_ => traits::IsConstable::No,
|
||||
},
|
||||
hir::ExprKind::Path(qpath) => {
|
||||
match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) {
|
||||
Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor,
|
||||
_ => traits::IsConstable::No,
|
||||
}
|
||||
}
|
||||
_ => traits::IsConstable::No,
|
||||
};
|
||||
|
||||
let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
|
||||
let code =
|
||||
traits::ObligationCauseCode::RepeatElementCopy { is_constable, elt_span: element.span };
|
||||
self.require_type_meets(element_ty, element.span, code, lang_item);
|
||||
}
|
||||
|
||||
fn check_expr_tuple(
|
||||
&self,
|
||||
elts: &'tcx [hir::Expr<'tcx>],
|
||||
|
@ -4,10 +4,10 @@ use itertools::Itertools;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, a_or_an, listify, pluralize};
|
||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::{ExprKind, HirId, Node, QPath};
|
||||
use rustc_hir::{ExprKind, HirId, LangItem, Node, QPath};
|
||||
use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
|
||||
use rustc_hir_analysis::check::potentially_plural_count;
|
||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
||||
@ -162,6 +162,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Requires that `element_ty` is `Copy` (unless it's a const expression itself).
|
||||
pub(super) fn enforce_repeat_element_needs_copy_bound(
|
||||
&self,
|
||||
element: &hir::Expr<'_>,
|
||||
element_ty: Ty<'tcx>,
|
||||
) {
|
||||
// Actual constants as the repeat element get inserted repeatedly instead of getting copied via Copy.
|
||||
match &element.kind {
|
||||
hir::ExprKind::ConstBlock(..) => return,
|
||||
hir::ExprKind::Path(qpath) => {
|
||||
let res = self.typeck_results.borrow().qpath_res(qpath, element.hir_id);
|
||||
if let Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::AnonConst, _) = res
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// If someone calls a const fn or constructs a const value, they can extract that
|
||||
// out into a separate constant (or a const block in the future), so we check that
|
||||
// to tell them that in the diagnostic. Does not affect typeck.
|
||||
let is_constable = match element.kind {
|
||||
hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
|
||||
ty::FnDef(def_id, _) if self.tcx.is_stable_const_fn(def_id) => {
|
||||
traits::IsConstable::Fn
|
||||
}
|
||||
_ => traits::IsConstable::No,
|
||||
},
|
||||
hir::ExprKind::Path(qpath) => {
|
||||
match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) {
|
||||
Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor,
|
||||
_ => traits::IsConstable::No,
|
||||
}
|
||||
}
|
||||
_ => traits::IsConstable::No,
|
||||
};
|
||||
|
||||
let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
|
||||
let code =
|
||||
traits::ObligationCauseCode::RepeatElementCopy { is_constable, elt_span: element.span };
|
||||
self.require_type_meets(element_ty, element.span, code, lang_item);
|
||||
}
|
||||
|
||||
pub(in super::super) fn check_method_argument_types(
|
||||
&self,
|
||||
sp: Span,
|
||||
|
@ -49,12 +49,14 @@ fn ice() {
|
||||
// Use index
|
||||
let arr = [0; 5];
|
||||
let _ = arr[2];
|
||||
//~^ ERROR cannot index into a value of type `[{integer}; 5]`
|
||||
|
||||
// Use phantomdata
|
||||
let _ = MyPhantomData::<(), i32>;
|
||||
|
||||
// Use Foo
|
||||
let _: () = Foo;
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
// use `start`
|
||||
|
@ -76,9 +76,23 @@ LL | r + a;
|
||||
| |
|
||||
| {integer}
|
||||
|
||||
error[E0608]: cannot index into a value of type `[{integer}; 5]`
|
||||
--> $DIR/lang-item-generic-requirements.rs:51:16
|
||||
|
|
||||
LL | let _ = arr[2];
|
||||
| ^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/lang-item-generic-requirements.rs:58:17
|
||||
|
|
||||
LL | let _: () = Foo;
|
||||
| -- ^^^ expected `()`, found `Foo`
|
||||
| |
|
||||
| expected due to this
|
||||
|
||||
error: requires `copy` lang_item
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0369, E0392, E0718.
|
||||
For more information about an error, try `rustc --explain E0369`.
|
||||
Some errors have detailed explanations: E0308, E0369, E0392, E0608, E0718.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
@ -0,0 +1,65 @@
|
||||
#![feature(generic_arg_infer)]
|
||||
|
||||
// Test when deferring repeat expr copy checks to end of typechecking whether elements
|
||||
// that are const items allow for repeat counts to go uninferred without an error being
|
||||
// emitted if they would later wind up inferred by integer fallback.
|
||||
//
|
||||
// This test should be updated if we wind up deferring repeat expr checks until *after*
|
||||
// integer fallback as the point of the test is not *specifically* about integer fallback
|
||||
// but rather about the behaviour of `const` element exprs.
|
||||
|
||||
trait Trait<const N: usize> {}
|
||||
|
||||
// We impl `Trait` for both `i32` and `u32` to avoid being able
|
||||
// to prove `?int: Trait<?n>` from there only being one impl.
|
||||
impl Trait<2> for i32 {}
|
||||
impl Trait<2> for u32 {}
|
||||
|
||||
fn tie_and_make_goal<const N: usize, T: Trait<N>>(_: &T, _: &[String; N]) {}
|
||||
|
||||
fn const_block() {
|
||||
// Deferred repeat expr `String; ?n`
|
||||
let a = [const { String::new() }; _];
|
||||
//~^ ERROR: type annotations needed for `[String; _]`
|
||||
|
||||
// `?int: Trait<?n>` goal
|
||||
tie_and_make_goal(&1, &a);
|
||||
|
||||
// If repeat expr checks structurally resolve the `?n`s before checking if the
|
||||
// element is a `const` then we would error here. Otherwise we avoid doing so,
|
||||
// integer fallback occurs, allowing `?int: Trait<?n>` goals to make progress,
|
||||
// inferring the repeat counts (to `2` but that doesn't matter as the element is `const`).
|
||||
}
|
||||
|
||||
fn const_item() {
|
||||
const MY_CONST: String = String::new();
|
||||
|
||||
// Deferred repeat expr `String; ?n`
|
||||
let a = [MY_CONST; _];
|
||||
//~^ ERROR: type annotations needed for `[String; _]`
|
||||
|
||||
// `?int: Trait<?n>` goal
|
||||
tie_and_make_goal(&1, &a);
|
||||
|
||||
// ... same as `const_block`
|
||||
}
|
||||
|
||||
fn assoc_const() {
|
||||
trait Dummy {
|
||||
const ASSOC: String;
|
||||
}
|
||||
impl Dummy for () {
|
||||
const ASSOC: String = String::new();
|
||||
}
|
||||
|
||||
// Deferred repeat expr `String; ?n`
|
||||
let a = [<() as Dummy>::ASSOC; _];
|
||||
//~^ ERROR: type annotations needed for `[String; _]`
|
||||
|
||||
// `?int: Trait<?n>` goal
|
||||
tie_and_make_goal(&1, &a);
|
||||
|
||||
// ... same as `const_block`
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,36 @@
|
||||
error[E0282]: type annotations needed for `[String; _]`
|
||||
--> $DIR/copy-check-const-element-uninferred-count.rs:22:9
|
||||
|
|
||||
LL | let a = [const { String::new() }; _];
|
||||
| ^ ----------------------- type must be known at this point
|
||||
|
|
||||
help: consider giving `a` an explicit type, where the value of const parameter `N` is specified
|
||||
|
|
||||
LL | let a: [_; N] = [const { String::new() }; _];
|
||||
| ++++++++
|
||||
|
||||
error[E0282]: type annotations needed for `[String; _]`
|
||||
--> $DIR/copy-check-const-element-uninferred-count.rs:38:9
|
||||
|
|
||||
LL | let a = [MY_CONST; _];
|
||||
| ^ -------- type must be known at this point
|
||||
|
|
||||
help: consider giving `a` an explicit type, where the value of const parameter `N` is specified
|
||||
|
|
||||
LL | let a: [_; N] = [MY_CONST; _];
|
||||
| ++++++++
|
||||
|
||||
error[E0282]: type annotations needed for `[String; _]`
|
||||
--> $DIR/copy-check-const-element-uninferred-count.rs:56:9
|
||||
|
|
||||
LL | let a = [<() as Dummy>::ASSOC; _];
|
||||
| ^ -------------------- type must be known at this point
|
||||
|
|
||||
help: consider giving `a` an explicit type, where the value of const parameter `N` is specified
|
||||
|
|
||||
LL | let a: [_; N] = [<() as Dummy>::ASSOC; _];
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
@ -1,8 +1,3 @@
|
||||
//@revisions: current gai
|
||||
//@[current] check-pass
|
||||
|
||||
#![cfg_attr(gai, feature(generic_arg_infer))]
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct Foo<T>(PhantomData<T>);
|
||||
@ -20,6 +15,6 @@ fn extract<T, const N: usize>(_: [Foo<T>; N]) -> T {
|
||||
|
||||
fn main() {
|
||||
let x = [Foo(PhantomData); 2];
|
||||
//[gai]~^ ERROR: type annotations needed
|
||||
_ = extract(x).max(2);
|
||||
//~^ ERROR: type annotations needed
|
||||
extract(x).max(2);
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
error[E0282]: type annotations needed for `[Foo<_>; 2]`
|
||||
--> $DIR/copy-inference-side-effects-are-lazy.rs:17:9
|
||||
|
|
||||
LL | let x = [Foo(PhantomData); 2];
|
||||
| ^
|
||||
LL |
|
||||
LL | extract(x).max(2);
|
||||
| ---------- type must be known at this point
|
||||
|
|
||||
help: consider giving `x` an explicit type, where the type for type parameter `T` is specified
|
||||
|
|
||||
LL | let x: [Foo<T>; 2] = [Foo(PhantomData); 2];
|
||||
| +++++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
Loading…
Reference in New Issue
Block a user