about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-05-04 19:18:21 +0200
committerGitHub <noreply@github.com>2023-05-04 19:18:21 +0200
commitc0ca84b006d86cfb76c9bc6c5e2c3805de073f5f (patch)
treecd25aedff57518a7334034d32795c5f7137a9b81
parentea0b6504faa95dd4bfb0666cbcb5dfcfe0591313 (diff)
parent7d9130f3b948400780fd8386e73d201df88d9ea9 (diff)
downloadrust-c0ca84b006d86cfb76c9bc6c5e2c3805de073f5f.tar.gz
rust-c0ca84b006d86cfb76c9bc6c5e2c3805de073f5f.zip
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`
-rw-r--r--compiler/rustc_borrowck/src/renumber.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs6
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs21
-rw-r--r--tests/ui/const-generics/sneaky-array-repeat-expr.rs2
-rw-r--r--tests/ui/const-generics/sneaky-array-repeat-expr.stderr20
-rw-r--r--tests/ui/consts/issue-50439.rs4
-rw-r--r--tests/ui/consts/issue-50439.stderr10
-rw-r--r--tests/ui/typeck/repeat-expr-checks-wf.rs10
-rw-r--r--tests/ui/typeck/repeat-expr-checks-wf.stderr12
10 files changed, 94 insertions, 6 deletions
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
@@ -109,6 +109,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> {
     }
 
     #[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;
         constant.literal = self.renumber_regions(literal, || RegionCtxt::Location(location));
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 43107db2923..dcabeb792be 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -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
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 8e8ca7874f5..6718605ed0b 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -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) {
             }
 
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<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() {
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<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
     }
 }
 
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 - !!(<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
 
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<T: Foo>() {
+    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`.