about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/base-db/src/fixture.rs6
-rw-r--r--crates/base-db/src/input.rs21
-rw-r--r--crates/hir-def/src/body.rs20
-rw-r--r--crates/hir-def/src/body/pretty.rs1
-rw-r--r--crates/hir-def/src/db.rs20
-rw-r--r--crates/hir-def/src/expander.rs2
-rw-r--r--crates/hir-def/src/hir.rs4
-rw-r--r--crates/hir-def/src/hir/type_ref.rs115
-rw-r--r--crates/hir-def/src/lib.rs214
-rw-r--r--crates/hir-def/src/path.rs4
-rw-r--r--crates/hir-def/src/path/lower.rs4
-rw-r--r--crates/hir-def/src/resolver.rs23
-rw-r--r--crates/hir-expand/src/ast_id_map.rs1
-rw-r--r--crates/hir-ty/src/chalk_db.rs2
-rw-r--r--crates/hir-ty/src/consteval.rs24
-rw-r--r--crates/hir-ty/src/consteval/tests.rs11
-rw-r--r--crates/hir-ty/src/db.rs1
-rw-r--r--crates/hir-ty/src/diagnostics/unsafe_check.rs7
-rw-r--r--crates/hir-ty/src/infer.rs42
-rw-r--r--crates/hir-ty/src/infer/expr.rs1
-rw-r--r--crates/hir-ty/src/infer/path.rs17
-rw-r--r--crates/hir-ty/src/interner.rs2
-rw-r--r--crates/hir-ty/src/layout/tests.rs35
-rw-r--r--crates/hir-ty/src/lower.rs117
-rw-r--r--crates/hir-ty/src/method_resolution.rs2
-rw-r--r--crates/hir-ty/src/mir/lower.rs1
-rw-r--r--crates/hir-ty/src/mir/pretty.rs3
-rw-r--r--crates/hir-ty/src/tests.rs2
-rw-r--r--crates/hir-ty/src/tests/regression.rs23
-rw-r--r--crates/hir-ty/src/tests/simple.rs32
-rw-r--r--crates/hir-ty/src/utils.rs30
-rw-r--r--crates/hir/src/from_id.rs3
-rw-r--r--crates/hir/src/lib.rs33
-rw-r--r--crates/hir/src/semantics.rs8
-rw-r--r--crates/hir/src/source_analyzer.rs7
-rw-r--r--crates/hir/src/symbols.rs1
-rw-r--r--crates/ide-assists/src/handlers/extract_type_alias.rs2
-rw-r--r--crates/ide-db/src/search.rs2
-rw-r--r--crates/ide/src/inlay_hints/chaining.rs12
-rw-r--r--crates/parser/src/grammar/types.rs2
-rw-r--r--crates/parser/test_data/parser/inline/ok/0017_array_type.rast5
-rw-r--r--crates/parser/test_data/parser/ok/0030_traits.rast5
-rw-r--r--crates/parser/test_data/parser/ok/0043_complex_assignment.rast5
-rw-r--r--crates/project-model/src/workspace.rs6
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs21
-rw-r--r--crates/syntax/rust.ungram2
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs2
-rw-r--r--crates/test-utils/src/minicore.rs27
48 files changed, 716 insertions, 214 deletions
diff --git a/crates/base-db/src/fixture.rs b/crates/base-db/src/fixture.rs
index 5b11343173b..d3abc3870b7 100644
--- a/crates/base-db/src/fixture.rs
+++ b/crates/base-db/src/fixture.rs
@@ -215,7 +215,7 @@ impl ChangeFixture {
                 None,
                 default_cfg,
                 Default::default(),
-                Env::default(),
+                Env::new_for_test_fixture(),
                 false,
                 CrateOrigin::Local { repo: None, name: None },
                 default_target_data_layout
@@ -259,7 +259,7 @@ impl ChangeFixture {
                 None,
                 Default::default(),
                 Default::default(),
-                Env::default(),
+                Env::new_for_test_fixture(),
                 false,
                 CrateOrigin::Lang(LangCrateOrigin::Core),
                 target_layout.clone(),
@@ -298,7 +298,7 @@ impl ChangeFixture {
                 None,
                 Default::default(),
                 Default::default(),
-                Env::default(),
+                Env::new_for_test_fixture(),
                 true,
                 CrateOrigin::Local { repo: None, name: None },
                 target_layout,
diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs
index e8d521b42f8..64b026f4da5 100644
--- a/crates/base-db/src/input.rs
+++ b/crates/base-db/src/input.rs
@@ -151,6 +151,12 @@ pub enum CrateOrigin {
     Lang(LangCrateOrigin),
 }
 
+impl CrateOrigin {
+    pub fn is_local(&self) -> bool {
+        matches!(self, CrateOrigin::Local { .. })
+    }
+}
+
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub enum LangCrateOrigin {
     Alloc,
@@ -333,6 +339,17 @@ pub struct Env {
     entries: FxHashMap<String, String>,
 }
 
+impl Env {
+    pub fn new_for_test_fixture() -> Self {
+        Env {
+            entries: FxHashMap::from_iter([(
+                String::from("__ra_is_test_fixture"),
+                String::from("__ra_is_test_fixture"),
+            )]),
+        }
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Dependency {
     pub crate_id: CrateId,
@@ -456,6 +473,10 @@ impl CrateGraph {
         self.arena.iter().map(|(idx, _)| idx)
     }
 
+    pub fn iter_mut(&mut self) -> impl Iterator<Item = (CrateId, &mut CrateData)> + '_ {
+        self.arena.iter_mut()
+    }
+
     /// Returns an iterator over all transitive dependencies of the given crate,
     /// including the crate itself.
     pub fn transitive_deps(&self, of: CrateId) -> impl Iterator<Item = CrateId> {
diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs
index 36626ed1a9b..3ed7dfefc0f 100644
--- a/crates/hir-def/src/body.rs
+++ b/crates/hir-def/src/body.rs
@@ -118,7 +118,7 @@ impl Body {
         let _p = profile::span("body_with_source_map_query");
         let mut params = None;
 
-        let (file_id, module, body, is_async_fn) = {
+        let (file_id, body, is_async_fn) = {
             match def {
                 DefWithBodyId::FunctionId(f) => {
                     let data = db.function_data(f);
@@ -138,31 +138,29 @@ impl Body {
                             }),
                         )
                     });
-                    (
-                        src.file_id,
-                        f.module(db),
-                        src.value.body().map(ast::Expr::from),
-                        data.has_async_kw(),
-                    )
+                    (src.file_id, src.value.body().map(ast::Expr::from), data.has_async_kw())
                 }
                 DefWithBodyId::ConstId(c) => {
                     let c = c.lookup(db);
                     let src = c.source(db);
-                    (src.file_id, c.module(db), src.value.body(), false)
+                    (src.file_id, src.value.body(), false)
                 }
                 DefWithBodyId::StaticId(s) => {
                     let s = s.lookup(db);
                     let src = s.source(db);
-                    (src.file_id, s.module(db), src.value.body(), false)
+                    (src.file_id, src.value.body(), false)
                 }
                 DefWithBodyId::VariantId(v) => {
-                    let e = v.parent.lookup(db);
                     let src = v.parent.child_source(db);
                     let variant = &src.value[v.local_id];
-                    (src.file_id, e.container, variant.expr(), false)
+                    (src.file_id, variant.expr(), false)
+                }
+                DefWithBodyId::InTypeConstId(c) => {
+                    (c.lookup(db).0.file_id, c.source(db).expr(), false)
                 }
             }
         };
+        let module = def.module(db);
         let expander = Expander::new(db, file_id, module);
         let (mut body, source_map) =
             Body::new(db, def, expander, params, body, module.krate, is_async_fn);
diff --git a/crates/hir-def/src/body/pretty.rs b/crates/hir-def/src/body/pretty.rs
index 88380aa355d..cd6df0e6325 100644
--- a/crates/hir-def/src/body/pretty.rs
+++ b/crates/hir-def/src/body/pretty.rs
@@ -40,6 +40,7 @@ pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBo
             };
             format!("const {name} = ")
         }
+        DefWithBodyId::InTypeConstId(_) => format!("In type const = "),
         DefWithBodyId::VariantId(it) => {
             let src = it.parent.child_source(db);
             let variant = &src.value[it.local_id];
diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs
index 6d18e3f56ca..e6a6eb03497 100644
--- a/crates/hir-def/src/db.rs
+++ b/crates/hir-def/src/db.rs
@@ -1,7 +1,7 @@
 //! Defines database & queries for name resolution.
 use base_db::{salsa, CrateId, SourceDatabase, Upcast};
 use either::Either;
-use hir_expand::{db::ExpandDatabase, HirFileId};
+use hir_expand::{db::ExpandDatabase, AstId, HirFileId};
 use intern::Interned;
 use la_arena::ArenaMap;
 use syntax::{ast, AstPtr};
@@ -22,11 +22,12 @@ use crate::{
     lang_item::{LangItem, LangItemTarget, LangItems},
     nameres::{diagnostics::DefDiagnostic, DefMap},
     visibility::{self, Visibility},
-    AnonymousConstId, AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId,
-    EnumLoc, ExternBlockId, ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc,
-    LocalEnumVariantId, LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, MacroRulesLoc,
-    ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId,
-    TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId,
+    AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc,
+    ExternBlockId, ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc,
+    InTypeConstId, LocalEnumVariantId, LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId,
+    MacroRulesLoc, OpaqueInternableThing, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId,
+    StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc,
+    TypeOwnerId, UnionId, UnionLoc, VariantId,
 };
 
 #[salsa::query_group(InternDatabaseStorage)]
@@ -62,7 +63,12 @@ pub trait InternDatabase: SourceDatabase {
     #[salsa::interned]
     fn intern_macro_rules(&self, loc: MacroRulesLoc) -> MacroRulesId;
     #[salsa::interned]
-    fn intern_anonymous_const(&self, id: (DefWithBodyId, ExprId)) -> AnonymousConstId;
+    fn intern_anonymous_const(&self, id: (DefWithBodyId, ExprId)) -> ConstBlockId;
+    #[salsa::interned]
+    fn intern_in_type_const(
+        &self,
+        id: (AstId<ast::ConstArg>, TypeOwnerId, Box<dyn OpaqueInternableThing>),
+    ) -> InTypeConstId;
 }
 
 #[salsa::query_group(DefDatabaseStorage)]
diff --git a/crates/hir-def/src/expander.rs b/crates/hir-def/src/expander.rs
index 31653916f41..a588827c8d3 100644
--- a/crates/hir-def/src/expander.rs
+++ b/crates/hir-def/src/expander.rs
@@ -155,7 +155,7 @@ impl Expander {
     }
 
     pub(crate) fn parse_path(&mut self, db: &dyn DefDatabase, path: ast::Path) -> Option<Path> {
-        let ctx = LowerCtx::with_hygiene(db, &self.cfg_expander.hygiene);
+        let ctx = LowerCtx::new(db, &self.cfg_expander.hygiene, self.current_file_id);
         Path::from_src(path, &ctx)
     }
 
diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs
index 4ad8a7aa8eb..77d879a77ba 100644
--- a/crates/hir-def/src/hir.rs
+++ b/crates/hir-def/src/hir.rs
@@ -26,7 +26,7 @@ use crate::{
     builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
     path::{GenericArgs, Path},
     type_ref::{Mutability, Rawness, TypeRef},
-    AnonymousConstId, BlockId,
+    BlockId, ConstBlockId,
 };
 
 pub use syntax::ast::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp};
@@ -181,7 +181,7 @@ pub enum Expr {
         statements: Box<[Statement]>,
         tail: Option<ExprId>,
     },
-    Const(AnonymousConstId),
+    Const(ConstBlockId),
     Unsafe {
         id: Option<BlockId>,
         statements: Box<[Statement]>,
diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs
index 0573c9a6f8a..fa1f4933a26 100644
--- a/crates/hir-def/src/hir/type_ref.rs
+++ b/crates/hir-def/src/hir/type_ref.rs
@@ -118,7 +118,7 @@ pub enum TypeRef {
     Reference(Box<TypeRef>, Option<LifetimeRef>, Mutability),
     // FIXME: for full const generics, the latter element (length) here is going to have to be an
     // expression that is further lowered later in hir_ty.
-    Array(Box<TypeRef>, ConstRefOrPath),
+    Array(Box<TypeRef>, ConstRef),
     Slice(Box<TypeRef>),
     /// A fn pointer. Last element of the vector is the return type.
     Fn(Vec<(Option<Name>, TypeRef)>, bool /*varargs*/, bool /*is_unsafe*/),
@@ -186,11 +186,7 @@ impl TypeRef {
                 TypeRef::RawPtr(Box::new(inner_ty), mutability)
             }
             ast::Type::ArrayType(inner) => {
-                // FIXME: This is a hack. We should probably reuse the machinery of
-                // `hir_def::body::lower` to lower this into an `Expr` and then evaluate it at the
-                // `hir_ty` level, which would allow knowing the type of:
-                // let v: [u8; 2 + 2] = [0u8; 4];
-                let len = ConstRefOrPath::from_expr_opt(inner.expr());
+                let len = ConstRef::from_const_arg(ctx, inner.const_arg());
                 TypeRef::Array(Box::new(TypeRef::from_ast_opt(ctx, inner.ty())), len)
             }
             ast::Type::SliceType(inner) => {
@@ -380,73 +376,84 @@ impl TypeBound {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum ConstRefOrPath {
-    Scalar(ConstRef),
+pub enum ConstRef {
+    Scalar(LiteralConstRef),
     Path(Name),
+    Complex(AstId<ast::ConstArg>),
 }
 
-impl ConstRefOrPath {
-    pub(crate) fn from_expr_opt(expr: Option<ast::Expr>) -> Self {
-        match expr {
-            Some(x) => Self::from_expr(x),
-            None => Self::Scalar(ConstRef::Unknown),
+impl ConstRef {
+    pub(crate) fn from_const_arg(lower_ctx: &LowerCtx<'_>, arg: Option<ast::ConstArg>) -> Self {
+        if let Some(arg) = arg {
+            let ast_id = lower_ctx.ast_id(&arg);
+            if let Some(expr) = arg.expr() {
+                return Self::from_expr(expr, ast_id);
+            }
         }
+        Self::Scalar(LiteralConstRef::Unknown)
     }
 
     pub fn display<'a>(&'a self, db: &'a dyn ExpandDatabase) -> impl fmt::Display + 'a {
-        struct Display<'a>(&'a dyn ExpandDatabase, &'a ConstRefOrPath);
+        struct Display<'a>(&'a dyn ExpandDatabase, &'a ConstRef);
         impl fmt::Display for Display<'_> {
             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 match self.1 {
-                    ConstRefOrPath::Scalar(s) => s.fmt(f),
-                    ConstRefOrPath::Path(n) => n.display(self.0).fmt(f),
+                    ConstRef::Scalar(s) => s.fmt(f),
+                    ConstRef::Path(n) => n.display(self.0).fmt(f),
+                    ConstRef::Complex(_) => f.write_str("{const}"),
                 }
             }
         }
         Display(db, self)
     }
 
-    // FIXME: as per the comments on `TypeRef::Array`, this evaluation should not happen at this
-    // parse stage.
-    fn from_expr(expr: ast::Expr) -> Self {
+    // We special case literals and single identifiers, to speed up things.
+    fn from_expr(expr: ast::Expr, ast_id: Option<AstId<ast::ConstArg>>) -> Self {
+        fn is_path_ident(p: &ast::PathExpr) -> bool {
+            let Some(path) = p.path() else {
+                return false;
+            };
+            if path.coloncolon_token().is_some() {
+                return false;
+            }
+            if let Some(s) = path.segment() {
+                if s.coloncolon_token().is_some() || s.generic_arg_list().is_some() {
+                    return false;
+                }
+            }
+            true
+        }
         match expr {
-            ast::Expr::PathExpr(p) => {
+            ast::Expr::PathExpr(p) if is_path_ident(&p) => {
                 match p.path().and_then(|x| x.segment()).and_then(|x| x.name_ref()) {
                     Some(x) => Self::Path(x.as_name()),
-                    None => Self::Scalar(ConstRef::Unknown),
+                    None => Self::Scalar(LiteralConstRef::Unknown),
                 }
             }
-            ast::Expr::PrefixExpr(prefix_expr) => match prefix_expr.op_kind() {
-                Some(ast::UnaryOp::Neg) => {
-                    let unsigned = Self::from_expr_opt(prefix_expr.expr());
-                    // Add sign
-                    match unsigned {
-                        Self::Scalar(ConstRef::UInt(num)) => {
-                            Self::Scalar(ConstRef::Int(-(num as i128)))
-                        }
-                        other => other,
-                    }
-                }
-                _ => Self::from_expr_opt(prefix_expr.expr()),
-            },
             ast::Expr::Literal(literal) => Self::Scalar(match literal.kind() {
                 ast::LiteralKind::IntNumber(num) => {
-                    num.value().map(ConstRef::UInt).unwrap_or(ConstRef::Unknown)
+                    num.value().map(LiteralConstRef::UInt).unwrap_or(LiteralConstRef::Unknown)
                 }
                 ast::LiteralKind::Char(c) => {
-                    c.value().map(ConstRef::Char).unwrap_or(ConstRef::Unknown)
+                    c.value().map(LiteralConstRef::Char).unwrap_or(LiteralConstRef::Unknown)
                 }
-                ast::LiteralKind::Bool(f) => ConstRef::Bool(f),
-                _ => ConstRef::Unknown,
+                ast::LiteralKind::Bool(f) => LiteralConstRef::Bool(f),
+                _ => LiteralConstRef::Unknown,
             }),
-            _ => Self::Scalar(ConstRef::Unknown),
+            _ => {
+                if let Some(ast_id) = ast_id {
+                    Self::Complex(ast_id)
+                } else {
+                    Self::Scalar(LiteralConstRef::Unknown)
+                }
+            }
         }
     }
 }
 
-/// A concrete constant value
+/// A literal constant value
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum ConstRef {
+pub enum LiteralConstRef {
     Int(i128),
     UInt(u128),
     Bool(bool),
@@ -460,18 +467,20 @@ pub enum ConstRef {
     Unknown,
 }
 
-impl ConstRef {
+impl LiteralConstRef {
     pub fn builtin_type(&self) -> BuiltinType {
         match self {
-            ConstRef::UInt(_) | ConstRef::Unknown => BuiltinType::Uint(BuiltinUint::U128),
-            ConstRef::Int(_) => BuiltinType::Int(BuiltinInt::I128),
-            ConstRef::Char(_) => BuiltinType::Char,
-            ConstRef::Bool(_) => BuiltinType::Bool,
+            LiteralConstRef::UInt(_) | LiteralConstRef::Unknown => {
+                BuiltinType::Uint(BuiltinUint::U128)
+            }
+            LiteralConstRef::Int(_) => BuiltinType::Int(BuiltinInt::I128),
+            LiteralConstRef::Char(_) => BuiltinType::Char,
+            LiteralConstRef::Bool(_) => BuiltinType::Bool,
         }
     }
 }
 
-impl From<Literal> for ConstRef {
+impl From<Literal> for LiteralConstRef {
     fn from(literal: Literal) -> Self {
         match literal {
             Literal::Char(c) => Self::Char(c),
@@ -483,14 +492,14 @@ impl From<Literal> for ConstRef {
     }
 }
 
-impl std::fmt::Display for ConstRef {
+impl std::fmt::Display for LiteralConstRef {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
         match self {
-            ConstRef::Int(num) => num.fmt(f),
-            ConstRef::UInt(num) => num.fmt(f),
-            ConstRef::Bool(flag) => flag.fmt(f),
-            ConstRef::Char(c) => write!(f, "'{c}'"),
-            ConstRef::Unknown => f.write_char('_'),
+            LiteralConstRef::Int(num) => num.fmt(f),
+            LiteralConstRef::UInt(num) => num.fmt(f),
+            LiteralConstRef::Bool(flag) => flag.fmt(f),
+            LiteralConstRef::Char(c) => write!(f, "'{c}'"),
+            LiteralConstRef::Unknown => f.write_char('_'),
         }
     }
 }
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index 98cff54cc22..4f68093bcbe 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -57,7 +57,10 @@ mod test_db;
 mod macro_expansion_tests;
 mod pretty;
 
-use std::hash::{Hash, Hasher};
+use std::{
+    hash::{Hash, Hasher},
+    panic::{RefUnwindSafe, UnwindSafe},
+};
 
 use base_db::{
     impl_intern_key,
@@ -89,8 +92,8 @@ use crate::{
     builtin_type::BuiltinType,
     data::adt::VariantData,
     item_tree::{
-        Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules, ModItem,
-        Static, Struct, Trait, TraitAlias, TypeAlias, Union,
+        Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules, Static,
+        Struct, Trait, TraitAlias, TypeAlias, Union,
     },
 };
 
@@ -476,29 +479,183 @@ impl_from!(
     for ModuleDefId
 );
 
-// FIXME: make this a DefWithBodyId
+/// Id of the anonymous const block expression and patterns. This is very similar to `ClosureId` and
+/// shouldn't be a `DefWithBodyId` since its type inference is dependent on its parent.
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+pub struct ConstBlockId(InternId);
+impl_intern_key!(ConstBlockId);
+
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+pub enum TypeOwnerId {
+    FunctionId(FunctionId),
+    StaticId(StaticId),
+    ConstId(ConstId),
+    InTypeConstId(InTypeConstId),
+    AdtId(AdtId),
+    TraitId(TraitId),
+    TraitAliasId(TraitAliasId),
+    TypeAliasId(TypeAliasId),
+    ImplId(ImplId),
+    EnumVariantId(EnumVariantId),
+    // FIXME(const-generic-body): ModuleId should not be a type owner. This needs to be fixed to make `TypeOwnerId` actually
+    // useful for assigning ids to in type consts.
+    ModuleId(ModuleId),
+}
+
+impl TypeOwnerId {
+    fn as_generic_def_id(self) -> Option<GenericDefId> {
+        Some(match self {
+            TypeOwnerId::FunctionId(x) => GenericDefId::FunctionId(x),
+            TypeOwnerId::ConstId(x) => GenericDefId::ConstId(x),
+            TypeOwnerId::AdtId(x) => GenericDefId::AdtId(x),
+            TypeOwnerId::TraitId(x) => GenericDefId::TraitId(x),
+            TypeOwnerId::TraitAliasId(x) => GenericDefId::TraitAliasId(x),
+            TypeOwnerId::TypeAliasId(x) => GenericDefId::TypeAliasId(x),
+            TypeOwnerId::ImplId(x) => GenericDefId::ImplId(x),
+            TypeOwnerId::EnumVariantId(x) => GenericDefId::EnumVariantId(x),
+            TypeOwnerId::InTypeConstId(_) | TypeOwnerId::ModuleId(_) | TypeOwnerId::StaticId(_) => {
+                return None
+            }
+        })
+    }
+}
+
+impl_from!(
+    FunctionId,
+    StaticId,
+    ConstId,
+    InTypeConstId,
+    AdtId,
+    TraitId,
+    TraitAliasId,
+    TypeAliasId,
+    ImplId,
+    EnumVariantId,
+    ModuleId
+    for TypeOwnerId
+);
+
+// Every `DefWithBodyId` is a type owner, since bodies can contain type (e.g. `{ let x: Type = _; }`)
+impl From<DefWithBodyId> for TypeOwnerId {
+    fn from(value: DefWithBodyId) -> Self {
+        match value {
+            DefWithBodyId::FunctionId(x) => x.into(),
+            DefWithBodyId::StaticId(x) => x.into(),
+            DefWithBodyId::ConstId(x) => x.into(),
+            DefWithBodyId::InTypeConstId(x) => x.into(),
+            DefWithBodyId::VariantId(x) => x.into(),
+        }
+    }
+}
+
+impl From<GenericDefId> for TypeOwnerId {
+    fn from(value: GenericDefId) -> Self {
+        match value {
+            GenericDefId::FunctionId(x) => x.into(),
+            GenericDefId::AdtId(x) => x.into(),
+            GenericDefId::TraitId(x) => x.into(),
+            GenericDefId::TraitAliasId(x) => x.into(),
+            GenericDefId::TypeAliasId(x) => x.into(),
+            GenericDefId::ImplId(x) => x.into(),
+            GenericDefId::EnumVariantId(x) => x.into(),
+            GenericDefId::ConstId(x) => x.into(),
+        }
+    }
+}
+
+/// A thing that we want to store in interned ids, but we don't know its type in `hir-def`. This is
+/// currently only used in `InTypeConstId` for storing the type (which has type `Ty` defined in
+/// the `hir-ty` crate) of the constant in its id, which is a temporary hack so we may want
+/// to remove this after removing that.
+pub trait OpaqueInternableThing:
+    std::any::Any + std::fmt::Debug + Sync + Send + UnwindSafe + RefUnwindSafe
+{
+    fn as_any(&self) -> &dyn std::any::Any;
+    fn box_any(&self) -> Box<dyn std::any::Any>;
+    fn dyn_hash(&self, state: &mut dyn Hasher);
+    fn dyn_eq(&self, other: &dyn OpaqueInternableThing) -> bool;
+    fn dyn_clone(&self) -> Box<dyn OpaqueInternableThing>;
+}
+
+impl Hash for dyn OpaqueInternableThing {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.dyn_hash(state);
+    }
+}
+
+impl PartialEq for dyn OpaqueInternableThing {
+    fn eq(&self, other: &Self) -> bool {
+        self.dyn_eq(other)
+    }
+}
+
+impl Eq for dyn OpaqueInternableThing {}
+
+impl Clone for Box<dyn OpaqueInternableThing> {
+    fn clone(&self) -> Self {
+        self.dyn_clone()
+    }
+}
+
+// FIXME(const-generic-body): Use an stable id for in type consts.
+//
+// The current id uses `AstId<ast::ConstArg>` which will be changed by every change in the code. Ideally
+// we should use an id which is relative to the type owner, so that every change will only invalidate the
+// id if it happens inside of the type owner.
+//
+// The solution probably is to have some query on `TypeOwnerId` to traverse its constant children and store
+// their `AstId` in a list (vector or arena), and use the index of that list in the id here. That query probably
+// needs name resolution, and might go far and handles the whole path lowering or type lowering for a `TypeOwnerId`.
+//
+// Whatever path the solution takes, it should answer 3 questions at the same time:
+// * Is the id stable enough?
+// * How to find a constant id using an ast node / position in the source code? This is needed when we want to
+//   provide ide functionalities inside an in type const (which we currently don't support) e.g. go to definition
+//   for a local defined there. A complex id might have some trouble in this reverse mapping.
+// * How to find the return type of a constant using its id? We have this data when we are doing type lowering
+//   and the name of the struct that contains this constant is resolved, so a query that only traverses the
+//   type owner by its syntax tree might have a hard time here.
+
+/// A constant in a type as a substitution for const generics (like `Foo<{ 2 + 2 }>`) or as an array
+/// length (like `[u8; 2 + 2]`). These constants are body owner and are a variant of `DefWithBodyId`. These
+/// are not called `AnonymousConstId` to prevent confusion with [`ConstBlockId`].
 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
-pub struct AnonymousConstId(InternId);
-impl_intern_key!(AnonymousConstId);
+pub struct InTypeConstId(InternId);
+type InTypeConstLoc = (AstId<ast::ConstArg>, TypeOwnerId, Box<dyn OpaqueInternableThing>);
+impl_intern!(InTypeConstId, InTypeConstLoc, intern_in_type_const, lookup_intern_in_type_const);
+
+impl InTypeConstId {
+    pub fn source(&self, db: &dyn db::DefDatabase) -> ast::ConstArg {
+        let src = self.lookup(db).0;
+        let file_id = src.file_id;
+        let root = &db.parse_or_expand(file_id);
+        db.ast_id_map(file_id).get(src.value).to_node(root)
+    }
+}
 
 /// A constant, which might appears as a const item, an annonymous const block in expressions
 /// or patterns, or as a constant in types with const generics.
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub enum GeneralConstId {
     ConstId(ConstId),
-    AnonymousConstId(AnonymousConstId),
+    ConstBlockId(ConstBlockId),
+    InTypeConstId(InTypeConstId),
 }
 
-impl_from!(ConstId, AnonymousConstId for GeneralConstId);
+impl_from!(ConstId, ConstBlockId, InTypeConstId for GeneralConstId);
 
 impl GeneralConstId {
     pub fn generic_def(self, db: &dyn db::DefDatabase) -> Option<GenericDefId> {
         match self {
             GeneralConstId::ConstId(x) => Some(x.into()),
-            GeneralConstId::AnonymousConstId(x) => {
+            GeneralConstId::ConstBlockId(x) => {
                 let (parent, _) = db.lookup_intern_anonymous_const(x);
                 parent.as_generic_def_id()
             }
+            GeneralConstId::InTypeConstId(x) => {
+                let (_, parent, _) = x.lookup(db);
+                parent.as_generic_def_id()
+            }
         }
     }
 
@@ -511,7 +668,8 @@ impl GeneralConstId {
                 .and_then(|x| x.as_str())
                 .unwrap_or("_")
                 .to_owned(),
-            GeneralConstId::AnonymousConstId(id) => format!("{{anonymous const {id:?}}}"),
+            GeneralConstId::ConstBlockId(id) => format!("{{anonymous const {id:?}}}"),
+            GeneralConstId::InTypeConstId(id) => format!("{{in type const {id:?}}}"),
         }
     }
 }
@@ -522,10 +680,11 @@ pub enum DefWithBodyId {
     FunctionId(FunctionId),
     StaticId(StaticId),
     ConstId(ConstId),
+    InTypeConstId(InTypeConstId),
     VariantId(EnumVariantId),
 }
 
-impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId);
+impl_from!(FunctionId, ConstId, StaticId, InTypeConstId for DefWithBodyId);
 
 impl From<EnumVariantId> for DefWithBodyId {
     fn from(id: EnumVariantId) -> Self {
@@ -540,6 +699,9 @@ impl DefWithBodyId {
             DefWithBodyId::StaticId(_) => None,
             DefWithBodyId::ConstId(c) => Some(c.into()),
             DefWithBodyId::VariantId(c) => Some(c.into()),
+            // FIXME: stable rust doesn't allow generics in constants, but we should
+            // use `TypeOwnerId::as_generic_def_id` when it does.
+            DefWithBodyId::InTypeConstId(_) => None,
         }
     }
 }
@@ -734,24 +896,32 @@ impl HasModule for MacroId {
     }
 }
 
-impl HasModule for DefWithBodyId {
+impl HasModule for TypeOwnerId {
     fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
         match self {
-            DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
-            DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
-            DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
-            DefWithBodyId::VariantId(it) => it.parent.lookup(db).container,
+            TypeOwnerId::FunctionId(x) => x.lookup(db).module(db),
+            TypeOwnerId::StaticId(x) => x.lookup(db).module(db),
+            TypeOwnerId::ConstId(x) => x.lookup(db).module(db),
+            TypeOwnerId::InTypeConstId(x) => x.lookup(db).1.module(db),
+            TypeOwnerId::AdtId(x) => x.module(db),
+            TypeOwnerId::TraitId(x) => x.lookup(db).container,
+            TypeOwnerId::TraitAliasId(x) => x.lookup(db).container,
+            TypeOwnerId::TypeAliasId(x) => x.lookup(db).module(db),
+            TypeOwnerId::ImplId(x) => x.lookup(db).container,
+            TypeOwnerId::EnumVariantId(x) => x.parent.lookup(db).container,
+            TypeOwnerId::ModuleId(x) => *x,
         }
     }
 }
 
-impl DefWithBodyId {
-    pub fn as_mod_item(self, db: &dyn db::DefDatabase) -> ModItem {
+impl HasModule for DefWithBodyId {
+    fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
         match self {
-            DefWithBodyId::FunctionId(it) => it.lookup(db).id.value.into(),
-            DefWithBodyId::StaticId(it) => it.lookup(db).id.value.into(),
-            DefWithBodyId::ConstId(it) => it.lookup(db).id.value.into(),
-            DefWithBodyId::VariantId(it) => it.parent.lookup(db).id.value.into(),
+            DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
+            DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
+            DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
+            DefWithBodyId::VariantId(it) => it.parent.lookup(db).container,
+            DefWithBodyId::InTypeConstId(it) => it.lookup(db).1.module(db),
         }
     }
 }
diff --git a/crates/hir-def/src/path.rs b/crates/hir-def/src/path.rs
index b9b80825497..ff4ae69546c 100644
--- a/crates/hir-def/src/path.rs
+++ b/crates/hir-def/src/path.rs
@@ -9,7 +9,7 @@ use std::{
 use crate::{
     lang_item::LangItemTarget,
     lower::LowerCtx,
-    type_ref::{ConstRefOrPath, LifetimeRef, TypeBound, TypeRef},
+    type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef},
 };
 use hir_expand::name::Name;
 use intern::Interned;
@@ -90,7 +90,7 @@ pub struct AssociatedTypeBinding {
 pub enum GenericArg {
     Type(TypeRef),
     Lifetime(LifetimeRef),
-    Const(ConstRefOrPath),
+    Const(ConstRef),
 }
 
 impl Path {
diff --git a/crates/hir-def/src/path/lower.rs b/crates/hir-def/src/path/lower.rs
index 26d2706175c..1cb17ff0d26 100644
--- a/crates/hir-def/src/path/lower.rs
+++ b/crates/hir-def/src/path/lower.rs
@@ -2,7 +2,7 @@
 
 use std::iter;
 
-use crate::{lower::LowerCtx, type_ref::ConstRefOrPath};
+use crate::{lower::LowerCtx, type_ref::ConstRef};
 
 use either::Either;
 use hir_expand::name::{name, AsName};
@@ -217,7 +217,7 @@ pub(super) fn lower_generic_args(
                 }
             }
             ast::GenericArg::ConstArg(arg) => {
-                let arg = ConstRefOrPath::from_expr_opt(arg.expr());
+                let arg = ConstRef::from_const_arg(lower_ctx, Some(arg));
                 args.push(GenericArg::Const(arg))
             }
         }
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index 06f5b2526a4..880a76f2b85 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -24,8 +24,8 @@ use crate::{
     AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId,
     FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
     LocalModuleId, Lookup, Macro2Id, MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId,
-    StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
-    VariantId,
+    StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId,
+    TypeParamId, VariantId,
 };
 
 #[derive(Debug, Clone)]
@@ -1009,6 +1009,24 @@ impl HasResolver for ExternBlockId {
     }
 }
 
+impl HasResolver for TypeOwnerId {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+        match self {
+            TypeOwnerId::FunctionId(x) => x.resolver(db),
+            TypeOwnerId::StaticId(x) => x.resolver(db),
+            TypeOwnerId::ConstId(x) => x.resolver(db),
+            TypeOwnerId::InTypeConstId(x) => x.lookup(db).1.resolver(db),
+            TypeOwnerId::AdtId(x) => x.resolver(db),
+            TypeOwnerId::TraitId(x) => x.resolver(db),
+            TypeOwnerId::TraitAliasId(x) => x.resolver(db),
+            TypeOwnerId::TypeAliasId(x) => x.resolver(db),
+            TypeOwnerId::ImplId(x) => x.resolver(db),
+            TypeOwnerId::EnumVariantId(x) => x.resolver(db),
+            TypeOwnerId::ModuleId(x) => x.resolver(db),
+        }
+    }
+}
+
 impl HasResolver for DefWithBodyId {
     fn resolver(self, db: &dyn DefDatabase) -> Resolver {
         match self {
@@ -1016,6 +1034,7 @@ impl HasResolver for DefWithBodyId {
             DefWithBodyId::FunctionId(f) => f.resolver(db),
             DefWithBodyId::StaticId(s) => s.resolver(db),
             DefWithBodyId::VariantId(v) => v.parent.resolver(db),
+            DefWithBodyId::InTypeConstId(c) => c.lookup(db).1.resolver(db),
         }
     }
 }
diff --git a/crates/hir-expand/src/ast_id_map.rs b/crates/hir-expand/src/ast_id_map.rs
index 400442de94b..02efaace437 100644
--- a/crates/hir-expand/src/ast_id_map.rs
+++ b/crates/hir-expand/src/ast_id_map.rs
@@ -98,6 +98,7 @@ impl AstIdMap {
                 || ast::Variant::can_cast(kind)
                 || ast::RecordField::can_cast(kind)
                 || ast::TupleField::can_cast(kind)
+                || ast::ConstArg::can_cast(kind)
             {
                 res.alloc(&it);
                 true
diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs
index ac962c9e3e1..2a31e5cab8a 100644
--- a/crates/hir-ty/src/chalk_db.rs
+++ b/crates/hir-ty/src/chalk_db.rs
@@ -497,7 +497,7 @@ pub(crate) fn associated_ty_data_query(
     let generic_params = generics(db.upcast(), type_alias.into());
     // let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
     let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast());
-    let ctx = crate::TyLoweringContext::new(db, &resolver)
+    let ctx = crate::TyLoweringContext::new(db, &resolver, type_alias.into())
         .with_type_param_mode(crate::lower::ParamLoweringMode::Variable);
 
     let trait_subst = TyBuilder::subst_for_def(db, trait_, None)
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index 40b63b17b5a..7a7c12e5b44 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/crates/hir-ty/src/consteval.rs
@@ -6,7 +6,7 @@ use hir_def::{
     hir::Expr,
     path::Path,
     resolver::{Resolver, ValueNs},
-    type_ref::ConstRef,
+    type_ref::LiteralConstRef,
     EnumVariantId, GeneralConstId, StaticId,
 };
 use la_arena::{Idx, RawIdx};
@@ -129,23 +129,28 @@ pub fn intern_const_scalar(value: ConstScalar, ty: Ty) -> Const {
 }
 
 /// Interns a constant scalar with the given type
-pub fn intern_const_ref(db: &dyn HirDatabase, value: &ConstRef, ty: Ty, krate: CrateId) -> Const {
+pub fn intern_const_ref(
+    db: &dyn HirDatabase,
+    value: &LiteralConstRef,
+    ty: Ty,
+    krate: CrateId,
+) -> Const {
     let layout = db.layout_of_ty(ty.clone(), krate);
     let bytes = match value {
-        ConstRef::Int(i) => {
+        LiteralConstRef::Int(i) => {
             // FIXME: We should handle failure of layout better.
             let size = layout.map(|x| x.size.bytes_usize()).unwrap_or(16);
             ConstScalar::Bytes(i.to_le_bytes()[0..size].to_vec(), MemoryMap::default())
         }
-        ConstRef::UInt(i) => {
+        LiteralConstRef::UInt(i) => {
             let size = layout.map(|x| x.size.bytes_usize()).unwrap_or(16);
             ConstScalar::Bytes(i.to_le_bytes()[0..size].to_vec(), MemoryMap::default())
         }
-        ConstRef::Bool(b) => ConstScalar::Bytes(vec![*b as u8], MemoryMap::default()),
-        ConstRef::Char(c) => {
+        LiteralConstRef::Bool(b) => ConstScalar::Bytes(vec![*b as u8], MemoryMap::default()),
+        LiteralConstRef::Char(c) => {
             ConstScalar::Bytes((*c as u32).to_le_bytes().to_vec(), MemoryMap::default())
         }
-        ConstRef::Unknown => ConstScalar::Unknown,
+        LiteralConstRef::Unknown => ConstScalar::Unknown,
     };
     intern_const_scalar(bytes, ty)
 }
@@ -154,7 +159,7 @@ pub fn intern_const_ref(db: &dyn HirDatabase, value: &ConstRef, ty: Ty, krate: C
 pub fn usize_const(db: &dyn HirDatabase, value: Option<u128>, krate: CrateId) -> Const {
     intern_const_ref(
         db,
-        &value.map_or(ConstRef::Unknown, ConstRef::UInt),
+        &value.map_or(LiteralConstRef::Unknown, LiteralConstRef::UInt),
         TyBuilder::usize(),
         krate,
     )
@@ -210,7 +215,7 @@ pub(crate) fn const_eval_query(
         GeneralConstId::ConstId(c) => {
             db.monomorphized_mir_body(c.into(), subst, db.trait_environment(c.into()))?
         }
-        GeneralConstId::AnonymousConstId(c) => {
+        GeneralConstId::ConstBlockId(c) => {
             let (def, root) = db.lookup_intern_anonymous_const(c);
             let body = db.body(def);
             let infer = db.infer(def);
@@ -221,6 +226,7 @@ pub(crate) fn const_eval_query(
                 db.trait_environment_for_body(def),
             )?)
         }
+        GeneralConstId::InTypeConstId(c) => db.mir_body(c.into())?,
     };
     let c = interpret_mir(db, &body, false).0?;
     Ok(c)
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index 06fff08b7d3..0db1fefbfef 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -2052,6 +2052,17 @@ fn extern_weak_statics() {
 }
 
 #[test]
+fn from_ne_bytes() {
+    check_number(
+        r#"
+//- minicore: int_impl
+const GOAL: u32 = u32::from_ne_bytes([44, 1, 0, 0]);
+        "#,
+        300,
+    );
+}
+
+#[test]
 fn enums() {
     check_number(
         r#"
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index ca8a394e360..9dd810f844d 100644
--- a/crates/hir-ty/src/db.rs
+++ b/crates/hir-ty/src/db.rs
@@ -278,6 +278,7 @@ fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult>
         DefWithBodyId::VariantId(it) => {
             db.enum_data(it.parent).variants[it.local_id].name.display(db.upcast()).to_string()
         }
+        DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"),
     });
     db.infer_query(def)
 }
diff --git a/crates/hir-ty/src/diagnostics/unsafe_check.rs b/crates/hir-ty/src/diagnostics/unsafe_check.rs
index 7c38e6583a7..9f9a56ffab0 100644
--- a/crates/hir-ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir-ty/src/diagnostics/unsafe_check.rs
@@ -18,9 +18,10 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> Vec<ExprId> {
 
     let is_unsafe = match def {
         DefWithBodyId::FunctionId(it) => db.function_data(it).has_unsafe_kw(),
-        DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) | DefWithBodyId::VariantId(_) => {
-            false
-        }
+        DefWithBodyId::StaticId(_)
+        | DefWithBodyId::ConstId(_)
+        | DefWithBodyId::VariantId(_)
+        | DefWithBodyId::InTypeConstId(_) => false,
     };
     if is_unsafe {
         return res;
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 80f32e96ee6..2506ae5bb6f 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -41,10 +41,15 @@ use stdx::{always, never};
 use triomphe::Arc;
 
 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,
+    db::HirDatabase,
+    fold_tys,
+    infer::coerce::CoerceMany,
+    lower::ImplTraitLoweringMode,
+    static_lifetime, to_assoc_type_id,
+    traits::FnTrait,
+    utils::{InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder},
+    AliasEq, AliasTy, ClosureId, DomainGoal, GenericArg, Goal, ImplTraitId, InEnvironment,
+    Interner, ProjectionTy, RpitId, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt,
 };
 
 // This lint has a false positive here. See the link below for details.
@@ -102,6 +107,11 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
                 },
             });
         }
+        DefWithBodyId::InTypeConstId(c) => {
+            // FIXME(const-generic-body): We should not get the return type in this way.
+            ctx.return_ty =
+                c.lookup(db.upcast()).2.box_any().downcast::<InTypeConstIdMetadata>().unwrap().0;
+        }
     }
 
     ctx.infer_body();
@@ -684,7 +694,7 @@ impl<'a> InferenceContext<'a> {
 
     fn collect_fn(&mut self, func: FunctionId) {
         let data = self.db.function_data(func);
-        let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
+        let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, func.into())
             .with_impl_trait_mode(ImplTraitLoweringMode::Param);
         let mut param_tys =
             data.params.iter().map(|type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>();
@@ -708,7 +718,7 @@ impl<'a> InferenceContext<'a> {
         }
         let return_ty = &*data.ret_type;
 
-        let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
+        let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into())
             .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
         let return_ty = ctx.lower_ty(return_ty);
         let return_ty = self.insert_type_vars(return_ty);
@@ -823,7 +833,7 @@ impl<'a> InferenceContext<'a> {
     }
 
     fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
-        let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
+        let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into());
         let ty = ctx.lower_ty(type_ref);
         let ty = self.insert_type_vars(ty);
         self.normalize_associated_types_in(ty)
@@ -850,7 +860,21 @@ impl<'a> InferenceContext<'a> {
     }
 
     fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
-        self.table.unify(ty1, ty2)
+        let ty1 = ty1
+            .clone()
+            .try_fold_with(
+                &mut UnevaluatedConstEvaluatorFolder { db: self.db },
+                DebruijnIndex::INNERMOST,
+            )
+            .unwrap();
+        let ty2 = ty2
+            .clone()
+            .try_fold_with(
+                &mut UnevaluatedConstEvaluatorFolder { db: self.db },
+                DebruijnIndex::INNERMOST,
+            )
+            .unwrap();
+        self.table.unify(&ty1, &ty2)
     }
 
     /// Attempts to returns the deeply last field of nested structures, but
@@ -973,7 +997,7 @@ impl<'a> InferenceContext<'a> {
             Some(path) => path,
             None => return (self.err_ty(), None),
         };
-        let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
+        let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into());
         let (resolution, unresolved) = if value_ns {
             match self.resolver.resolve_path_in_value_ns(self.db.upcast(), path) {
                 Some(ResolveValueResult::ValueNs(value)) => match value {
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 33e98ac86cf..e1efa0b6d8c 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -1715,6 +1715,7 @@ impl<'a> InferenceContext<'a> {
                         const_or_path_to_chalk(
                             this.db,
                             &this.resolver,
+                            this.owner.into(),
                             ty,
                             c,
                             ParamLoweringMode::Placeholder,
diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs
index 95a20f983f1..79d9e21e797 100644
--- a/crates/hir-ty/src/infer/path.rs
+++ b/crates/hir-ty/src/infer/path.rs
@@ -44,7 +44,8 @@ impl InferenceContext<'_> {
             let last = path.segments().last()?;
 
             // Don't use `self.make_ty()` here as we need `orig_ns`.
-            let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
+            let ctx =
+                crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into());
             let (ty, orig_ns) = ctx.lower_ty_ext(type_ref);
             let ty = self.table.insert_type_vars(ty);
             let ty = self.table.normalize_associated_types_in(ty);
@@ -108,7 +109,7 @@ impl InferenceContext<'_> {
             }
         };
 
-        let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
+        let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into());
         let substs = ctx.substs_from_path(path, value_def, true);
         let substs = substs.as_slice(Interner);
         let parent_substs = self_subst.or_else(|| {
@@ -190,7 +191,11 @@ impl InferenceContext<'_> {
             (TypeNs::TraitId(trait_), true) => {
                 let segment =
                     remaining_segments.last().expect("there should be at least one segment here");
-                let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
+                let ctx = crate::lower::TyLoweringContext::new(
+                    self.db,
+                    &self.resolver,
+                    self.owner.into(),
+                );
                 let trait_ref =
                     ctx.lower_trait_ref_from_resolved_path(trait_, resolved_segment, None);
                 self.resolve_trait_assoc_item(trait_ref, segment, id)
@@ -202,7 +207,11 @@ impl InferenceContext<'_> {
                 // as Iterator>::Item::default`)
                 let remaining_segments_for_ty =
                     remaining_segments.take(remaining_segments.len() - 1);
-                let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
+                let ctx = crate::lower::TyLoweringContext::new(
+                    self.db,
+                    &self.resolver,
+                    self.owner.into(),
+                );
                 let (ty, _) = ctx.lower_partly_resolved_path(
                     def,
                     resolved_segment,
diff --git a/crates/hir-ty/src/interner.rs b/crates/hir-ty/src/interner.rs
index 89f7d9c4f4a..e4dd4b86cf9 100644
--- a/crates/hir-ty/src/interner.rs
+++ b/crates/hir-ty/src/interner.rs
@@ -266,7 +266,7 @@ impl chalk_ir::interner::Interner for Interner {
         c1: &Self::InternedConcreteConst,
         c2: &Self::InternedConcreteConst,
     ) -> bool {
-        (c1 == &ConstScalar::Unknown) || (c2 == &ConstScalar::Unknown) || (c1 == c2)
+        !matches!(c1, ConstScalar::Bytes(..)) || !matches!(c2, ConstScalar::Bytes(..)) || (c1 == c2)
     }
 
     fn intern_generic_arg(
diff --git a/crates/hir-ty/src/layout/tests.rs b/crates/hir-ty/src/layout/tests.rs
index fca2e09ff0a..0ff8c532d47 100644
--- a/crates/hir-ty/src/layout/tests.rs
+++ b/crates/hir-ty/src/layout/tests.rs
@@ -2,6 +2,7 @@ use std::collections::HashMap;
 
 use base_db::fixture::WithFixture;
 use chalk_ir::{AdtId, TyKind};
+use either::Either;
 use hir_def::db::DefDatabase;
 use triomphe::Arc;
 
@@ -25,27 +26,38 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
     );
 
     let (db, file_ids) = TestDB::with_many_files(&ra_fixture);
-    let (adt_id, module_id) = file_ids
+    let (adt_or_type_alias_id, module_id) = file_ids
         .into_iter()
         .find_map(|file_id| {
             let module_id = db.module_for_file(file_id);
             let def_map = module_id.def_map(&db);
             let scope = &def_map[module_id.local_id].scope;
-            let adt_id = scope.declarations().find_map(|x| match x {
+            let adt_or_type_alias_id = scope.declarations().find_map(|x| match x {
                 hir_def::ModuleDefId::AdtId(x) => {
                     let name = match x {
                         hir_def::AdtId::StructId(x) => db.struct_data(x).name.to_smol_str(),
                         hir_def::AdtId::UnionId(x) => db.union_data(x).name.to_smol_str(),
                         hir_def::AdtId::EnumId(x) => db.enum_data(x).name.to_smol_str(),
                     };
-                    (name == "Goal").then_some(x)
+                    (name == "Goal").then_some(Either::Left(x))
+                }
+                hir_def::ModuleDefId::TypeAliasId(x) => {
+                    let name = db.type_alias_data(x).name.to_smol_str();
+                    (name == "Goal").then_some(Either::Right(x))
                 }
                 _ => None,
             })?;
-            Some((adt_id, module_id))
+            Some((adt_or_type_alias_id, module_id))
         })
         .unwrap();
-    let goal_ty = TyKind::Adt(AdtId(adt_id), Substitution::empty(Interner)).intern(Interner);
+    let goal_ty = match adt_or_type_alias_id {
+        Either::Left(adt_id) => {
+            TyKind::Adt(AdtId(adt_id), Substitution::empty(Interner)).intern(Interner)
+        }
+        Either::Right(ty_id) => {
+            db.ty(ty_id.into()).substitute(Interner, &Substitution::empty(Interner))
+        }
+    };
     db.layout_of_ty(goal_ty, module_id.krate())
 }
 
@@ -380,9 +392,22 @@ fn niche_optimization() {
 #[test]
 fn const_eval() {
     size_and_align! {
+        struct Goal([i32; 2 + 2]);
+    }
+    size_and_align! {
         const X: usize = 5;
         struct Goal([i32; X]);
     }
+    size_and_align! {
+        mod foo {
+            pub(super) const BAR: usize = 5;
+        }
+        struct Ar<T>([T; foo::BAR]);
+        struct Goal(Ar<Ar<i32>>);
+    }
+    size_and_align! {
+        type Goal = [u8; 2 + 2];
+    }
 }
 
 #[test]
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 0c68891fe49..c0bcf790b1f 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -27,10 +27,11 @@ use hir_def::{
     nameres::MacroSubNs,
     path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
     resolver::{HasResolver, Resolver, TypeNs},
-    type_ref::{ConstRefOrPath, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef},
+    type_ref::{ConstRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef},
     AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
     GenericDefId, HasModule, ImplId, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, StaticId,
-    StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, VariantId,
+    StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, UnionId,
+    VariantId,
 };
 use hir_expand::{name::Name, ExpandResult};
 use intern::Interned;
@@ -43,17 +44,24 @@ use triomphe::Arc;
 
 use crate::{
     all_super_traits,
-    consteval::{intern_const_ref, path_to_const, unknown_const, unknown_const_as_generic},
+    consteval::{
+        intern_const_ref, intern_const_scalar, path_to_const, unknown_const,
+        unknown_const_as_generic,
+    },
     db::HirDatabase,
     make_binders,
     mapping::{from_chalk_trait_id, ToChalk},
     static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
     utils::Generics,
-    utils::{all_super_trait_refs, associated_type_by_name_including_super_traits, generics},
-    AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, DebruijnIndex, DynTy, FnPointer,
-    FnSig, FnSubst, GenericArgData, ImplTraitId, Interner, ParamKind, PolyFnSig, ProjectionTy,
-    QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits,
-    Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
+    utils::{
+        all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
+        InTypeConstIdMetadata,
+    },
+    AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
+    FnPointer, FnSig, FnSubst, GenericArgData, ImplTraitId, Interner, ParamKind, PolyFnSig,
+    ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait,
+    ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder,
+    TyKind, WhereClause,
 };
 
 #[derive(Debug)]
@@ -106,6 +114,7 @@ pub struct TyLoweringContext<'a> {
     pub db: &'a dyn HirDatabase,
     resolver: &'a Resolver,
     in_binders: DebruijnIndex,
+    owner: TypeOwnerId,
     /// Note: Conceptually, it's thinkable that we could be in a location where
     /// some type params should be represented as placeholders, and others
     /// should be converted to variables. I think in practice, this isn't
@@ -118,13 +127,14 @@ pub struct TyLoweringContext<'a> {
 }
 
 impl<'a> TyLoweringContext<'a> {
-    pub fn new(db: &'a dyn HirDatabase, resolver: &'a Resolver) -> Self {
+    pub fn new(db: &'a dyn HirDatabase, resolver: &'a Resolver, owner: TypeOwnerId) -> Self {
         let impl_trait_mode = ImplTraitLoweringState::Disallowed;
         let type_param_mode = ParamLoweringMode::Placeholder;
         let in_binders = DebruijnIndex::INNERMOST;
         Self {
             db,
             resolver,
+            owner,
             in_binders,
             impl_trait_mode,
             type_param_mode,
@@ -235,6 +245,7 @@ impl<'a> TyLoweringContext<'a> {
                 let const_len = const_or_path_to_chalk(
                     self.db,
                     self.resolver,
+                    self.owner,
                     TyBuilder::usize(),
                     len,
                     self.type_param_mode,
@@ -840,6 +851,7 @@ impl<'a> TyLoweringContext<'a> {
                             const_or_path_to_chalk(
                                 self.db,
                                 self.resolver,
+                                self.owner,
                                 ty,
                                 c,
                                 self.type_param_mode,
@@ -1356,8 +1368,8 @@ pub(crate) fn field_types_query(
     };
     let generics = generics(db.upcast(), def);
     let mut res = ArenaMap::default();
-    let ctx =
-        TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
+    let ctx = TyLoweringContext::new(db, &resolver, GenericDefId::from(variant_id.adt_id()).into())
+        .with_type_param_mode(ParamLoweringMode::Variable);
     for (field_id, field_data) in var_data.fields().iter() {
         res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(&field_data.type_ref)));
     }
@@ -1379,8 +1391,8 @@ pub(crate) fn generic_predicates_for_param_query(
     assoc_name: Option<Name>,
 ) -> Arc<[Binders<QuantifiedWhereClause>]> {
     let resolver = def.resolver(db.upcast());
-    let ctx =
-        TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
+    let ctx = TyLoweringContext::new(db, &resolver, def.into())
+        .with_type_param_mode(ParamLoweringMode::Variable);
     let generics = generics(db.upcast(), def);
     let mut predicates: Vec<_> = resolver
         .where_predicates_in_scope()
@@ -1468,8 +1480,8 @@ pub(crate) fn trait_environment_query(
     def: GenericDefId,
 ) -> Arc<TraitEnvironment> {
     let resolver = def.resolver(db.upcast());
-    let ctx =
-        TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Placeholder);
+    let ctx = TyLoweringContext::new(db, &resolver, def.into())
+        .with_type_param_mode(ParamLoweringMode::Placeholder);
     let mut traits_in_scope = Vec::new();
     let mut clauses = Vec::new();
     for pred in resolver.where_predicates_in_scope() {
@@ -1527,8 +1539,8 @@ pub(crate) fn generic_predicates_query(
     def: GenericDefId,
 ) -> Arc<[Binders<QuantifiedWhereClause>]> {
     let resolver = def.resolver(db.upcast());
-    let ctx =
-        TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
+    let ctx = TyLoweringContext::new(db, &resolver, def.into())
+        .with_type_param_mode(ParamLoweringMode::Variable);
     let generics = generics(db.upcast(), def);
 
     let mut predicates = resolver
@@ -1582,8 +1594,8 @@ pub(crate) fn generic_defaults_query(
     def: GenericDefId,
 ) -> Arc<[Binders<chalk_ir::GenericArg<Interner>>]> {
     let resolver = def.resolver(db.upcast());
-    let ctx =
-        TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
+    let ctx = TyLoweringContext::new(db, &resolver, def.into())
+        .with_type_param_mode(ParamLoweringMode::Variable);
     let generic_params = generics(db.upcast(), def);
     let parent_start_idx = generic_params.len_self();
 
@@ -1648,11 +1660,11 @@ pub(crate) fn generic_defaults_recover(
 fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
     let data = db.function_data(def);
     let resolver = def.resolver(db.upcast());
-    let ctx_params = TyLoweringContext::new(db, &resolver)
+    let ctx_params = TyLoweringContext::new(db, &resolver, def.into())
         .with_impl_trait_mode(ImplTraitLoweringMode::Variable)
         .with_type_param_mode(ParamLoweringMode::Variable);
     let params = data.params.iter().map(|tr| ctx_params.lower_ty(tr)).collect::<Vec<_>>();
-    let ctx_ret = TyLoweringContext::new(db, &resolver)
+    let ctx_ret = TyLoweringContext::new(db, &resolver, def.into())
         .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
         .with_type_param_mode(ParamLoweringMode::Variable);
     let ret = ctx_ret.lower_ty(&data.ret_type);
@@ -1683,8 +1695,8 @@ fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> Binders<Ty> {
     let data = db.const_data(def);
     let generics = generics(db.upcast(), def.into());
     let resolver = def.resolver(db.upcast());
-    let ctx =
-        TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
+    let ctx = TyLoweringContext::new(db, &resolver, def.into())
+        .with_type_param_mode(ParamLoweringMode::Variable);
 
     make_binders(db, &generics, ctx.lower_ty(&data.type_ref))
 }
@@ -1693,7 +1705,7 @@ fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> Binders<Ty> {
 fn type_for_static(db: &dyn HirDatabase, def: StaticId) -> Binders<Ty> {
     let data = db.static_data(def);
     let resolver = def.resolver(db.upcast());
-    let ctx = TyLoweringContext::new(db, &resolver);
+    let ctx = TyLoweringContext::new(db, &resolver, def.into());
 
     Binders::empty(Interner, ctx.lower_ty(&data.type_ref))
 }
@@ -1702,8 +1714,8 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
     let struct_data = db.struct_data(def);
     let fields = struct_data.variant_data.fields();
     let resolver = def.resolver(db.upcast());
-    let ctx =
-        TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
+    let ctx = TyLoweringContext::new(db, &resolver, AdtId::from(def).into())
+        .with_type_param_mode(ParamLoweringMode::Variable);
     let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
     let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders();
     Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe))
@@ -1715,7 +1727,7 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders<T
     if let StructKind::Unit = struct_data.variant_data.kind() {
         return type_for_adt(db, def.into());
     }
-    let generics = generics(db.upcast(), def.into());
+    let generics = generics(db.upcast(), AdtId::from(def).into());
     let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
     make_binders(
         db,
@@ -1729,8 +1741,8 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId)
     let var_data = &enum_data.variants[def.local_id];
     let fields = var_data.variant_data.fields();
     let resolver = def.parent.resolver(db.upcast());
-    let ctx =
-        TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
+    let ctx = TyLoweringContext::new(db, &resolver, DefWithBodyId::VariantId(def).into())
+        .with_type_param_mode(ParamLoweringMode::Variable);
     let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
     let (ret, binders) = type_for_adt(db, def.parent.into()).into_value_and_skipped_binders();
     Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe))
@@ -1762,8 +1774,8 @@ fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
 fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
     let generics = generics(db.upcast(), t.into());
     let resolver = t.resolver(db.upcast());
-    let ctx =
-        TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
+    let ctx = TyLoweringContext::new(db, &resolver, t.into())
+        .with_type_param_mode(ParamLoweringMode::Variable);
     if db.type_alias_data(t).is_extern {
         Binders::empty(Interner, TyKind::Foreign(crate::to_foreign_def_id(t)).intern(Interner))
     } else {
@@ -1884,8 +1896,8 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde
         "impl_self_ty_query({impl_id:?} -> {impl_loc:?} -> {impl_data:?})"
     ));
     let generics = generics(db.upcast(), impl_id.into());
-    let ctx =
-        TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
+    let ctx = TyLoweringContext::new(db, &resolver, impl_id.into())
+        .with_type_param_mode(ParamLoweringMode::Variable);
     make_binders(db, &generics, ctx.lower_ty(&impl_data.self_ty))
 }
 
@@ -1894,7 +1906,7 @@ pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> T
     let parent_data = db.generic_params(def.parent());
     let data = &parent_data.type_or_consts[def.local_id()];
     let resolver = def.parent().resolver(db.upcast());
-    let ctx = TyLoweringContext::new(db, &resolver);
+    let ctx = TyLoweringContext::new(db, &resolver, def.parent().into());
     match data {
         TypeOrConstParamData::TypeParamData(_) => {
             never!();
@@ -1920,8 +1932,8 @@ pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<
     let _cx = stdx::panic_context::enter(format!(
         "impl_trait_query({impl_id:?} -> {impl_loc:?} -> {impl_data:?})"
     ));
-    let ctx =
-        TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
+    let ctx = TyLoweringContext::new(db, &resolver, impl_id.into())
+        .with_type_param_mode(ParamLoweringMode::Variable);
     let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders();
     let target_trait = impl_data.target_trait.as_ref()?;
     Some(Binders::new(binders, ctx.lower_trait_ref(target_trait, Some(self_ty))?))
@@ -1934,7 +1946,7 @@ pub(crate) fn return_type_impl_traits(
     // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe
     let data = db.function_data(def);
     let resolver = def.resolver(db.upcast());
-    let ctx_ret = TyLoweringContext::new(db, &resolver)
+    let ctx_ret = TyLoweringContext::new(db, &resolver, def.into())
         .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
         .with_type_param_mode(ParamLoweringMode::Variable);
     let _ret = ctx_ret.lower_ty(&data.ret_type);
@@ -1969,7 +1981,7 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
     arg: &'a GenericArg,
     this: &mut T,
     for_type: impl FnOnce(&mut T, &TypeRef) -> Ty + 'a,
-    for_const: impl FnOnce(&mut T, &ConstRefOrPath, Ty) -> Const + 'a,
+    for_const: impl FnOnce(&mut T, &ConstRef, Ty) -> Const + 'a,
 ) -> Option<crate::GenericArg> {
     let kind = match kind_id {
         Either::Left(_) => ParamKind::Type,
@@ -1997,7 +2009,7 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
                 let p = p.mod_path()?;
                 if p.kind == PathKind::Plain {
                     if let [n] = p.segments() {
-                        let c = ConstRefOrPath::Path(n.clone());
+                        let c = ConstRef::Path(n.clone());
                         return Some(
                             GenericArgData::Const(for_const(this, &c, c_ty)).intern(Interner),
                         );
@@ -2013,15 +2025,16 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
 pub(crate) fn const_or_path_to_chalk(
     db: &dyn HirDatabase,
     resolver: &Resolver,
+    owner: TypeOwnerId,
     expected_ty: Ty,
-    value: &ConstRefOrPath,
+    value: &ConstRef,
     mode: ParamLoweringMode,
     args: impl FnOnce() -> Generics,
     debruijn: DebruijnIndex,
 ) -> Const {
     match value {
-        ConstRefOrPath::Scalar(s) => intern_const_ref(db, s, expected_ty, resolver.krate()),
-        ConstRefOrPath::Path(n) => {
+        ConstRef::Scalar(s) => intern_const_ref(db, s, expected_ty, resolver.krate()),
+        ConstRef::Path(n) => {
             let path = ModPath::from_segments(PathKind::Plain, Some(n.clone()));
             path_to_const(
                 db,
@@ -2034,6 +2047,26 @@ pub(crate) fn const_or_path_to_chalk(
             )
             .unwrap_or_else(|| unknown_const(expected_ty))
         }
+        &ConstRef::Complex(x) => {
+            let crate_data = &db.crate_graph()[owner.module(db.upcast()).krate()];
+            if crate_data.env.get("__ra_is_test_fixture").is_none() && crate_data.origin.is_local()
+            {
+                // FIXME: current `InTypeConstId` is very unstable, so we only use it in non local crate
+                // that are unlikely to be edited.
+                return unknown_const(expected_ty);
+            }
+            let c = db
+                .intern_in_type_const((
+                    x,
+                    owner,
+                    Box::new(InTypeConstIdMetadata(expected_ty.clone())),
+                ))
+                .into();
+            intern_const_scalar(
+                ConstScalar::UnevaluatedConst(c, Substitution::empty(Interner)),
+                expected_ty,
+            )
+        }
     }
 }
 
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index 6fa3d1351a9..ab6430e8f19 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -570,7 +570,7 @@ impl ReceiverAdjustments {
                         .intern(Interner);
                     }
                 }
-                never!("unsize_array with non-reference-to-array {:?}", ty);
+                // FIXME: report diagnostic if array unsizing happens without indirection.
                 ty
             };
             adjust.push(Adjustment {
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index aad1a82f298..e3401a36ceb 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -1876,6 +1876,7 @@ pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result<Arc<Mi
         DefWithBodyId::VariantId(it) => {
             db.enum_data(it.parent).variants[it.local_id].name.display(db.upcast()).to_string()
         }
+        DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"),
     });
     let body = db.body(def);
     let infer = db.infer(def);
diff --git a/crates/hir-ty/src/mir/pretty.rs b/crates/hir-ty/src/mir/pretty.rs
index 58662b01b99..ac23e77bd2b 100644
--- a/crates/hir-ty/src/mir/pretty.rs
+++ b/crates/hir-ty/src/mir/pretty.rs
@@ -60,6 +60,9 @@ impl MirBody {
                 let data = db.enum_data(id.parent);
                 w!(this, "enum {} = ", data.name.display(db.upcast()));
             }
+            hir_def::DefWithBodyId::InTypeConstId(id) => {
+                w!(this, "in type const {id:?} = ");
+            }
         });
         ctx.result
     }
diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs
index 2db04024b7b..85714128006 100644
--- a/crates/hir-ty/src/tests.rs
+++ b/crates/hir-ty/src/tests.rs
@@ -146,6 +146,7 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
             let loc = db.lookup_intern_enum(it.parent);
             loc.source(&db).value.syntax().text_range().start()
         }
+        DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(),
     });
     let mut unexpected_type_mismatches = String::new();
     for def in defs {
@@ -391,6 +392,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
             let loc = db.lookup_intern_enum(it.parent);
             loc.source(&db).value.syntax().text_range().start()
         }
+        DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(),
     });
     for def in defs {
         let (body, source_map) = db.body_with_source_map(def);
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index f18c953a7af..047900a324e 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -1955,3 +1955,26 @@ impl Inner<1> {
         "#,
     );
 }
+
+#[test]
+fn dont_crash_on_slice_unsizing() {
+    check_no_mismatches(
+        r#"
+//- minicore: slice, unsize, coerce_unsized
+trait Tr {
+    fn f(self);
+}
+
+impl Tr for [i32] {
+    fn f(self) {
+        let t;
+        x(t);
+    }
+}
+
+fn x(a: [i32; 4]) {
+    let b = a.f();
+}
+        "#,
+    );
+}
diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs
index 3ece40486dd..fb0aa2faf1f 100644
--- a/crates/hir-ty/src/tests/simple.rs
+++ b/crates/hir-ty/src/tests/simple.rs
@@ -1829,6 +1829,38 @@ impl Foo for u8 {
 }
 
 #[test]
+fn const_eval_in_function_signature() {
+    check_types(
+        r#"
+const fn foo() -> usize {
+    5
+}
+
+fn f() -> [u8; foo()] {
+    loop {}
+}
+
+fn main() {
+    let t = f();
+      //^ [u8; 5]
+}"#,
+    );
+    check_types(
+        r#"
+//- minicore: default, builtin_impls
+fn f() -> [u8; Default::default()] {
+    loop {}
+}
+
+fn main() {
+    let t = f();
+      //^ [u8; 0]
+}
+    "#,
+    );
+}
+
+#[test]
 fn shadowing_primitive_with_inner_items() {
     check_types(
         r#"
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index 681d087ede6..3636580630d 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -1,7 +1,7 @@
 //! Helper functions for working with def, which don't need to be a separate
 //! query, but can't be computed directly from `*Data` (ie, which need a `db`).
 
-use std::iter;
+use std::{hash::Hash, iter};
 
 use base_db::CrateId;
 use chalk_ir::{
@@ -20,7 +20,8 @@ use hir_def::{
     resolver::{HasResolver, TypeNs},
     type_ref::{TraitBoundModifier, TypeRef},
     ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId,
-    LocalEnumVariantId, Lookup, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
+    LocalEnumVariantId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId,
+    TypeParamId,
 };
 use hir_expand::name::Name;
 use intern::Interned;
@@ -464,3 +465,28 @@ pub(crate) fn detect_variant_from_bytes<'a>(
     };
     Some((var_id, var_layout))
 }
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub(crate) struct InTypeConstIdMetadata(pub(crate) Ty);
+
+impl OpaqueInternableThing for InTypeConstIdMetadata {
+    fn dyn_hash(&self, mut state: &mut dyn std::hash::Hasher) {
+        self.hash(&mut state);
+    }
+
+    fn dyn_eq(&self, other: &dyn OpaqueInternableThing) -> bool {
+        other.as_any().downcast_ref::<Self>().map_or(false, |x| self == x)
+    }
+
+    fn dyn_clone(&self) -> Box<dyn OpaqueInternableThing> {
+        Box::new(self.clone())
+    }
+
+    fn as_any(&self) -> &dyn std::any::Any {
+        self
+    }
+
+    fn box_any(&self) -> Box<dyn std::any::Any> {
+        Box::new(self.clone())
+    }
+}
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs
index 883e6a29b06..de23902199f 100644
--- a/crates/hir/src/from_id.rs
+++ b/crates/hir/src/from_id.rs
@@ -40,6 +40,7 @@ from_id![
     (hir_def::TraitAliasId, crate::TraitAlias),
     (hir_def::StaticId, crate::Static),
     (hir_def::ConstId, crate::Const),
+    (hir_def::InTypeConstId, crate::InTypeConst),
     (hir_def::FunctionId, crate::Function),
     (hir_def::ImplId, crate::Impl),
     (hir_def::TypeOrConstParamId, crate::TypeOrConstParam),
@@ -144,6 +145,7 @@ impl From<DefWithBody> for DefWithBodyId {
             DefWithBody::Static(it) => DefWithBodyId::StaticId(it.id),
             DefWithBody::Const(it) => DefWithBodyId::ConstId(it.id),
             DefWithBody::Variant(it) => DefWithBodyId::VariantId(it.into()),
+            DefWithBody::InTypeConst(it) => DefWithBodyId::InTypeConstId(it.id),
         }
     }
 }
@@ -155,6 +157,7 @@ impl From<DefWithBodyId> for DefWithBody {
             DefWithBodyId::StaticId(it) => DefWithBody::Static(it.into()),
             DefWithBodyId::ConstId(it) => DefWithBody::Const(it.into()),
             DefWithBodyId::VariantId(it) => DefWithBody::Variant(it.into()),
+            DefWithBodyId::InTypeConstId(it) => DefWithBody::InTypeConst(it.into()),
         }
     }
 }
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 5527eb59387..a11e25c79a2 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -52,9 +52,10 @@ use hir_def::{
     resolver::{HasResolver, Resolver},
     src::HasSource as _,
     AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
-    EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
-    LocalEnumVariantId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId,
-    TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
+    EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, InTypeConstId, ItemContainerId,
+    LifetimeParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId,
+    StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
+    UnionId,
 };
 use hir_expand::{name::name, MacroCallKind};
 use hir_ty::{
@@ -1375,8 +1376,9 @@ pub enum DefWithBody {
     Static(Static),
     Const(Const),
     Variant(Variant),
+    InTypeConst(InTypeConst),
 }
-impl_from!(Function, Const, Static, Variant for DefWithBody);
+impl_from!(Function, Const, Static, Variant, InTypeConst for DefWithBody);
 
 impl DefWithBody {
     pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -1385,6 +1387,7 @@ impl DefWithBody {
             DefWithBody::Function(f) => f.module(db),
             DefWithBody::Static(s) => s.module(db),
             DefWithBody::Variant(v) => v.module(db),
+            DefWithBody::InTypeConst(c) => c.module(db),
         }
     }
 
@@ -1394,6 +1397,7 @@ impl DefWithBody {
             DefWithBody::Static(s) => Some(s.name(db)),
             DefWithBody::Const(c) => c.name(db),
             DefWithBody::Variant(v) => Some(v.name(db)),
+            DefWithBody::InTypeConst(_) => None,
         }
     }
 
@@ -1404,6 +1408,11 @@ impl DefWithBody {
             DefWithBody::Static(it) => it.ty(db),
             DefWithBody::Const(it) => it.ty(db),
             DefWithBody::Variant(it) => it.parent.variant_body_ty(db),
+            DefWithBody::InTypeConst(it) => Type::new_with_resolver_inner(
+                db,
+                &DefWithBodyId::from(it.id).resolver(db.upcast()),
+                TyKind::Error.intern(Interner),
+            ),
         }
     }
 
@@ -1413,6 +1422,7 @@ impl DefWithBody {
             DefWithBody::Static(it) => it.id.into(),
             DefWithBody::Const(it) => it.id.into(),
             DefWithBody::Variant(it) => it.into(),
+            DefWithBody::InTypeConst(it) => it.id.into(),
         }
     }
 
@@ -1797,6 +1807,8 @@ impl DefWithBody {
             DefWithBody::Static(it) => it.into(),
             DefWithBody::Const(it) => it.into(),
             DefWithBody::Variant(it) => it.into(),
+            // FIXME: don't ignore diagnostics for in type const
+            DefWithBody::InTypeConst(_) => return,
         };
         for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) {
             acc.push(diag.into())
@@ -2086,6 +2098,17 @@ impl HasVisibility for Function {
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct InTypeConst {
+    pub(crate) id: InTypeConstId,
+}
+
+impl InTypeConst {
+    pub fn module(self, db: &dyn HirDatabase) -> Module {
+        Module { id: self.id.lookup(db.upcast()).1.module(db.upcast()) }
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct Const {
     pub(crate) id: ConstId,
 }
@@ -2515,7 +2538,7 @@ impl AsAssocItem for DefWithBody {
         match self {
             DefWithBody::Function(it) => it.as_assoc_item(db),
             DefWithBody::Const(it) => it.as_assoc_item(db),
-            DefWithBody::Static(_) | DefWithBody::Variant(_) => None,
+            DefWithBody::Static(_) | DefWithBody::Variant(_) | DefWithBody::InTypeConst(_) => None,
         }
     }
 }
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 36ded659b46..5a76a9185a2 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -1070,8 +1070,12 @@ impl<'db> SemanticsImpl<'db> {
     fn resolve_type(&self, ty: &ast::Type) -> Option<Type> {
         let analyze = self.analyze(ty.syntax())?;
         let ctx = LowerCtx::with_file_id(self.db.upcast(), analyze.file_id);
-        let ty = hir_ty::TyLoweringContext::new(self.db, &analyze.resolver)
-            .lower_ty(&crate::TypeRef::from_ast(&ctx, ty.clone()));
+        let ty = hir_ty::TyLoweringContext::new(
+            self.db,
+            &analyze.resolver,
+            analyze.resolver.module().into(),
+        )
+        .lower_ty(&crate::TypeRef::from_ast(&ctx, ty.clone()));
         Some(Type::new_with_resolver(self.db, &analyze.resolver, ty))
     }
 
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 1374fa332c6..ecb1b306a66 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -38,8 +38,8 @@ use hir_ty::{
         UnsafeExpr,
     },
     lang_items::lang_items_for_bin_op,
-    method_resolution::{self},
-    Adjustment, InferenceResult, Interner, Substitution, Ty, TyExt, TyKind, TyLoweringContext,
+    method_resolution, Adjustment, InferenceResult, Interner, Substitution, Ty, TyExt, TyKind,
+    TyLoweringContext,
 };
 use itertools::Itertools;
 use smallvec::SmallVec;
@@ -978,7 +978,8 @@ fn resolve_hir_path_(
     let types = || {
         let (ty, unresolved) = match path.type_anchor() {
             Some(type_ref) => {
-                let (_, res) = TyLoweringContext::new(db, resolver).lower_ty_ext(type_ref);
+                let (_, res) = TyLoweringContext::new(db, resolver, resolver.module().into())
+                    .lower_ty_ext(type_ref);
                 res.map(|ty_ns| (ty_ns, path.segments().first()))
             }
             None => {
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index 207e8206c92..43d957412bc 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -233,6 +233,7 @@ impl<'a> SymbolCollector<'a> {
             DefWithBodyId::VariantId(id) => {
                 Some(self.db.enum_data(id.parent).variants[id.local_id].name.to_smol_str())
             }
+            DefWithBodyId::InTypeConstId(_) => Some("in type const".into()),
         }
     }
 
diff --git a/crates/ide-assists/src/handlers/extract_type_alias.rs b/crates/ide-assists/src/handlers/extract_type_alias.rs
index 71b45d88cb8..b6e7d6209c9 100644
--- a/crates/ide-assists/src/handlers/extract_type_alias.rs
+++ b/crates/ide-assists/src/handlers/extract_type_alias.rs
@@ -158,7 +158,7 @@ fn collect_used_generics<'gp>(
                     .and_then(|lt| known_generics.iter().find(find_lifetime(&lt.text()))),
             ),
             ast::Type::ArrayType(ar) => {
-                if let Some(ast::Expr::PathExpr(p)) = ar.expr() {
+                if let Some(ast::Expr::PathExpr(p)) = ar.const_arg().and_then(|x| x.expr()) {
                     if let Some(path) = p.path() {
                         if let Some(name_ref) = path.as_single_name_ref() {
                             if let Some(param) = known_generics.iter().find(|gp| {
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index 73cd5dcaf23..e8ff107bd49 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -243,6 +243,8 @@ impl Definition {
                 DefWithBody::Const(c) => c.source(db).map(|src| src.syntax().cloned()),
                 DefWithBody::Static(s) => s.source(db).map(|src| src.syntax().cloned()),
                 DefWithBody::Variant(v) => v.source(db).map(|src| src.syntax().cloned()),
+                // FIXME: implement
+                DefWithBody::InTypeConst(_) => return SearchScope::empty(),
             };
             return match def {
                 Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)),
diff --git a/crates/ide/src/inlay_hints/chaining.rs b/crates/ide/src/inlay_hints/chaining.rs
index ce1e03a069b..fd4e347d259 100644
--- a/crates/ide/src/inlay_hints/chaining.rs
+++ b/crates/ide/src/inlay_hints/chaining.rs
@@ -474,7 +474,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9332..9340,
+                                        range: 9333..9341,
                                     },
                                 ),
                                 tooltip: "",
@@ -487,7 +487,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9364..9368,
+                                        range: 9365..9369,
                                     },
                                 ),
                                 tooltip: "",
@@ -511,7 +511,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9332..9340,
+                                        range: 9333..9341,
                                     },
                                 ),
                                 tooltip: "",
@@ -524,7 +524,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9364..9368,
+                                        range: 9365..9369,
                                     },
                                 ),
                                 tooltip: "",
@@ -548,7 +548,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9332..9340,
+                                        range: 9333..9341,
                                     },
                                 ),
                                 tooltip: "",
@@ -561,7 +561,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9364..9368,
+                                        range: 9365..9369,
                                     },
                                 ),
                                 tooltip: "",
diff --git a/crates/parser/src/grammar/types.rs b/crates/parser/src/grammar/types.rs
index 93ef4835027..96a6cdeaaff 100644
--- a/crates/parser/src/grammar/types.rs
+++ b/crates/parser/src/grammar/types.rs
@@ -153,7 +153,9 @@ fn array_or_slice_type(p: &mut Parser<'_>) {
         // type T = [(); 92];
         T![;] => {
             p.bump(T![;]);
+            let m = p.start();
             expressions::expr(p);
+            m.complete(p, CONST_ARG);
             p.expect(T![']']);
             ARRAY_TYPE
         }
diff --git a/crates/parser/test_data/parser/inline/ok/0017_array_type.rast b/crates/parser/test_data/parser/inline/ok/0017_array_type.rast
index 2a5c644d467..0d50144b730 100644
--- a/crates/parser/test_data/parser/inline/ok/0017_array_type.rast
+++ b/crates/parser/test_data/parser/inline/ok/0017_array_type.rast
@@ -14,8 +14,9 @@ SOURCE_FILE
         R_PAREN ")"
       SEMICOLON ";"
       WHITESPACE " "
-      LITERAL
-        INT_NUMBER "92"
+      CONST_ARG
+        LITERAL
+          INT_NUMBER "92"
       R_BRACK "]"
     SEMICOLON ";"
   WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/ok/0030_traits.rast b/crates/parser/test_data/parser/ok/0030_traits.rast
index 44423581e6a..3965ae9596b 100644
--- a/crates/parser/test_data/parser/ok/0030_traits.rast
+++ b/crates/parser/test_data/parser/ok/0030_traits.rast
@@ -51,8 +51,9 @@ SOURCE_FILE
                       IDENT "i32"
               SEMICOLON ";"
               WHITESPACE " "
-              LITERAL
-                INT_NUMBER "1"
+              CONST_ARG
+                LITERAL
+                  INT_NUMBER "1"
               R_BRACK "]"
           R_PAREN ")"
         SEMICOLON ";"
diff --git a/crates/parser/test_data/parser/ok/0043_complex_assignment.rast b/crates/parser/test_data/parser/ok/0043_complex_assignment.rast
index 3b02c3f96ae..f3c85b45b6b 100644
--- a/crates/parser/test_data/parser/ok/0043_complex_assignment.rast
+++ b/crates/parser/test_data/parser/ok/0043_complex_assignment.rast
@@ -24,8 +24,9 @@ SOURCE_FILE
                   IDENT "u8"
           SEMICOLON ";"
           WHITESPACE " "
-          LITERAL
-            INT_NUMBER "1"
+          CONST_ARG
+            LITERAL
+              INT_NUMBER "1"
           R_BRACK "]"
       WHITESPACE " "
       R_CURLY "}"
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 0aca620a675..b5fe237fc4c 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -1403,6 +1403,12 @@ fn handle_hack_cargo_workspace(
             .unwrap();
         crate_graph.remove_and_replace(fake, original).unwrap();
     }
+    for (_, c) in crate_graph.iter_mut() {
+        if c.origin.is_local() {
+            // LangCrateOrigin::Other is good enough for a hack.
+            c.origin = CrateOrigin::Lang(LangCrateOrigin::Other);
+        }
+    }
     sysroot
         .crates()
         .filter_map(|krate| {
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 2c2a9a18d2e..4c0a08d926b 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -328,14 +328,21 @@ impl flags::AnalysisStats {
         let analysis = host.analysis();
         for f in funcs.iter().copied() {
             let name = f.name(db);
-            let full_name = f
-                .module(db)
-                .path_to_root(db)
+            let module = f.module(db);
+            let full_name = module
+                .krate()
+                .display_name(db)
+                .map(|x| x.canonical_name().to_string())
                 .into_iter()
-                .rev()
-                .filter_map(|it| it.name(db))
-                .chain(Some(f.name(db)))
-                .map(|it| it.display(db).to_string())
+                .chain(
+                    module
+                        .path_to_root(db)
+                        .into_iter()
+                        .filter_map(|it| it.name(db))
+                        .rev()
+                        .chain(Some(f.name(db)))
+                        .map(|it| it.display(db).to_string()),
+                )
                 .join("::");
             if let Some(only_name) = self.only.as_deref() {
                 if name.display(db).to_string() != only_name && full_name != only_name {
diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram
index 4c9027dec68..b096c997448 100644
--- a/crates/syntax/rust.ungram
+++ b/crates/syntax/rust.ungram
@@ -565,7 +565,7 @@ RefType =
   '&' Lifetime? 'mut'? Type
 
 ArrayType =
-  '[' Type ';' Expr ']'
+  '[' Type ';' ConstArg ']'
 
 SliceType =
   '[' Type ']'
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 61f6a04c98d..e520801ea2e 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -1207,7 +1207,7 @@ impl ArrayType {
     pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
     pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
     pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn const_arg(&self) -> Option<ConstArg> { support::child(&self.syntax) }
     pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
 }
 
diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs
index c79b4e966d6..1484a4497a4 100644
--- a/crates/test-utils/src/minicore.rs
+++ b/crates/test-utils/src/minicore.rs
@@ -32,6 +32,7 @@
 //!     include:
 //!     index: sized
 //!     infallible:
+//!     int_impl: size_of, transmute
 //!     iterator: option
 //!     iterators: iterator, fn
 //!     manually_drop: drop
@@ -44,6 +45,7 @@
 //!     range:
 //!     result:
 //!     send: sized
+//!     size_of: sized
 //!     sized:
 //!     slice:
 //!     sync: sized
@@ -345,6 +347,12 @@ pub mod mem {
         pub fn transmute<Src, Dst>(src: Src) -> Dst;
     }
     // endregion:transmute
+
+    // region:size_of
+    extern "rust-intrinsic" {
+        pub fn size_of<T>() -> usize;
+    }
+    // endregion:size_of
 }
 
 pub mod ptr {
@@ -1307,6 +1315,25 @@ impl bool {
 }
 // endregion:bool_impl
 
+// region:int_impl
+macro_rules! impl_int {
+    ($($t:ty)*) => {
+        $(
+            impl $t {
+                pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+                    unsafe { mem::transmute(bytes) }
+                }
+            }
+        )*
+    }
+}
+
+impl_int! {
+    usize u8 u16 u32 u64 u128
+    isize i8 i16 i32 i64 i128
+}
+// endregion:int_impl
+
 // region:error
 pub mod error {
     #[rustc_has_incoherent_inherent_impls]