check array type of repeat exprs is wf

This commit is contained in:
Boxy 2023-05-02 18:04:52 +01:00
parent 6f8c0557e0
commit c04106f9f1
10 changed files with 96 additions and 6 deletions

View file

@ -108,6 +108,14 @@ fn visit_region(&mut self, region: &mut ty::Region<'tcx>, location: Location) {
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;

View file

@ -1803,6 +1803,13 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
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

View file

@ -1426,6 +1426,12 @@ fn check_expr_repeat(
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)
}

View file

@ -192,6 +192,15 @@ fn visit_constant(
self.super_constant(constant, location);
}
#[allow(rustc::pass_by_value)]
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 +634,9 @@ fn super_rvalue(&mut self,
self.visit_operand(operand, location);
}
Rvalue::Repeat(value, _) => {
Rvalue::Repeat(value, ct) => {
self.visit_operand(value, location);
self.visit_ty_const(ct, location);
}
Rvalue::ThreadLocalRef(_) => {}
@ -878,12 +888,21 @@ fn super_constant(
self.visit_span($(& $mutability)? *span);
drop(user_ty); // no visit method for this
match literal {
ConstantKind::Ty(_) => {}
ConstantKind::Ty(ct) => self.visit_ty_const(ct, location),
ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
ConstantKind::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
}
}
#[allow(rustc::pass_by_value)]
fn super_ty_const(
&mut self,
_ct: & $($mutability)? ty::Const<'tcx>,
_location: Location,
) {
}
fn super_span(&mut self, _span: $(& $mutability)? Span) {
}

View file

@ -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() {

View file

@ -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

View file

@ -22,7 +22,9 @@ fn is_valid()
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
}
}

View file

@ -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

View 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() {}

View 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`.