Rollup merge of #111100 - BoxyUwU:array_repeat_expr_wf, r=compiler-errors
check array type of repeat exprs is wf Fixes #111091 Also makes sure that we actually renumber regions in the length of repeat exprs which we previously weren't doing and would cause ICEs in `adt_const_params` + `generic_const_exprs` from attempting to prove the wf goals when the length was an unevaluated constant with `'erased` in the `ty` field of `Const` The duplicate errors are caused by the fact that `const_arg_to_const`/`array_len_to_const` in `FnCtxt` adds a `WellFormed` goal for the created `Const` which is also checked by the added `WellFormed(array_ty)`. I don't want to change this to just emit a `T: Sized` goal for the element type since that would ignore `ConstArgHasType` wf requirements and generally uncomfortable with the idea of trying to sync up `wf::obligations` for arrays and the code in hir typeck for repeat exprs. r? `@compiler-errors`
This commit is contained in:
commit
c0ca84b006
@ -108,6 +108,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> {
|
||||
debug!(?region);
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn visit_ty_const(&mut self, ct: &mut ty::Const<'tcx>, location: Location) {
|
||||
let old_ct = *ct;
|
||||
*ct = self.renumber_regions(old_ct, || RegionCtxt::Location(location));
|
||||
|
||||
debug!(?ct);
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) {
|
||||
let literal = constant.literal;
|
||||
|
@ -1801,6 +1801,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
Rvalue::Repeat(operand, len) => {
|
||||
self.check_operand(operand, location);
|
||||
|
||||
let array_ty = rvalue.ty(body.local_decls(), tcx);
|
||||
self.prove_predicate(
|
||||
ty::PredicateKind::WellFormed(array_ty.into()),
|
||||
Locations::Single(location),
|
||||
ConstraintCategory::Boring,
|
||||
);
|
||||
|
||||
// If the length cannot be evaluated we must assume that the length can be larger
|
||||
// than 1.
|
||||
// If the length is larger than 1, the repeat expression will need to copy the
|
||||
|
@ -1426,6 +1426,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
self.check_repeat_element_needs_copy_bound(element, count, element_ty);
|
||||
|
||||
self.register_wf_obligation(
|
||||
tcx.mk_array_with_const_len(t, count).into(),
|
||||
expr.span,
|
||||
traits::WellFormed(None),
|
||||
);
|
||||
|
||||
tcx.mk_array_with_const_len(t, count)
|
||||
}
|
||||
|
||||
|
@ -192,6 +192,14 @@ macro_rules! make_mir_visitor {
|
||||
self.super_constant(constant, location);
|
||||
}
|
||||
|
||||
fn visit_ty_const(
|
||||
&mut self,
|
||||
ct: $( & $mutability)? ty::Const<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
self.super_ty_const(ct, location);
|
||||
}
|
||||
|
||||
fn visit_span(
|
||||
&mut self,
|
||||
span: $(& $mutability)? Span,
|
||||
@ -625,8 +633,9 @@ macro_rules! make_mir_visitor {
|
||||
self.visit_operand(operand, location);
|
||||
}
|
||||
|
||||
Rvalue::Repeat(value, _) => {
|
||||
Rvalue::Repeat(value, ct) => {
|
||||
self.visit_operand(value, location);
|
||||
self.visit_ty_const($(&$mutability)? *ct, location);
|
||||
}
|
||||
|
||||
Rvalue::ThreadLocalRef(_) => {}
|
||||
@ -878,12 +887,20 @@ macro_rules! make_mir_visitor {
|
||||
self.visit_span($(& $mutability)? *span);
|
||||
drop(user_ty); // no visit method for this
|
||||
match literal {
|
||||
ConstantKind::Ty(_) => {}
|
||||
ConstantKind::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location),
|
||||
ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
||||
ConstantKind::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
||||
}
|
||||
}
|
||||
|
||||
fn super_ty_const(
|
||||
&mut self,
|
||||
_ct: $(& $mutability)? ty::Const<'tcx>,
|
||||
_location: Location,
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
fn super_span(&mut self, _span: $(& $mutability)? Span) {
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ impl<const N: usize> Trait<N> for () {
|
||||
pub const fn foo<const N: usize>() where (): Trait<N> {
|
||||
let bar = [(); <()>::Assoc];
|
||||
//~^ error: constant expression depends on a generic parameter
|
||||
//~| error: constant expression depends on a generic parameter
|
||||
}
|
||||
|
||||
trait Trait2<const N: usize> {
|
||||
@ -24,6 +25,7 @@ impl<const N: usize> Trait2<N> for () {
|
||||
pub const fn foo2<const N: usize>() where (): Trait2<N> {
|
||||
let bar2 = [(); <()>::Assoc2];
|
||||
//~^ error: constant expression depends on a generic parameter
|
||||
//~| error: constant expression depends on a generic parameter
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -7,12 +7,28 @@ LL | let bar = [(); <()>::Assoc];
|
||||
= note: this may fail depending on what value the parameter takes
|
||||
|
||||
error: constant expression depends on a generic parameter
|
||||
--> $DIR/sneaky-array-repeat-expr.rs:25:21
|
||||
--> $DIR/sneaky-array-repeat-expr.rs:11:15
|
||||
|
|
||||
LL | let bar = [(); <()>::Assoc];
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this may fail depending on what value the parameter takes
|
||||
|
||||
error: constant expression depends on a generic parameter
|
||||
--> $DIR/sneaky-array-repeat-expr.rs:26:21
|
||||
|
|
||||
LL | let bar2 = [(); <()>::Assoc2];
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: this may fail depending on what value the parameter takes
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: constant expression depends on a generic parameter
|
||||
--> $DIR/sneaky-array-repeat-expr.rs:26:16
|
||||
|
|
||||
LL | let bar2 = [(); <()>::Assoc2];
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this may fail depending on what value the parameter takes
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -22,7 +22,9 @@ impl<T: Sized> PinDropInternal for Bears<T> {
|
||||
where
|
||||
Self: ReflectDrop,
|
||||
{
|
||||
let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usize]; //~ ERROR constant expression depends on a generic parameter
|
||||
let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usize];
|
||||
//~^ ERROR constant expression depends on a generic parameter
|
||||
//~| ERROR constant expression depends on a generic parameter
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,5 +6,13 @@ LL | let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usi
|
||||
|
|
||||
= note: this may fail depending on what value the parameter takes
|
||||
|
||||
error: aborting due to previous error
|
||||
error: constant expression depends on a generic parameter
|
||||
--> $DIR/issue-50439.rs:25:17
|
||||
|
|
||||
LL | let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usize];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this may fail depending on what value the parameter takes
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
10
tests/ui/typeck/repeat-expr-checks-wf.rs
Normal file
10
tests/ui/typeck/repeat-expr-checks-wf.rs
Normal file
@ -0,0 +1,10 @@
|
||||
trait Foo {
|
||||
const ASSOC: [u8];
|
||||
}
|
||||
|
||||
fn bar<T: Foo>() {
|
||||
let a = [T::ASSOC; 2];
|
||||
//~^ ERROR: the size for values of type `[u8]` cannot be known at compilation time
|
||||
}
|
||||
|
||||
fn main() {}
|
12
tests/ui/typeck/repeat-expr-checks-wf.stderr
Normal file
12
tests/ui/typeck/repeat-expr-checks-wf.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/repeat-expr-checks-wf.rs:6:13
|
||||
|
|
||||
LL | let a = [T::ASSOC; 2];
|
||||
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `[u8]`
|
||||
= note: slice and array elements must have `Sized` type
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
Loading…
x
Reference in New Issue
Block a user