From c04106f9f13cb6e8f73aff8ea0888e94631dc47a Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 2 May 2023 18:04:52 +0100 Subject: [PATCH 1/2] check array type of repeat exprs is wf --- compiler/rustc_borrowck/src/renumber.rs | 8 +++++++ compiler/rustc_borrowck/src/type_check/mod.rs | 7 ++++++ compiler/rustc_hir_typeck/src/expr.rs | 6 +++++ compiler/rustc_middle/src/mir/visit.rs | 23 +++++++++++++++++-- .../sneaky-array-repeat-expr.rs | 2 ++ .../sneaky-array-repeat-expr.stderr | 20 ++++++++++++++-- tests/ui/consts/issue-50439.rs | 4 +++- tests/ui/consts/issue-50439.stderr | 10 +++++++- tests/ui/typeck/repeat-expr-checks-wf.rs | 10 ++++++++ tests/ui/typeck/repeat-expr-checks-wf.stderr | 12 ++++++++++ 10 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 tests/ui/typeck/repeat-expr-checks-wf.rs create mode 100644 tests/ui/typeck/repeat-expr-checks-wf.stderr diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index 22de7549e94..4389d2b60bc 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -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; diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 601589480d1..6eb67644741 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1803,6 +1803,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 diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 047d8a82bfc..bba049c3819 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -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) } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 0a9fcd898b9..8e379e0baac 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -192,6 +192,15 @@ macro_rules! make_mir_visitor { 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 @@ 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(ct, location); } Rvalue::ThreadLocalRef(_) => {} @@ -878,12 +888,21 @@ 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(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) { } diff --git a/tests/ui/const-generics/sneaky-array-repeat-expr.rs b/tests/ui/const-generics/sneaky-array-repeat-expr.rs index b147c246bda..cd1607608a6 100644 --- a/tests/ui/const-generics/sneaky-array-repeat-expr.rs +++ b/tests/ui/const-generics/sneaky-array-repeat-expr.rs @@ -10,6 +10,7 @@ impl Trait for () { pub const fn foo() where (): Trait { let bar = [(); <()>::Assoc]; //~^ error: constant expression depends on a generic parameter + //~| error: constant expression depends on a generic parameter } trait Trait2 { @@ -24,6 +25,7 @@ impl Trait2 for () { pub const fn foo2() where (): Trait2 { let bar2 = [(); <()>::Assoc2]; //~^ error: constant expression depends on a generic parameter + //~| error: constant expression depends on a generic parameter } fn main() { diff --git a/tests/ui/const-generics/sneaky-array-repeat-expr.stderr b/tests/ui/const-generics/sneaky-array-repeat-expr.stderr index 5c77375d399..e532f27a10d 100644 --- a/tests/ui/const-generics/sneaky-array-repeat-expr.stderr +++ b/tests/ui/const-generics/sneaky-array-repeat-expr.stderr @@ -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 diff --git a/tests/ui/consts/issue-50439.rs b/tests/ui/consts/issue-50439.rs index 0be7c405473..d42347e136e 100644 --- a/tests/ui/consts/issue-50439.rs +++ b/tests/ui/consts/issue-50439.rs @@ -22,7 +22,9 @@ impl PinDropInternal for Bears { where Self: ReflectDrop, { - let _ = [(); 0 - !!( as ReflectDrop>::REFLECT_DROP) as usize]; //~ ERROR constant expression depends on a generic parameter + let _ = [(); 0 - !!( as ReflectDrop>::REFLECT_DROP) as usize]; + //~^ ERROR constant expression depends on a generic parameter + //~| ERROR constant expression depends on a generic parameter } } diff --git a/tests/ui/consts/issue-50439.stderr b/tests/ui/consts/issue-50439.stderr index 3fbdf33b2d8..7a8cd45ecc7 100644 --- a/tests/ui/consts/issue-50439.stderr +++ b/tests/ui/consts/issue-50439.stderr @@ -6,5 +6,13 @@ LL | let _ = [(); 0 - !!( 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 - !!( as ReflectDrop>::REFLECT_DROP) as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/repeat-expr-checks-wf.rs b/tests/ui/typeck/repeat-expr-checks-wf.rs new file mode 100644 index 00000000000..b8a2a0ceb58 --- /dev/null +++ b/tests/ui/typeck/repeat-expr-checks-wf.rs @@ -0,0 +1,10 @@ +trait Foo { + const ASSOC: [u8]; +} + +fn bar() { + let a = [T::ASSOC; 2]; + //~^ ERROR: the size for values of type `[u8]` cannot be known at compilation time +} + +fn main() {} diff --git a/tests/ui/typeck/repeat-expr-checks-wf.stderr b/tests/ui/typeck/repeat-expr-checks-wf.stderr new file mode 100644 index 00000000000..a821088a4b3 --- /dev/null +++ b/tests/ui/typeck/repeat-expr-checks-wf.stderr @@ -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`. From 7d9130f3b948400780fd8386e73d201df88d9ea9 Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 4 May 2023 11:22:11 +0100 Subject: [PATCH 2/2] do not allow rustc::pass_by_value lint --- compiler/rustc_middle/src/mir/visit.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 8e379e0baac..6a7e49cbec6 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -192,10 +192,9 @@ macro_rules! make_mir_visitor { self.super_constant(constant, location); } - #[allow(rustc::pass_by_value)] fn visit_ty_const( &mut self, - ct: & $($mutability)? ty::Const<'tcx>, + ct: $( & $mutability)? ty::Const<'tcx>, location: Location, ) { self.super_ty_const(ct, location); @@ -636,7 +635,7 @@ macro_rules! make_mir_visitor { Rvalue::Repeat(value, ct) => { self.visit_operand(value, location); - self.visit_ty_const(ct, location); + self.visit_ty_const($(&$mutability)? *ct, location); } Rvalue::ThreadLocalRef(_) => {} @@ -888,16 +887,15 @@ macro_rules! make_mir_visitor { self.visit_span($(& $mutability)? *span); drop(user_ty); // no visit method for this match literal { - ConstantKind::Ty(ct) => self.visit_ty_const(ct, location), + 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)), } } - #[allow(rustc::pass_by_value)] fn super_ty_const( &mut self, - _ct: & $($mutability)? ty::Const<'tcx>, + _ct: $(& $mutability)? ty::Const<'tcx>, _location: Location, ) {