about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-ty/src/consteval.rs18
-rw-r--r--crates/hir-ty/src/tests/regression.rs12
2 files changed, 27 insertions, 3 deletions
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index 0348680e5da..b4bbae6175a 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/crates/hir-ty/src/consteval.rs
@@ -3,7 +3,8 @@
 use base_db::CrateId;
 use chalk_ir::{cast::Cast, BoundVar, DebruijnIndex};
 use hir_def::{
-    hir::Expr,
+    body::Body,
+    hir::{Expr, ExprId},
     path::Path,
     resolver::{Resolver, ValueNs},
     type_ref::LiteralConstRef,
@@ -280,7 +281,7 @@ pub(crate) fn const_eval_discriminant_variant(
 // get an `InferenceResult` instead of an `InferenceContext`. And we should remove `ctx.clone().resolve_all()` here
 // and make this function private. See the fixme comment on `InferenceContext::resolve_all`.
 pub(crate) fn eval_to_const(
-    expr: Idx<Expr>,
+    expr: ExprId,
     mode: ParamLoweringMode,
     ctx: &mut InferenceContext<'_>,
     args: impl FnOnce() -> Generics,
@@ -288,13 +289,24 @@ pub(crate) fn eval_to_const(
 ) -> Const {
     let db = ctx.db;
     let infer = ctx.clone().resolve_all();
+    fn has_closure(body: &Body, expr: ExprId) -> bool {
+        if matches!(body[expr], Expr::Closure { .. }) {
+            return true;
+        }
+        let mut r = false;
+        body[expr].walk_child_exprs(|idx| r |= has_closure(body, idx));
+        r
+    }
+    if has_closure(&ctx.body, expr) {
+        // Type checking clousres need an isolated body (See the above FIXME). Bail out early to prevent panic.
+        return unknown_const(infer[expr].clone());
+    }
     if let Expr::Path(p) = &ctx.body.exprs[expr] {
         let resolver = &ctx.resolver;
         if let Some(c) = path_to_const(db, resolver, p, mode, args, debruijn, infer[expr].clone()) {
             return c;
         }
     }
-    let infer = ctx.clone().resolve_all();
     if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, &ctx.body, &infer, expr) {
         if let Ok(result) = interpret_mir(db, Arc::new(mir_body), true, None).0 {
             return result;
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index 6ea059065e9..35079e70946 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -2000,3 +2000,15 @@ fn test() {
 "#,
     );
 }
+
+#[test]
+fn rustc_test_issue_52437() {
+    check_types(
+        r#"
+    fn main() {
+        let x = [(); &(&'static: loop { |x| {}; }) as *const _ as usize]
+          //^ [(); _]
+    }
+    "#,
+    );
+}