about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-05-08 07:14:57 +0000
committerbors <bors@rust-lang.org>2023-05-08 07:14:57 +0000
commitff8b9699518d4fe92f08629d91b3983e00f75282 (patch)
tree6f30c49ff0f86c95b8c08167ac88431c13b25511
parent833d5301d1ac47b2d3f0a71b67c5887f7481cc4e (diff)
parentaafe9b1e06b2027b04bc87389adef04f931823e6 (diff)
downloadrust-ff8b9699518d4fe92f08629d91b3983e00f75282.tar.gz
rust-ff8b9699518d4fe92f08629d91b3983e00f75282.zip
Auto merge of #14727 - HKalbasi:mir, r=HKalbasi
Lazy evaluate consts in `path_to_const`

fix #14275
-rw-r--r--crates/hir-ty/src/consteval.rs8
-rw-r--r--crates/hir-ty/src/infer.rs11
-rw-r--r--crates/hir-ty/src/infer/unify.rs45
-rw-r--r--crates/hir-ty/src/layout/tests.rs8
-rw-r--r--crates/hir-ty/src/lower.rs1
-rw-r--r--crates/hir-ty/src/tests/simple.rs20
6 files changed, 76 insertions, 17 deletions
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index 80b72768b3c..c3726905b67 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/crates/hir-ty/src/consteval.rs
@@ -76,6 +76,7 @@ pub(crate) fn path_to_const(
     mode: ParamLoweringMode,
     args_lazy: impl FnOnce() -> Generics,
     debruijn: DebruijnIndex,
+    expected_ty: Ty,
 ) -> Option<Const> {
     match resolver.resolve_path_in_value_ns_fully(db.upcast(), path) {
         Some(ValueNs::GenericParam(p)) => {
@@ -100,6 +101,10 @@ pub(crate) fn path_to_const(
             };
             Some(ConstData { ty, value }.intern(Interner))
         }
+        Some(ValueNs::ConstId(c)) => Some(intern_const_scalar(
+            ConstScalar::UnevaluatedConst(c.into(), Substitution::empty(Interner)),
+            expected_ty,
+        )),
         _ => None,
     }
 }
@@ -227,9 +232,10 @@ pub(crate) fn eval_to_const(
     debruijn: DebruijnIndex,
 ) -> Const {
     let db = ctx.db;
+    let infer = ctx.clone().resolve_all();
     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) {
+        if let Some(c) = path_to_const(db, resolver, p, mode, args, debruijn, infer[expr].clone()) {
             return c;
         }
     }
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 0e9b7206d04..32e87031438 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -17,7 +17,7 @@ use std::{convert::identity, ops::Index};
 
 use chalk_ir::{
     cast::Cast, fold::TypeFoldable, interner::HasInterner, DebruijnIndex, Mutability, Safety,
-    Scalar, TypeFlags,
+    Scalar, TyKind, TypeFlags,
 };
 use either::Either;
 use hir_def::{
@@ -44,7 +44,7 @@ use crate::{
     db::HirDatabase, fold_tys, infer::coerce::CoerceMany, lower::ImplTraitLoweringMode,
     static_lifetime, to_assoc_type_id, traits::FnTrait, AliasEq, AliasTy, ClosureId, DomainGoal,
     GenericArg, Goal, ImplTraitId, InEnvironment, Interner, ProjectionTy, RpitId, Substitution,
-    TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind,
+    TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt,
 };
 
 // This lint has a false positive here. See the link below for details.
@@ -118,7 +118,12 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
 /// This is appropriate to use only after type-check: it assumes
 /// that normalization will succeed, for example.
 pub(crate) fn normalize(db: &dyn HirDatabase, trait_env: Arc<TraitEnvironment>, ty: Ty) -> Ty {
-    if !ty.data(Interner).flags.intersects(TypeFlags::HAS_PROJECTION) {
+    // FIXME: TypeFlags::HAS_CT_PROJECTION is not implemented in chalk, so TypeFlags::HAS_PROJECTION only
+    // works for the type case, so we check array unconditionally. Remove the array part
+    // when the bug in chalk becomes fixed.
+    if !ty.data(Interner).flags.intersects(TypeFlags::HAS_PROJECTION)
+        && !matches!(ty.kind(Interner), TyKind::Array(..))
+    {
         return ty;
     }
     let mut table = unify::InferenceTable::new(db, trait_env);
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index b735a11adfb..21b962a48f2 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -15,11 +15,11 @@ use triomphe::Arc;
 
 use super::{InferOk, InferResult, InferenceContext, TypeError};
 use crate::{
-    db::HirDatabase, fold_tys, fold_tys_and_consts, static_lifetime, to_chalk_trait_id,
-    traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue, DebruijnIndex,
-    GenericArg, GenericArgData, Goal, Guidance, InEnvironment, InferenceVar, Interner, Lifetime,
-    ParamKind, ProjectionTy, ProjectionTyExt, Scalar, Solution, Substitution, TraitEnvironment, Ty,
-    TyBuilder, TyExt, TyKind, VariableKind,
+    db::HirDatabase, fold_tys_and_consts, static_lifetime, to_chalk_trait_id, traits::FnTrait,
+    AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue, DebruijnIndex, GenericArg,
+    GenericArgData, Goal, Guidance, InEnvironment, InferenceVar, Interner, Lifetime, ParamKind,
+    ProjectionTy, ProjectionTyExt, Scalar, Solution, Substitution, TraitEnvironment, Ty, TyBuilder,
+    TyExt, TyKind, VariableKind,
 };
 
 impl<'a> InferenceContext<'a> {
@@ -236,13 +236,36 @@ impl<'a> InferenceTable<'a> {
     where
         T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
     {
-        fold_tys(
+        fold_tys_and_consts(
             ty,
-            |ty, _| match ty.kind(Interner) {
-                TyKind::Alias(AliasTy::Projection(proj_ty)) => {
-                    self.normalize_projection_ty(proj_ty.clone())
-                }
-                _ => ty,
+            |e, _| match e {
+                Either::Left(ty) => Either::Left(match ty.kind(Interner) {
+                    TyKind::Alias(AliasTy::Projection(proj_ty)) => {
+                        self.normalize_projection_ty(proj_ty.clone())
+                    }
+                    _ => ty,
+                }),
+                Either::Right(c) => Either::Right(match &c.data(Interner).value {
+                    chalk_ir::ConstValue::Concrete(cc) => match &cc.interned {
+                        crate::ConstScalar::UnevaluatedConst(c_id, subst) => {
+                            // FIXME: Ideally here we should do everything that we do with type alias, i.e. adding a variable
+                            // and registering an obligation. But it needs chalk support, so we handle the most basic
+                            // case (a non associated const without generic parameters) manually.
+                            if subst.len(Interner) == 0 {
+                                if let Ok(eval) = self.db.const_eval((*c_id).into(), subst.clone())
+                                {
+                                    eval
+                                } else {
+                                    c
+                                }
+                            } else {
+                                c
+                            }
+                        }
+                        _ => c,
+                    },
+                    _ => c,
+                }),
             },
             DebruijnIndex::INNERMOST,
         )
diff --git a/crates/hir-ty/src/layout/tests.rs b/crates/hir-ty/src/layout/tests.rs
index 1502ab14cc7..e1038c0affe 100644
--- a/crates/hir-ty/src/layout/tests.rs
+++ b/crates/hir-ty/src/layout/tests.rs
@@ -354,6 +354,14 @@ fn niche_optimization() {
 }
 
 #[test]
+fn const_eval() {
+    size_and_align! {
+        const X: usize = 5;
+        struct Goal([i32; X]);
+    }
+}
+
+#[test]
 fn enums_with_discriminants() {
     size_and_align! {
         enum Goal {
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 4000ba5c14c..0f823580cba 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -2023,6 +2023,7 @@ pub(crate) fn const_or_path_to_chalk(
                 mode,
                 args,
                 debruijn,
+                expected_ty.clone(),
             )
             .unwrap_or_else(|| unknown_const(expected_ty))
         }
diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs
index 72e98138a34..e249cddc2fc 100644
--- a/crates/hir-ty/src/tests/simple.rs
+++ b/crates/hir-ty/src/tests/simple.rs
@@ -3529,14 +3529,30 @@ fn main() {
 
 #[test]
 fn issue_14275() {
-    // FIXME: evaluate const generic
     check_types(
         r#"
 struct Foo<const T: bool>;
 fn main() {
     const B: bool = false;
     let foo = Foo::<B>;
-      //^^^ Foo<_>
+      //^^^ Foo<false>
+}
+"#,
+    );
+    check_types(
+        r#"
+struct Foo<const T: bool>;
+impl Foo<true> {
+    fn foo(self) -> u8 { 2 }
+}
+impl Foo<false> {
+    fn foo(self) -> u16 { 5 }
+}
+fn main() {
+    const B: bool = false;
+    let foo: Foo<B> = Foo;
+    let x = foo.foo();
+      //^ u16
 }
 "#,
     );