about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-04-14 21:23:40 +0000
committerbors <bors@rust-lang.org>2020-04-14 21:23:40 +0000
commitd12f0304839e599d498b3faaa652336b273bdcc8 (patch)
tree427b504d391c002d04259643ba4695de2e84131a /src
parentedc02580e4e80476ac1ded2cc1008eaf8b8400e6 (diff)
parent8bb7b7bf9c781968b44732791d52962c9a9a00fe (diff)
downloadrust-d12f0304839e599d498b3faaa652336b273bdcc8.tar.gz
rust-d12f0304839e599d498b3faaa652336b273bdcc8.zip
Auto merge of #70452 - eddyb:repeat-expr-correct-generics-parent, r=nikomatsakis
typeck: always expose repeat count `AnonConst`s' parent in `generics_of`.

This should reduce some of the confusion around #43408, although, if you look at the changed test outputs (for the last commit), they all hit #68436, so nothing new will start compiling.

We can let counts of "repeat expressions" (`N` in `[x; N]`) always have the correct generics parenting, because they're always in a body, so nothing in the `where` clauses or `impl` trait/type of the parent can use it, and therefore no query cycles can occur.

<hr/>

Other potential candidates we might want to apply the same approach to, are:
* ~~(easy) `enum` discriminants (see also #70453)~~ opened #70825
* (trickier) array *type* (not *expression*) lengths nested in:
  * bodies
  * types of (associated or not) `const`/`static`
  * RHS of `type` aliases and associated `type`s
  * `fn` signatures

We should've done so from the start, the only reason we haven't is because I was squeamish about blacklisting some of the cases, but if we whitelist instead we should be fine.
Also, lazy normalization is taking forever :disappointed:.

<hr/>

There's also 5 other commits here:
* "typeck: track any errors injected during writeback and taint tables appropriately." - fixes #66706, as the next commit would otherwise trigger an ICE again
* "typeck: workaround WF hole in `to_const`." - its purpose is to emulate most of #70107's direct effect, at least in the case of repeat expressions, where the count always goes through `to_const`
  * this is the reason no new code can really compile, as the WF checks require #68436 to bypass
  * however, this has more test changes than I hoped, so it should be reviewed separately, and maybe even landed separately (as #70107 might take a while, as it's blocked on a few of my PRs)
* "ty: erase lifetimes early in `ty::Const::eval`." - first attempt at fixing #70773
  * still useful, I believe the new approach is less likely to cause issues long-term
  * I could take this out or move it into another PR if desired or someone else could take over (cc @skinny121)
* "traits/query/normalize: add some `debug!` logging for the result." - debugging aid for #70773
* "borrow_check/type_check: normalize `Aggregate` and `Call` operands." - actually fixes #70773

r? @nikomatsakis cc @pnkfelix @varkor @yodaldevoid @oli-obk @estebank
Diffstat (limited to 'src')
-rw-r--r--src/librustc_middle/ty/sty.rs58
-rw-r--r--src/librustc_mir/borrow_check/type_check/mod.rs2
-rw-r--r--src/librustc_trait_selection/traits/query/normalize.rs15
-rw-r--r--src/librustc_typeck/check/mod.rs27
-rw-r--r--src/librustc_typeck/check/writeback.rs20
-rw-r--r--src/librustc_typeck/collect.rs20
-rw-r--r--src/test/compile-fail/issue-52443.rs5
-rw-r--r--src/test/ui/associated-const/associated-const-type-parameter-arrays-2.rs2
-rw-r--r--src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr13
-rw-r--r--src/test/ui/const-generics/issues/issue-62456.rs3
-rw-r--r--src/test/ui/const-generics/issues/issue-62456.stderr10
-rw-r--r--src/test/ui/const-generics/issues/issue-62504.rs1
-rw-r--r--src/test/ui/const-generics/issues/issue-62504.stderr10
-rw-r--r--src/test/ui/const-generics/issues/issue-66205.rs3
-rw-r--r--src/test/ui/const-generics/issues/issue-66205.stderr10
-rw-r--r--src/test/ui/const-generics/issues/issue-67739.rs3
-rw-r--r--src/test/ui/const-generics/issues/issue-67739.stderr10
-rw-r--r--src/test/ui/consts/const-eval/issue-52442.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-52442.stderr20
-rw-r--r--src/test/ui/consts/issue-52432.rs1
-rw-r--r--src/test/ui/consts/issue-52432.stderr12
-rw-r--r--src/test/ui/consts/issue-70773-mir-typeck-lt-norm.rs15
-rw-r--r--src/test/ui/consts/too_generic_eval_ice.rs7
-rw-r--r--src/test/ui/consts/too_generic_eval_ice.stderr46
-rw-r--r--src/test/ui/issues/issue-39211.rs3
-rw-r--r--src/test/ui/issues/issue-39211.stderr9
-rw-r--r--src/test/ui/issues/issue-66706.rs13
-rw-r--r--src/test/ui/issues/issue-66706.stderr43
-rw-r--r--src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs1
-rw-r--r--src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr10
30 files changed, 276 insertions, 118 deletions
diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index 081e6f06b33..248a2095d0a 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -2339,43 +2339,41 @@ impl<'tcx> Const<'tcx> {
     /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
     /// unevaluated constant.
     pub fn eval(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> &Const<'tcx> {
-        let try_const_eval = |did, param_env: ParamEnv<'tcx>, substs, promoted| {
+        if let ConstKind::Unevaluated(did, substs, promoted) = self.val {
             let param_env_and_substs = param_env.with_reveal_all().and(substs);
 
-            // Avoid querying `tcx.const_eval(...)` with any inference vars.
-            if param_env_and_substs.needs_infer() {
-                return None;
-            }
+            // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
+            // also does later, but we want to do it before checking for
+            // inference variables.
+            let param_env_and_substs = tcx.erase_regions(&param_env_and_substs);
+
+            // HACK(eddyb) when the query key would contain inference variables,
+            // attempt using identity substs and `ParamEnv` instead, that will succeed
+            // when the expression doesn't depend on any parameters.
+            // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
+            // we can call `infcx.const_eval_resolve` which handles inference variables.
+            let param_env_and_substs = if param_env_and_substs.needs_infer() {
+                tcx.param_env(did).and(InternalSubsts::identity_for_item(tcx, did))
+            } else {
+                param_env_and_substs
+            };
 
+            // FIXME(eddyb) maybe the `const_eval_*` methods should take
+            // `ty::ParamEnvAnd<SubstsRef>` instead of having them separate.
             let (param_env, substs) = param_env_and_substs.into_parts();
-
             // try to resolve e.g. associated constants to their definition on an impl, and then
             // evaluate the const.
-            tcx.const_eval_resolve(param_env, did, substs, promoted, None)
-                .ok()
-                .map(|val| Const::from_value(tcx, val, self.ty))
-        };
-
-        match self.val {
-            ConstKind::Unevaluated(did, substs, promoted) => {
-                // HACK(eddyb) when substs contain inference variables,
-                // attempt using identity substs instead, that will succeed
-                // when the expression doesn't depend on any parameters.
-                // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
-                // we can call `infcx.const_eval_resolve` which handles inference variables.
-                if substs.needs_infer() {
-                    let identity_substs = InternalSubsts::identity_for_item(tcx, did);
-                    // The `ParamEnv` needs to match the `identity_substs`.
-                    let identity_param_env = tcx.param_env(did);
-                    match try_const_eval(did, identity_param_env, identity_substs, promoted) {
-                        Some(ct) => ct.subst(tcx, substs),
-                        None => self,
-                    }
-                } else {
-                    try_const_eval(did, param_env, substs, promoted).unwrap_or(self)
-                }
+            match tcx.const_eval_resolve(param_env, did, substs, promoted, None) {
+                // NOTE(eddyb) `val` contains no lifetimes/types/consts,
+                // and we use the original type, so nothing from `substs`
+                // (which may be identity substs, see above),
+                // can leak through `val` into the const we return.
+                Ok(val) => Const::from_value(tcx, val, self.ty),
+
+                Err(_) => self,
             }
-            _ => self,
+        } else {
+            self
         }
     }
 
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index a118fe2db71..4dc4fb6d8e9 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -1760,6 +1760,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
         for (n, (fn_arg, op_arg)) in sig.inputs().iter().zip(args).enumerate() {
             let op_arg_ty = op_arg.ty(body, self.tcx());
+            let op_arg_ty = self.normalize(op_arg_ty, term_location);
             let category = if from_hir_call {
                 ConstraintCategory::CallArgument
             } else {
@@ -2402,6 +2403,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
             };
             let operand_ty = operand.ty(body, tcx);
+            let operand_ty = self.normalize(operand_ty, location);
 
             if let Err(terr) = self.sub_types(
                 operand_ty,
diff --git a/src/librustc_trait_selection/traits/query/normalize.rs b/src/librustc_trait_selection/traits/query/normalize.rs
index 28d59b41e56..0da26abc330 100644
--- a/src/librustc_trait_selection/traits/query/normalize.rs
+++ b/src/librustc_trait_selection/traits/query/normalize.rs
@@ -59,11 +59,22 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
             anon_depth: 0,
         };
 
-        let value1 = value.fold_with(&mut normalizer);
+        let result = value.fold_with(&mut normalizer);
+        debug!(
+            "normalize::<{}>: result={:?} with {} obligations",
+            ::std::any::type_name::<T>(),
+            result,
+            normalizer.obligations.len(),
+        );
+        debug!(
+            "normalize::<{}>: obligations={:?}",
+            ::std::any::type_name::<T>(),
+            normalizer.obligations,
+        );
         if normalizer.error {
             Err(NoSolution)
         } else {
-            Ok(Normalized { value: value1, obligations: normalizer.obligations })
+            Ok(Normalized { value: result, obligations: normalizer.obligations })
         }
     }
 }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 2db397d5c74..3aff70390fa 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -3311,8 +3311,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     pub fn to_const(&self, ast_c: &hir::AnonConst) -> &'tcx ty::Const<'tcx> {
-        let c = self.tcx.hir().local_def_id(ast_c.hir_id).expect_local();
-        ty::Const::from_anon_const(self.tcx, c)
+        let const_def_id = self.tcx.hir().local_def_id(ast_c.hir_id).expect_local();
+        let c = ty::Const::from_anon_const(self.tcx, const_def_id);
+
+        // HACK(eddyb) emulate what a `WellFormedConst` obligation would do.
+        // This code should be replaced with the proper WF handling ASAP.
+        if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = c.val {
+            assert!(promoted.is_none());
+
+            // HACK(eddyb) let's hope these are always empty.
+            // let obligations = self.nominal_obligations(def_id, substs);
+            // self.out.extend(obligations);
+
+            let cause = traits::ObligationCause::new(
+                self.tcx.def_span(const_def_id.to_def_id()),
+                self.body_id,
+                traits::MiscObligation,
+            );
+            self.register_predicate(traits::Obligation::new(
+                cause,
+                self.param_env,
+                ty::Predicate::ConstEvaluatable(def_id, substs),
+            ));
+        }
+
+        c
     }
 
     // If the type given by the user has free regions, save it for later, since
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 146fc04bc27..f9100300e3a 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -75,7 +75,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         wbcx.tables.upvar_list =
             mem::replace(&mut self.tables.borrow_mut().upvar_list, Default::default());
 
-        wbcx.tables.tainted_by_errors = self.is_tainted_by_errors();
+        wbcx.tables.tainted_by_errors |= self.is_tainted_by_errors();
 
         debug!("writeback: tables for {:?} are {:#?}", item_def_id, wbcx.tables);
 
@@ -578,14 +578,21 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         }
     }
 
-    fn resolve<T>(&self, x: &T, span: &dyn Locatable) -> T
+    fn resolve<T>(&mut self, x: &T, span: &dyn Locatable) -> T
     where
         T: TypeFoldable<'tcx>,
     {
-        let x = x.fold_with(&mut Resolver::new(self.fcx, span, self.body));
+        let mut resolver = Resolver::new(self.fcx, span, self.body);
+        let x = x.fold_with(&mut resolver);
         if cfg!(debug_assertions) && x.needs_infer() {
             span_bug!(span.to_span(self.fcx.tcx), "writeback: `{:?}` has inference variables", x);
         }
+
+        // We may have introduced e.g. `ty::Error`, if inference failed, make sure
+        // to mark the `TypeckTables` as tainted in that case, so that downstream
+        // users of the tables don't produce extra errors, or worse, ICEs.
+        self.tables.tainted_by_errors |= resolver.replaced_with_error;
+
         x
     }
 }
@@ -613,6 +620,9 @@ struct Resolver<'cx, 'tcx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
     span: &'cx dyn Locatable,
     body: &'tcx hir::Body<'tcx>,
+
+    /// Set to `true` if any `Ty` or `ty::Const` had to be replaced with an `Error`.
+    replaced_with_error: bool,
 }
 
 impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
@@ -621,7 +631,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
         span: &'cx dyn Locatable,
         body: &'tcx hir::Body<'tcx>,
     ) -> Resolver<'cx, 'tcx> {
-        Resolver { tcx: fcx.tcx, infcx: fcx, span, body }
+        Resolver { tcx: fcx.tcx, infcx: fcx, span, body, replaced_with_error: false }
     }
 
     fn report_error(&self, t: Ty<'tcx>) {
@@ -644,6 +654,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
             Err(_) => {
                 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
                 self.report_error(t);
+                self.replaced_with_error = true;
                 self.tcx().types.err
             }
         }
@@ -661,6 +672,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
                 debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
                 // FIXME: we'd like to use `self.report_error`, but it doesn't yet
                 // accept a &'tcx ty::Const.
+                self.replaced_with_error = true;
                 self.tcx().consts.err
             }
         }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 43fea82608e..a327951b3b0 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1170,14 +1170,28 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
         }
         // FIXME(#43408) enable this always when we get lazy normalization.
         Node::AnonConst(_) => {
+            let parent_id = tcx.hir().get_parent_item(hir_id);
+            let parent_def_id = tcx.hir().local_def_id(parent_id);
+
             // HACK(eddyb) this provides the correct generics when
             // `feature(const_generics)` is enabled, so that const expressions
             // used with const generics, e.g. `Foo<{N+1}>`, can work at all.
             if tcx.features().const_generics {
-                let parent_id = tcx.hir().get_parent_item(hir_id);
-                Some(tcx.hir().local_def_id(parent_id))
+                Some(parent_def_id)
             } else {
-                None
+                let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
+                match parent_node {
+                    // HACK(eddyb) this provides the correct generics for repeat
+                    // expressions' count (i.e. `N` in `[x; N]`), as they shouldn't
+                    // be able to cause query cycle errors.
+                    Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
+                        if constant.hir_id == hir_id =>
+                    {
+                        Some(parent_def_id)
+                    }
+
+                    _ => None,
+                }
             }
         }
         Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
diff --git a/src/test/compile-fail/issue-52443.rs b/src/test/compile-fail/issue-52443.rs
index 3a022230b39..ad6f4970367 100644
--- a/src/test/compile-fail/issue-52443.rs
+++ b/src/test/compile-fail/issue-52443.rs
@@ -8,4 +8,9 @@ fn main() {
     //~| WARN denote infinite loops with
     [(); { for _ in 0usize.. {}; 0}];
     //~^ ERROR `for` is not allowed in a `const`
+    //~| ERROR calls in constants are limited to constant functions
+    //~| ERROR references in constants may only refer to immutable values
+    //~| ERROR calls in constants are limited to constant functions
+    //~| ERROR constant contains unimplemented expression type
+    //~| ERROR evaluation of constant value failed
 }
diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.rs b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.rs
index f1f82caf7d4..8fe79b97d9b 100644
--- a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.rs
+++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.rs
@@ -14,7 +14,7 @@ impl Foo for Def {
 
 pub fn test<A: Foo, B: Foo>() {
     let _array = [4; <A as Foo>::Y];
-    //~^ ERROR the trait bound `A: Foo` is not satisfied [E0277]
+    //~^ ERROR constant expression depends on a generic parameter
 }
 
 fn main() {
diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr
index 946a1f1a07a..0bc019b2dc8 100644
--- a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr
+++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr
@@ -1,17 +1,10 @@
-error[E0277]: the trait bound `A: Foo` is not satisfied
+error: constant expression depends on a generic parameter
   --> $DIR/associated-const-type-parameter-arrays-2.rs:16:22
    |
-LL |     const Y: usize;
-   |     --------------- required by `Foo::Y`
-...
 LL |     let _array = [4; <A as Foo>::Y];
-   |                      ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A`
+   |                      ^^^^^^^^^^^^^
    |
-help: consider further restricting this bound
-   |
-LL | pub fn test<A: Foo + Foo, B: Foo>() {
-   |                    ^^^^^
+   = note: this may fail depending on what value the parameter takes
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/issues/issue-62456.rs b/src/test/ui/const-generics/issues/issue-62456.rs
index 14b1190df0f..5d068eb7fc8 100644
--- a/src/test/ui/const-generics/issues/issue-62456.rs
+++ b/src/test/ui/const-generics/issues/issue-62456.rs
@@ -1,10 +1,9 @@
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
 
-// build-pass
-
 fn foo<const N: usize>() {
     let _ = [0u64; N + 1];
+    //~^ ERROR constant expression depends on a generic parameter
 }
 
 fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-62456.stderr b/src/test/ui/const-generics/issues/issue-62456.stderr
index fc26f68d235..96a07110e73 100644
--- a/src/test/ui/const-generics/issues/issue-62456.stderr
+++ b/src/test/ui/const-generics/issues/issue-62456.stderr
@@ -6,5 +6,13 @@ LL | #![feature(const_generics)]
    |
    = note: `#[warn(incomplete_features)]` on by default
 
-warning: 1 warning emitted
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-62456.rs:5:20
+   |
+LL |     let _ = [0u64; N + 1];
+   |                    ^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/const-generics/issues/issue-62504.rs b/src/test/ui/const-generics/issues/issue-62504.rs
index 212e16253f6..264e693a008 100644
--- a/src/test/ui/const-generics/issues/issue-62504.rs
+++ b/src/test/ui/const-generics/issues/issue-62504.rs
@@ -17,6 +17,7 @@ impl<const X: usize> ArrayHolder<X> {
     pub const fn new() -> Self {
         ArrayHolder([0; Self::SIZE])
         //~^ ERROR: mismatched types
+        //~| ERROR constant expression depends on a generic parameter
     }
 }
 
diff --git a/src/test/ui/const-generics/issues/issue-62504.stderr b/src/test/ui/const-generics/issues/issue-62504.stderr
index 4482389bbdd..a3a864f770c 100644
--- a/src/test/ui/const-generics/issues/issue-62504.stderr
+++ b/src/test/ui/const-generics/issues/issue-62504.stderr
@@ -7,6 +7,14 @@ LL |         ArrayHolder([0; Self::SIZE])
    = note: expected array `[u32; _]`
               found array `[u32; _]`
 
-error: aborting due to previous error
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-62504.rs:18:25
+   |
+LL |         ArrayHolder([0; Self::SIZE])
+   |                         ^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issues/issue-66205.rs b/src/test/ui/const-generics/issues/issue-66205.rs
index 2e47b4d1882..73ba4fa6aae 100644
--- a/src/test/ui/const-generics/issues/issue-66205.rs
+++ b/src/test/ui/const-generics/issues/issue-66205.rs
@@ -1,10 +1,9 @@
-// check-pass
-
 #![allow(incomplete_features, dead_code, unconditional_recursion)]
 #![feature(const_generics)]
 
 fn fact<const N: usize>() {
     fact::<{ N - 1 }>();
+    //~^ ERROR constant expression depends on a generic parameter
 }
 
 fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-66205.stderr b/src/test/ui/const-generics/issues/issue-66205.stderr
new file mode 100644
index 00000000000..2bd013e8b41
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-66205.stderr
@@ -0,0 +1,10 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-66205.rs:5:12
+   |
+LL |     fact::<{ N - 1 }>();
+   |            ^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-67739.rs b/src/test/ui/const-generics/issues/issue-67739.rs
index 3d657b0947b..c8ee1821239 100644
--- a/src/test/ui/const-generics/issues/issue-67739.rs
+++ b/src/test/ui/const-generics/issues/issue-67739.rs
@@ -1,7 +1,5 @@
 // Regression test for #67739
 
-// check-pass
-
 #![allow(incomplete_features)]
 #![feature(const_generics)]
 
@@ -12,6 +10,7 @@ pub trait Trait {
 
     fn associated_size(&self) -> usize {
         [0u8; mem::size_of::<Self::Associated>()];
+        //~^ ERROR constant expression depends on a generic parameter
         0
     }
 }
diff --git a/src/test/ui/const-generics/issues/issue-67739.stderr b/src/test/ui/const-generics/issues/issue-67739.stderr
new file mode 100644
index 00000000000..27a56b8eb02
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-67739.stderr
@@ -0,0 +1,10 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-67739.rs:12:15
+   |
+LL |         [0u8; mem::size_of::<Self::Associated>()];
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-eval/issue-52442.rs b/src/test/ui/consts/const-eval/issue-52442.rs
index df4cc8e3026..07fb491015a 100644
--- a/src/test/ui/consts/const-eval/issue-52442.rs
+++ b/src/test/ui/consts/const-eval/issue-52442.rs
@@ -1,4 +1,6 @@
 fn main() {
     [();  { &loop { break } as *const _ as usize } ];
     //~^ ERROR `loop` is not allowed in a `const`
+    //~| ERROR casting pointers to integers in constants is unstable
+    //~| ERROR evaluation of constant value failed
 }
diff --git a/src/test/ui/consts/const-eval/issue-52442.stderr b/src/test/ui/consts/const-eval/issue-52442.stderr
index 0ea974f1f66..eda2dbf0b6b 100644
--- a/src/test/ui/consts/const-eval/issue-52442.stderr
+++ b/src/test/ui/consts/const-eval/issue-52442.stderr
@@ -7,6 +7,22 @@ LL |     [();  { &loop { break } as *const _ as usize } ];
    = note: see issue #52000 <https://github.com/rust-lang/rust/issues/52000> for more information
    = help: add `#![feature(const_loop)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: casting pointers to integers in constants is unstable
+  --> $DIR/issue-52442.rs:2:13
+   |
+LL |     [();  { &loop { break } as *const _ as usize } ];
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
+   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-52442.rs:2:13
+   |
+LL |     [();  { &loop { break } as *const _ as usize } ];
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants
+
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
+Some errors have detailed explanations: E0080, E0658.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/issue-52432.rs b/src/test/ui/consts/issue-52432.rs
index ded79458e63..d719bf1b971 100644
--- a/src/test/ui/consts/issue-52432.rs
+++ b/src/test/ui/consts/issue-52432.rs
@@ -6,4 +6,5 @@ fn main() {
     //~| ERROR: type annotations needed
     [(); &(static || {}) as *const _ as usize];
     //~^ ERROR: closures cannot be static
+    //~| ERROR evaluation of constant value failed
 }
diff --git a/src/test/ui/consts/issue-52432.stderr b/src/test/ui/consts/issue-52432.stderr
index d25c11138f4..e9539d24118 100644
--- a/src/test/ui/consts/issue-52432.stderr
+++ b/src/test/ui/consts/issue-52432.stderr
@@ -16,7 +16,13 @@ error[E0282]: type annotations needed
 LL |     [(); &(static |x| {}) as *const _ as usize];
    |                    ^ consider giving this closure parameter a type
 
-error: aborting due to 3 previous errors
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-52432.rs:7:10
+   |
+LL |     [(); &(static || {}) as *const _ as usize];
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants
+
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0282, E0697.
-For more information about an error, try `rustc --explain E0282`.
+Some errors have detailed explanations: E0080, E0282, E0697.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/issue-70773-mir-typeck-lt-norm.rs b/src/test/ui/consts/issue-70773-mir-typeck-lt-norm.rs
new file mode 100644
index 00000000000..07af8310424
--- /dev/null
+++ b/src/test/ui/consts/issue-70773-mir-typeck-lt-norm.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+const HASH_LEN: usize = 20;
+struct Hash([u8; HASH_LEN]);
+fn init_hash(_: &mut [u8; HASH_LEN]) {}
+
+fn foo<'a>() -> &'a () {
+    Hash([0; HASH_LEN]);
+    init_hash(&mut [0; HASH_LEN]);
+    &()
+}
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/consts/too_generic_eval_ice.rs b/src/test/ui/consts/too_generic_eval_ice.rs
index 7e4d4dbe446..3ea5f88f07d 100644
--- a/src/test/ui/consts/too_generic_eval_ice.rs
+++ b/src/test/ui/consts/too_generic_eval_ice.rs
@@ -4,10 +4,9 @@ impl<A, B> Foo<A, B> {
     const HOST_SIZE: usize = std::mem::size_of::<B>();
 
     pub fn crash() -> bool {
-        [5; Self::HOST_SIZE] == [6; 0] //~ ERROR no associated item named `HOST_SIZE`
-        //~^ the size for values of type `A` cannot be known
-        //~| the size for values of type `B` cannot be known
-        //~| binary operation `==` cannot be applied to type `[{integer}; _]`
+        [5; Self::HOST_SIZE] == [6; 0]
+        //~^ ERROR constant expression depends on a generic parameter
+        //~| ERROR binary operation `==` cannot be applied to type `[{integer}; _]`
     }
 }
 
diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr
index 8b57d237516..8b29c533bcc 100644
--- a/src/test/ui/consts/too_generic_eval_ice.stderr
+++ b/src/test/ui/consts/too_generic_eval_ice.stderr
@@ -1,45 +1,10 @@
-error[E0599]: no associated item named `HOST_SIZE` found for struct `Foo<A, B>` in the current scope
-  --> $DIR/too_generic_eval_ice.rs:7:19
-   |
-LL | pub struct Foo<A, B>(A, B);
-   | --------------------------- associated item `HOST_SIZE` not found for this
-...
-LL |         [5; Self::HOST_SIZE] == [6; 0]
-   |                   ^^^^^^^^^ associated item not found in `Foo<A, B>`
-   |
-   = note: the method `HOST_SIZE` exists but the following trait bounds were not satisfied:
-           `A: std::marker::Sized`
-           `B: std::marker::Sized`
-
-error[E0277]: the size for values of type `A` cannot be known at compilation time
-  --> $DIR/too_generic_eval_ice.rs:7:13
-   |
-LL | pub struct Foo<A, B>(A, B);
-   |                - required by this bound in `Foo`
-LL | 
-LL | impl<A, B> Foo<A, B> {
-   |      - this type parameter needs to be `std::marker::Sized`
-...
-LL |         [5; Self::HOST_SIZE] == [6; 0]
-   |             ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `std::marker::Sized` is not implemented for `A`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
-
-error[E0277]: the size for values of type `B` cannot be known at compilation time
+error: constant expression depends on a generic parameter
   --> $DIR/too_generic_eval_ice.rs:7:13
    |
-LL | pub struct Foo<A, B>(A, B);
-   |                   - required by this bound in `Foo`
-LL | 
-LL | impl<A, B> Foo<A, B> {
-   |         - this type parameter needs to be `std::marker::Sized`
-...
 LL |         [5; Self::HOST_SIZE] == [6; 0]
-   |             ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |             ^^^^^^^^^^^^^^^
    |
-   = help: the trait `std::marker::Sized` is not implemented for `B`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: this may fail depending on what value the parameter takes
 
 error[E0369]: binary operation `==` cannot be applied to type `[{integer}; _]`
   --> $DIR/too_generic_eval_ice.rs:7:30
@@ -49,7 +14,6 @@ LL |         [5; Self::HOST_SIZE] == [6; 0]
    |         |
    |         [{integer}; _]
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0277, E0369, E0599.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/issues/issue-39211.rs b/src/test/ui/issues/issue-39211.rs
index db101ae248c..c7b6f1d58f3 100644
--- a/src/test/ui/issues/issue-39211.rs
+++ b/src/test/ui/issues/issue-39211.rs
@@ -8,7 +8,8 @@ trait Mat {
 }
 
 fn m<M: Mat>() {
-    let a = [3; M::Row::DIM]; //~ ERROR associated type `Row` not found for `M`
+    let a = [3; M::Row::DIM];
+    //~^ ERROR constant expression depends on a generic parameter
 }
 fn main() {
 }
diff --git a/src/test/ui/issues/issue-39211.stderr b/src/test/ui/issues/issue-39211.stderr
index c14c663e5a1..c555983ea68 100644
--- a/src/test/ui/issues/issue-39211.stderr
+++ b/src/test/ui/issues/issue-39211.stderr
@@ -1,9 +1,10 @@
-error[E0220]: associated type `Row` not found for `M`
-  --> $DIR/issue-39211.rs:11:20
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-39211.rs:11:17
    |
 LL |     let a = [3; M::Row::DIM];
-   |                    ^^^ associated type `Row` not found
+   |                 ^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0220`.
diff --git a/src/test/ui/issues/issue-66706.rs b/src/test/ui/issues/issue-66706.rs
index 5e64f63d533..02305191f6e 100644
--- a/src/test/ui/issues/issue-66706.rs
+++ b/src/test/ui/issues/issue-66706.rs
@@ -10,4 +10,17 @@ fn b() {
     //~^ ERROR expected identifier, found reserved identifier `_`
 }
 
+fn c() {
+    [0; [|&_: _ &_| {}; 0 ].len()]
+    //~^ ERROR expected `,`, found `&`
+    //~| ERROR mismatched types
+}
+
+fn d() {
+    [0; match [|f @ &ref _| () ] {} ]
+    //~^ ERROR expected identifier, found reserved identifier `_`
+    //~| ERROR `match` is not allowed in a `const`
+    //~| ERROR mismatched types
+}
+
 fn main() {}
diff --git a/src/test/ui/issues/issue-66706.stderr b/src/test/ui/issues/issue-66706.stderr
index 6d290bccc7d..ea461cc5d03 100644
--- a/src/test/ui/issues/issue-66706.stderr
+++ b/src/test/ui/issues/issue-66706.stderr
@@ -12,6 +12,29 @@ error: expected identifier, found reserved identifier `_`
 LL |     [0; [|f @ &ref _| {} ; 0 ].len() ];
    |                    ^ expected identifier, found reserved identifier
 
+error: expected `,`, found `&`
+  --> $DIR/issue-66706.rs:14:17
+   |
+LL |     [0; [|&_: _ &_| {}; 0 ].len()]
+   |                -^ expected `,`
+   |                |
+   |                help: missing `,`
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-66706.rs:20:26
+   |
+LL |     [0; match [|f @ &ref _| () ] {} ]
+   |                          ^ expected identifier, found reserved identifier
+
+error[E0658]: `match` is not allowed in a `const`
+  --> $DIR/issue-66706.rs:20:9
+   |
+LL |     [0; match [|f @ &ref _| () ] {} ]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #49146 <https://github.com/rust-lang/rust/issues/49146> for more information
+   = help: add `#![feature(const_if_match)]` to the crate attributes to enable
+
 error[E0282]: type annotations needed
   --> $DIR/issue-66706.rs:2:11
    |
@@ -26,7 +49,23 @@ LL | fn a() {
 LL |     [0; [|_: _ &_| ()].len()]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]`
 
-error: aborting due to 4 previous errors
+error[E0308]: mismatched types
+  --> $DIR/issue-66706.rs:14:5
+   |
+LL | fn c() {
+   |        - help: try adding a return type: `-> [{integer}; _]`
+LL |     [0; [|&_: _ &_| {}; 0 ].len()]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-66706.rs:20:5
+   |
+LL | fn d() {
+   |        - help: try adding a return type: `-> [{integer}; _]`
+LL |     [0; match [|f @ &ref _| () ] {} ]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]`
+
+error: aborting due to 9 previous errors
 
-Some errors have detailed explanations: E0282, E0308.
+Some errors have detailed explanations: E0282, E0308, E0658.
 For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs
index 2c5257ce063..6ac3eb53cb3 100644
--- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs
+++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs
@@ -19,4 +19,5 @@ impl TraitB for B { //~ ERROR not all trait items implemented, missing: `MyA`
 
 fn main() {
     let _ = [0; B::VALUE];
+    //~^ ERROR constant expression depends on a generic parameter
 }
diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr
index 8ae0f8b804c..175e6b0eaa0 100644
--- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr
+++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr
@@ -13,7 +13,15 @@ LL |     type MyA: TraitA;
 LL | impl TraitB for B {
    | ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation
 
-error: aborting due to 2 previous errors
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-69602-type-err-during-codegen-ice.rs:21:17
+   |
+LL |     let _ = [0; B::VALUE];
+   |                 ^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0046, E0437.
 For more information about an error, try `rustc --explain E0046`.