Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22048 from ChayimFriedman2/upgrade-rustc
internal: Upgrade rustc crates
Chayim Refael Friedman 5 weeks ago
parent 94421fe · parent 20b02ef · commit 1e7decd
-rw-r--r--Cargo.lock71
-rw-r--r--Cargo.toml23
-rw-r--r--crates/hir-def/src/attrs.rs44
-rw-r--r--crates/hir-def/src/hir.rs10
-rw-r--r--crates/hir-ty/src/builtin_derive.rs22
-rw-r--r--crates/hir-ty/src/consteval.rs251
-rw-r--r--crates/hir-ty/src/consteval/tests.rs43
-rw-r--r--crates/hir-ty/src/db.rs8
-rw-r--r--crates/hir-ty/src/display.rs181
-rw-r--r--crates/hir-ty/src/dyn_compatibility.rs57
-rw-r--r--crates/hir-ty/src/infer.rs10
-rw-r--r--crates/hir-ty/src/infer/closure.rs2
-rw-r--r--crates/hir-ty/src/infer/coerce.rs2
-rw-r--r--crates/hir-ty/src/infer/unify.rs7
-rw-r--r--crates/hir-ty/src/layout/target.rs31
-rw-r--r--crates/hir-ty/src/lib.rs13
-rw-r--r--crates/hir-ty/src/lower.rs10
-rw-r--r--crates/hir-ty/src/lower/path.rs6
-rw-r--r--crates/hir-ty/src/mir.rs23
-rw-r--r--crates/hir-ty/src/mir/borrowck.rs4
-rw-r--r--crates/hir-ty/src/mir/eval.rs197
-rw-r--r--crates/hir-ty/src/mir/lower.rs37
-rw-r--r--crates/hir-ty/src/mir/monomorphization.rs17
-rw-r--r--crates/hir-ty/src/mir/pretty.rs3
-rw-r--r--crates/hir-ty/src/next_solver.rs30
-rw-r--r--crates/hir-ty/src/next_solver/allocation.rs73
-rw-r--r--crates/hir-ty/src/next_solver/consts.rs219
-rw-r--r--crates/hir-ty/src/next_solver/consts/valtree.rs712
-rw-r--r--crates/hir-ty/src/next_solver/fold.rs26
-rw-r--r--crates/hir-ty/src/next_solver/fulfill.rs2
-rw-r--r--crates/hir-ty/src/next_solver/fulfill/errors.rs1173
-rw-r--r--crates/hir-ty/src/next_solver/infer/canonical/canonicalizer.rs38
-rw-r--r--crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs14
-rw-r--r--crates/hir-ty/src/next_solver/infer/canonical/mod.rs18
-rw-r--r--crates/hir-ty/src/next_solver/infer/mod.rs18
-rw-r--r--crates/hir-ty/src/next_solver/infer/region_constraints/mod.rs4
-rw-r--r--crates/hir-ty/src/next_solver/infer/relate/generalize.rs2
-rw-r--r--crates/hir-ty/src/next_solver/infer/relate/higher_ranked.rs23
-rw-r--r--crates/hir-ty/src/next_solver/infer/relate/lattice.rs4
-rw-r--r--crates/hir-ty/src/next_solver/inspect.rs6
-rw-r--r--crates/hir-ty/src/next_solver/interner.rs230
-rw-r--r--crates/hir-ty/src/next_solver/ir_print.rs2
-rw-r--r--crates/hir-ty/src/next_solver/normalize.rs1
-rw-r--r--crates/hir-ty/src/next_solver/region.rs136
-rw-r--r--crates/hir-ty/src/next_solver/solver.rs45
-rw-r--r--crates/hir-ty/src/next_solver/ty.rs97
-rw-r--r--crates/hir-ty/src/next_solver/util.rs21
-rw-r--r--crates/hir-ty/src/variance.rs2
-rw-r--r--crates/hir/src/lib.rs47
-rw-r--r--crates/hir/src/source_analyzer.rs12
50 files changed, 1827 insertions, 2200 deletions
diff --git a/Cargo.lock b/Cargo.lock
index da530b3a93..94e9507c02 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -458,9 +458,9 @@ dependencies = [
[[package]]
name = "derive-where"
-version = "1.6.0"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f"
+checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534"
dependencies = [
"proc-macro2",
"quote",
@@ -2048,9 +2048,9 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "ra-ap-rustc_abi"
-version = "0.143.0"
+version = "0.160.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d49dbe5d570793b3c3227972a6ac85fc3e830f09b32c3cb3b68cfceebad3b0a"
+checksum = "4b917ab47d7036977be4c984321af3e0de089229404d68ea9a286f50aa464697"
dependencies = [
"bitflags 2.9.4",
"ra-ap-rustc_hashes",
@@ -2060,33 +2060,33 @@ dependencies = [
[[package]]
name = "ra-ap-rustc_ast_ir"
-version = "0.143.0"
+version = "0.160.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd0956db62c264a899d15667993cbbd2e8f0b02108712217e2579c61ac30b94b"
+checksum = "021d80bea67458b8c90cc25bfdca6f911ea818a41905e370c1f310cced1dd07e"
[[package]]
name = "ra-ap-rustc_hashes"
-version = "0.143.0"
+version = "0.160.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7df512084c24f4c96c8cc9a59cbd264301efbc8913d3759b065398024af316c9"
+checksum = "8bb89395306ecfc980d252f77a4038d8b8bb578a25c856b545cbeeb3fde8358e"
dependencies = [
"rustc-stable-hash",
]
[[package]]
name = "ra-ap-rustc_index"
-version = "0.143.0"
+version = "0.160.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bca3a49a928d38ba7927605e5909b6abe77d09ff359e4695c070c3f91d69cc8a"
+checksum = "84219d028a1954c4340ddde11adffe93eb83e476e942718fe926f4d99637cbbe"
dependencies = [
"ra-ap-rustc_index_macros",
]
[[package]]
name = "ra-ap-rustc_index_macros"
-version = "0.143.0"
+version = "0.160.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4463e908a62c64c2a65c1966c2f4995d0e1f8b7dfc85a8b8de2562edf3d89070"
+checksum = "3908fdfa258c663d8ee407e6b4a205b0880e323b533c0df7edceafbd54a02fb6"
dependencies = [
"proc-macro2",
"quote",
@@ -2095,20 +2095,20 @@ dependencies = [
[[package]]
name = "ra-ap-rustc_lexer"
-version = "0.143.0"
+version = "0.160.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "228e01e1b237adb4bd8793487e1c37019c1e526a8f93716d99602301be267056"
+checksum = "34b50f19d5856b8e2b36150e89b53a6102ab096e8044e1f55fd6fef977b10d85"
dependencies = [
"memchr",
+ "unicode-ident",
"unicode-properties",
- "unicode-xid",
]
[[package]]
name = "ra-ap-rustc_next_trait_solver"
-version = "0.143.0"
+version = "0.160.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10d6f91143011d474bb844d268b0784c6a4c6db57743558b83f5ad34511627f1"
+checksum = "76f83dcc451bcee8a99e284a583d5b3d82db5a200107a256a40ef132c4988f1b"
dependencies = [
"derive-where",
"ra-ap-rustc_index",
@@ -2119,19 +2119,19 @@ dependencies = [
[[package]]
name = "ra-ap-rustc_parse_format"
-version = "0.143.0"
+version = "0.160.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37fa8effbc436c0ddd9d7b1421aa3cccf8b94566c841c4e4aa3e09063b8f423f"
+checksum = "f31236bdc6cbcae8af42d0b2db2fa8d812a8715b90a2ba5afb1132b37a4d0bbc"
dependencies = [
"ra-ap-rustc_lexer",
- "rustc-literal-escaper 0.0.5",
+ "rustc-literal-escaper 0.0.7",
]
[[package]]
name = "ra-ap-rustc_pattern_analysis"
-version = "0.143.0"
+version = "0.160.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "883c843fc27847ad03b8e772dd4a2d2728af4333a6d6821a22dfcfe7136dff3e"
+checksum = "3fc4edac740e896fba4b3b4d9c423083e3eac49947732561ddfb2377e1f57829"
dependencies = [
"ra-ap-rustc_index",
"rustc-hash 2.1.1",
@@ -2142,15 +2142,16 @@ dependencies = [
[[package]]
name = "ra-ap-rustc_type_ir"
-version = "0.143.0"
+version = "0.160.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a86e33c46b2b261a173b23f207461a514812a8b2d2d7935bbc685f733eacce10"
+checksum = "8efa119afc1bcadd821b27aa94332abf79c48ac0a972cb78932f63004ba4cdd9"
dependencies = [
"arrayvec",
"bitflags 2.9.4",
"derive-where",
"ena",
"indexmap",
+ "ra-ap-rustc_abi",
"ra-ap-rustc_ast_ir",
"ra-ap-rustc_index",
"ra-ap-rustc_type_ir_macros",
@@ -2162,9 +2163,9 @@ dependencies = [
[[package]]
name = "ra-ap-rustc_type_ir_macros"
-version = "0.143.0"
+version = "0.160.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15034c2fcaa5cf302aea6db20eda0f71fffeb0b372d6073cc50f940e974a2a47"
+checksum = "e6b1dc03abfabc7179393c282892c73a3f0e4bbd5f0b6c87ff42c2b142e68f57"
dependencies = [
"proc-macro2",
"quote",
@@ -2385,9 +2386,9 @@ checksum = "ab03008eb631b703dd16978282ae36c73282e7922fe101a4bd072a40ecea7b8b"
[[package]]
name = "rustc-literal-escaper"
-version = "0.0.5"
+version = "0.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4ee29da77c5a54f42697493cd4c9b9f31b74df666a6c04dfc4fde77abe0438b"
+checksum = "8be87abb9e40db7466e0681dc8ecd9dcfd40360cb10b4c8fe24a7c4c3669b198"
[[package]]
name = "rustc-stable-hash"
@@ -3139,21 +3140,15 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
[[package]]
name = "unicode-ident"
-version = "1.0.19"
+version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "unicode-properties"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.6"
+version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d"
[[package]]
name = "url"
diff --git a/Cargo.toml b/Cargo.toml
index 3b3929df0d..0ae65922d0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -86,14 +86,14 @@ vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
vfs = { path = "./crates/vfs", version = "0.0.0" }
edition = { path = "./crates/edition", version = "0.0.0" }
-ra-ap-rustc_lexer = { version = "0.143", default-features = false }
-ra-ap-rustc_parse_format = { version = "0.143", default-features = false }
-ra-ap-rustc_index = { version = "0.143", default-features = false }
-ra-ap-rustc_abi = { version = "0.143", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.143", default-features = false }
-ra-ap-rustc_ast_ir = { version = "0.143", default-features = false }
-ra-ap-rustc_type_ir = { version = "0.143", default-features = false }
-ra-ap-rustc_next_trait_solver = { version = "0.143", default-features = false }
+ra-ap-rustc_lexer = { version = "0.160", default-features = false }
+ra-ap-rustc_parse_format = { version = "0.160", default-features = false }
+ra-ap-rustc_index = { version = "0.160", default-features = false }
+ra-ap-rustc_abi = { version = "0.160", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.160", default-features = false }
+ra-ap-rustc_ast_ir = { version = "0.160", default-features = false }
+ra-ap-rustc_type_ir = { version = "0.160", default-features = false }
+ra-ap-rustc_next_trait_solver = { version = "0.160", default-features = false }
# local crates that aren't published to crates.io. These should not have versions.
@@ -127,7 +127,7 @@ object = { version = "0.36.7", default-features = false, features = [
"macho",
"pe",
] }
-postcard = {version = "1.1.3", features = ["alloc"]}
+postcard = { version = "1.1.3", features = ["alloc"] }
process-wrap = { version = "8.2.1", features = ["std"] }
pulldown-cmark-to-cmark = "10.0.4"
pulldown-cmark = { version = "0.9.6", default-features = false }
@@ -186,7 +186,10 @@ hashbrown = { version = "0.14.*", features = [
elided_lifetimes_in_paths = "warn"
explicit_outlives_requirements = "warn"
unsafe_op_in_unsafe_fn = "warn"
-unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bootstrap)', "cfg(no_salsa_async_drops)"] }
+unexpected_cfgs = { level = "warn", check-cfg = [
+ 'cfg(bootstrap)',
+ "cfg(no_salsa_async_drops)",
+] }
unused_extern_crates = "warn"
unused_lifetimes = "warn"
unreachable_pub = "warn"
diff --git a/crates/hir-def/src/attrs.rs b/crates/hir-def/src/attrs.rs
index 9da5b98d83..f5f483d6af 100644
--- a/crates/hir-def/src/attrs.rs
+++ b/crates/hir-def/src/attrs.rs
@@ -159,7 +159,7 @@ fn match_attr_flags(attr_flags: &mut AttrFlags, attr: ast::Meta) -> ControlFlow<
None => match &*first_segment {
"deprecated" => attr_flags.insert(AttrFlags::IS_DEPRECATED),
"doc" => extract_doc_tt_attr(attr_flags, tt),
- "repr" => attr_flags.insert(AttrFlags::HAS_REPR),
+ "repr" | "rustc_scalable_vector" => attr_flags.insert(AttrFlags::HAS_REPR),
"target_feature" => attr_flags.insert(AttrFlags::HAS_TARGET_FEATURE),
"proc_macro_derive" | "rustc_builtin_macro" => {
attr_flags.insert(AttrFlags::IS_DERIVE_OR_BUILTIN_MACRO)
@@ -217,6 +217,7 @@ fn match_attr_flags(attr_flags: &mut AttrFlags, attr: ast::Meta) -> ControlFlow<
"rustc_allow_incoherent_impl" => {
attr_flags.insert(AttrFlags::RUSTC_ALLOW_INCOHERENT_IMPL)
}
+ "rustc_scalable_vector" => attr_flags.insert(AttrFlags::HAS_REPR),
"fundamental" => attr_flags.insert(AttrFlags::FUNDAMENTAL),
"no_std" => attr_flags.insert(AttrFlags::IS_NO_STD),
"may_dangle" => attr_flags.insert(AttrFlags::MAY_DANGLE),
@@ -724,14 +725,40 @@ impl AttrFlags {
fn repr(db: &dyn DefDatabase, owner: AdtId) -> Option<ReprOptions> {
let mut result = None;
collect_attrs::<Infallible>(db, owner.into(), |attr| {
- if let ast::Meta::TokenTreeMeta(attr) = attr
- && attr.path().is1("repr")
+ let mut current = None;
+ if let ast::Meta::TokenTreeMeta(attr) = &attr
+ && let Some(path) = attr.path()
&& let Some(tt) = attr.token_tree()
- && let Some(repr) = parse_repr_tt(&tt)
{
+ if path.is1("repr")
+ && let Some(repr) = parse_repr_tt(&tt)
+ {
+ current = Some(repr);
+ } else if path.is1("rustc_scalable_vector")
+ && let mut tt = TokenTreeChildren::new(&tt)
+ && let Some(NodeOrToken::Token(scalable)) = tt.next()
+ && let Some(scalable) = ast::IntNumber::cast(scalable)
+ && let Ok(scalable) = scalable.value()
+ && let Ok(scalable) = scalable.try_into()
+ {
+ current = Some(ReprOptions {
+ scalable: Some(rustc_abi::ScalableElt::ElementCount(scalable)),
+ ..ReprOptions::default()
+ });
+ }
+ } else if let ast::Meta::PathMeta(attr) = &attr
+ && attr.path().is1("rustc_scalable_vector")
+ {
+ current = Some(ReprOptions {
+ scalable: Some(rustc_abi::ScalableElt::Container),
+ ..ReprOptions::default()
+ });
+ }
+
+ if let Some(current) = current {
match &mut result {
- Some(existing) => merge_repr(existing, repr),
- None => result = Some(repr),
+ Some(existing) => merge_repr(existing, current),
+ None => result = Some(current),
}
}
ControlFlow::Continue(())
@@ -1114,7 +1141,7 @@ impl AttrFlags {
}
fn merge_repr(this: &mut ReprOptions, other: ReprOptions) {
- let ReprOptions { int, align, pack, flags, field_shuffle_seed: _ } = this;
+ let ReprOptions { int, align, pack, flags, scalable, field_shuffle_seed: _ } = this;
flags.insert(other.flags);
*align = (*align).max(other.align);
*pack = match (*pack, other.pack) {
@@ -1124,6 +1151,9 @@ fn merge_repr(this: &mut ReprOptions, other: ReprOptions) {
if other.int.is_some() {
*int = other.int;
}
+ if other.scalable.is_some() {
+ *scalable = other.scalable;
+ }
}
fn parse_repr_tt(tt: &ast::TokenTree) -> Option<ReprOptions> {
diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs
index 4dd113d419..9e51d0eac9 100644
--- a/crates/hir-def/src/hir.rs
+++ b/crates/hir-def/src/hir.rs
@@ -21,7 +21,7 @@ use std::fmt;
use hir_expand::{MacroDefId, name::Name};
use intern::Symbol;
use la_arena::Idx;
-use rustc_apfloat::ieee::{Half as f16, Quad as f128};
+use rustc_apfloat::ieee::{Double, Half, Quad, Single};
use syntax::ast;
use type_ref::TypeRefId;
@@ -94,19 +94,19 @@ impl FloatTypeWrapper {
Self(sym)
}
- pub fn to_f128(&self) -> f128 {
+ pub fn to_f128(&self) -> Quad {
self.0.as_str().parse().unwrap_or_default()
}
- pub fn to_f64(&self) -> f64 {
+ pub fn to_f64(&self) -> Double {
self.0.as_str().parse().unwrap_or_default()
}
- pub fn to_f32(&self) -> f32 {
+ pub fn to_f32(&self) -> Single {
self.0.as_str().parse().unwrap_or_default()
}
- pub fn to_f16(&self) -> f16 {
+ pub fn to_f16(&self) -> Half {
self.0.as_str().parse().unwrap_or_default()
}
}
diff --git a/crates/hir-ty/src/builtin_derive.rs b/crates/hir-ty/src/builtin_derive.rs
index eb3922f4b6..6a9b1671e7 100644
--- a/crates/hir-ty/src/builtin_derive.rs
+++ b/crates/hir-ty/src/builtin_derive.rs
@@ -20,8 +20,8 @@ use crate::{
GenericPredicates,
db::HirDatabase,
next_solver::{
- Clause, Clauses, DbInterner, EarlyBinder, GenericArgs, ParamEnv, StoredEarlyBinder,
- StoredTy, TraitRef, Ty, TyKind, fold::fold_tys, generics::Generics,
+ AliasTy, Clause, Clauses, DbInterner, EarlyBinder, GenericArgs, ParamEnv,
+ StoredEarlyBinder, StoredTy, TraitRef, Ty, TyKind, fold::fold_tys, generics::Generics,
},
};
@@ -342,7 +342,7 @@ fn extend_assoc_type_bounds<'db>(
type Result = ();
fn visit_ty(&mut self, t: Ty<'db>) -> Self::Result {
- if let TyKind::Alias(AliasTyKind::Projection, _) = t.kind() {
+ if let TyKind::Alias(AliasTy { kind: AliasTyKind::Projection { .. }, .. }) = t.kind() {
self.assoc_type_bounds.push(
TraitRef::new_from_args(
self.interner,
@@ -546,49 +546,49 @@ struct WithGenerics<'a, T: Trait, const N: usize>(&'a [T; N], T::Assoc);
Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Debug, polarity:Positive), bound_vars: [] })
- Clause(Binder { value: TraitPredicate(Alias(Projection, AliasTy { args: [#1], def_id: TypeAliasId("Assoc"), .. }): Debug, polarity:Positive), bound_vars: [] })
+ Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): Debug, polarity:Positive), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Clone, polarity:Positive), bound_vars: [] })
- Clause(Binder { value: TraitPredicate(Alias(Projection, AliasTy { args: [#1], def_id: TypeAliasId("Assoc"), .. }): Clone, polarity:Positive), bound_vars: [] })
+ Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): Clone, polarity:Positive), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Copy, polarity:Positive), bound_vars: [] })
- Clause(Binder { value: TraitPredicate(Alias(Projection, AliasTy { args: [#1], def_id: TypeAliasId("Assoc"), .. }): Copy, polarity:Positive), bound_vars: [] })
+ Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): Copy, polarity:Positive), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: PartialEq<[#1]>, polarity:Positive), bound_vars: [] })
- Clause(Binder { value: TraitPredicate(Alias(Projection, AliasTy { args: [#1], def_id: TypeAliasId("Assoc"), .. }): PartialEq<[Alias(Projection, AliasTy { args: [#1], def_id: TypeAliasId("Assoc"), .. })]>, polarity:Positive), bound_vars: [] })
+ Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): PartialEq<[Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. })]>, polarity:Positive), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Eq, polarity:Positive), bound_vars: [] })
- Clause(Binder { value: TraitPredicate(Alias(Projection, AliasTy { args: [#1], def_id: TypeAliasId("Assoc"), .. }): Eq, polarity:Positive), bound_vars: [] })
+ Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): Eq, polarity:Positive), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: PartialOrd<[#1]>, polarity:Positive), bound_vars: [] })
- Clause(Binder { value: TraitPredicate(Alias(Projection, AliasTy { args: [#1], def_id: TypeAliasId("Assoc"), .. }): PartialOrd<[Alias(Projection, AliasTy { args: [#1], def_id: TypeAliasId("Assoc"), .. })]>, polarity:Positive), bound_vars: [] })
+ Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): PartialOrd<[Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. })]>, polarity:Positive), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Ord, polarity:Positive), bound_vars: [] })
- Clause(Binder { value: TraitPredicate(Alias(Projection, AliasTy { args: [#1], def_id: TypeAliasId("Assoc"), .. }): Ord, polarity:Positive), bound_vars: [] })
+ Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): Ord, polarity:Positive), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
Clause(Binder { value: TraitPredicate(#1: Hash, polarity:Positive), bound_vars: [] })
- Clause(Binder { value: TraitPredicate(Alias(Projection, AliasTy { args: [#1], def_id: TypeAliasId("Assoc"), .. }): Hash, polarity:Positive), bound_vars: [] })
+ Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): Hash, polarity:Positive), bound_vars: [] })
"#]],
);
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index 928396c63a..80e7e05d76 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/crates/hir-ty/src/consteval.rs
@@ -8,28 +8,30 @@ use hir_def::{
ConstId, EnumVariantId, ExpressionStoreOwnerId, GeneralConstId, GenericDefId, HasModule,
StaticId,
attrs::AttrFlags,
- builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
expr_store::{Body, ExpressionStore},
hir::{Expr, ExprId, Literal},
};
use hir_expand::Lookup;
+use rustc_abi::Size;
+use rustc_apfloat::Float;
use rustc_type_ir::inherent::IntoKind;
+use stdx::never;
use triomphe::Arc;
use crate::{
- LifetimeElisionKind, MemoryMap, ParamEnvAndCrate, TyLoweringContext,
+ LifetimeElisionKind, ParamEnvAndCrate, TyLoweringContext,
db::HirDatabase,
display::DisplayTarget,
infer::InferenceContext,
- mir::{MirEvalError, MirLowerError},
+ mir::{MirEvalError, MirLowerError, pad16},
next_solver::{
- Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs,
- StoredConst, StoredGenericArgs, Ty, ValueConst,
+ Allocation, Const, ConstKind, Consts, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs,
+ ScalarInt, StoredAllocation, StoredGenericArgs, Ty, TyKind, ValTreeKind, default_types,
},
traits::StoredParamEnvAndCrate,
};
-use super::mir::{interpret_mir, lower_body_to_mir, pad16};
+use super::mir::{interpret_mir, lower_body_to_mir};
pub fn unknown_const<'db>(_ty: Ty<'db>) -> Const<'db> {
Const::new(DbInterner::conjure(), rustc_type_ir::ConstKind::Error(ErrorGuaranteed))
@@ -84,140 +86,87 @@ pub fn intern_const_ref<'a>(
db: &'a dyn HirDatabase,
value: &Literal,
ty: Ty<'a>,
- _krate: Crate,
+ krate: Crate,
) -> Const<'a> {
let interner = DbInterner::new_no_crate(db);
- let kind = match value {
- &Literal::Uint(i, builtin_ty)
- if builtin_ty.is_none() || ty.as_builtin() == builtin_ty.map(BuiltinType::Uint) =>
- {
- let memory = match ty.as_builtin() {
- Some(BuiltinType::Uint(builtin_uint)) => match builtin_uint {
- BuiltinUint::U8 => Box::new([i as u8]) as Box<[u8]>,
- BuiltinUint::U16 => Box::new((i as u16).to_le_bytes()),
- BuiltinUint::U32 => Box::new((i as u32).to_le_bytes()),
- BuiltinUint::U64 => Box::new((i as u64).to_le_bytes()),
- BuiltinUint::U128 => Box::new((i).to_le_bytes()),
- BuiltinUint::Usize => Box::new((i as usize).to_le_bytes()),
- },
- _ => return Const::new(interner, rustc_type_ir::ConstKind::Error(ErrorGuaranteed)),
- };
- rustc_type_ir::ConstKind::Value(ValueConst::new(
- ty,
- ConstBytes { memory, memory_map: MemoryMap::default() },
- ))
+ let Ok(data_layout) = db.target_data_layout(krate) else {
+ return Const::error(interner);
+ };
+ let valtree = match (ty.kind(), value) {
+ (TyKind::Uint(uint), Literal::Uint(value, _)) => {
+ let size = uint.bit_width().map(Size::from_bits).unwrap_or(data_layout.pointer_size());
+ let scalar = ScalarInt::try_from_uint(*value, size).unwrap();
+ ValTreeKind::Leaf(scalar)
}
- &Literal::Int(i, None)
- if ty
- .as_builtin()
- .is_some_and(|builtin_ty| matches!(builtin_ty, BuiltinType::Uint(_))) =>
- {
- let memory = match ty.as_builtin() {
- Some(BuiltinType::Uint(builtin_uint)) => match builtin_uint {
- BuiltinUint::U8 => Box::new([i as u8]) as Box<[u8]>,
- BuiltinUint::U16 => Box::new((i as u16).to_le_bytes()),
- BuiltinUint::U32 => Box::new((i as u32).to_le_bytes()),
- BuiltinUint::U64 => Box::new((i as u64).to_le_bytes()),
- BuiltinUint::U128 => Box::new((i as u128).to_le_bytes()),
- BuiltinUint::Usize => Box::new((i as usize).to_le_bytes()),
- },
- _ => return Const::new(interner, rustc_type_ir::ConstKind::Error(ErrorGuaranteed)),
- };
- rustc_type_ir::ConstKind::Value(ValueConst::new(
- ty,
- ConstBytes { memory, memory_map: MemoryMap::default() },
- ))
+ (TyKind::Uint(uint), Literal::Int(value, _)) => {
+ // `Literal::Int` is the default, so we also need to account for the type being uint.
+ let size = uint.bit_width().map(Size::from_bits).unwrap_or(data_layout.pointer_size());
+ let scalar = ScalarInt::try_from_uint(*value as u128, size).unwrap();
+ ValTreeKind::Leaf(scalar)
}
- &Literal::Int(i, builtin_ty)
- if builtin_ty.is_none() || ty.as_builtin() == builtin_ty.map(BuiltinType::Int) =>
- {
- let memory = match ty.as_builtin() {
- Some(BuiltinType::Int(builtin_int)) => match builtin_int {
- BuiltinInt::I8 => Box::new([i as u8]) as Box<[u8]>,
- BuiltinInt::I16 => Box::new((i as i16).to_le_bytes()),
- BuiltinInt::I32 => Box::new((i as i32).to_le_bytes()),
- BuiltinInt::I64 => Box::new((i as i64).to_le_bytes()),
- BuiltinInt::I128 => Box::new((i).to_le_bytes()),
- BuiltinInt::Isize => Box::new((i as isize).to_le_bytes()),
- },
- _ => return Const::new(interner, rustc_type_ir::ConstKind::Error(ErrorGuaranteed)),
- };
- rustc_type_ir::ConstKind::Value(ValueConst::new(
- ty,
- ConstBytes { memory, memory_map: MemoryMap::default() },
- ))
+ (TyKind::Int(int), Literal::Int(value, _)) => {
+ let size = int.bit_width().map(Size::from_bits).unwrap_or(data_layout.pointer_size());
+ let scalar = ScalarInt::try_from_int(*value, size).unwrap();
+ ValTreeKind::Leaf(scalar)
}
- Literal::Float(float_type_wrapper, builtin_float)
- if builtin_float.is_none()
- || ty.as_builtin() == builtin_float.map(BuiltinType::Float) =>
- {
- let memory = match ty.as_builtin().unwrap() {
- BuiltinType::Float(builtin_float) => match builtin_float {
- // FIXME:
- hir_def::builtin_type::BuiltinFloat::F16 => Box::new([0u8; 2]) as Box<[u8]>,
- hir_def::builtin_type::BuiltinFloat::F32 => {
- Box::new(float_type_wrapper.to_f32().to_le_bytes())
- }
- hir_def::builtin_type::BuiltinFloat::F64 => {
- Box::new(float_type_wrapper.to_f64().to_le_bytes())
- }
- // FIXME:
- hir_def::builtin_type::BuiltinFloat::F128 => Box::new([0; 16]),
- },
- _ => unreachable!(),
+ (TyKind::Bool, Literal::Bool(value)) => ValTreeKind::Leaf(ScalarInt::from(*value)),
+ (TyKind::Char, Literal::Char(value)) => ValTreeKind::Leaf(ScalarInt::from(*value)),
+ (TyKind::Float(float), Literal::Float(value, _)) => {
+ let size = Size::from_bits(float.bit_width());
+ let value = match float {
+ rustc_ast_ir::FloatTy::F16 => value.to_f16().to_bits(),
+ rustc_ast_ir::FloatTy::F32 => value.to_f32().to_bits(),
+ rustc_ast_ir::FloatTy::F64 => value.to_f64().to_bits(),
+ rustc_ast_ir::FloatTy::F128 => value.to_f128().to_bits(),
};
- rustc_type_ir::ConstKind::Value(ValueConst::new(
- ty,
- ConstBytes { memory, memory_map: MemoryMap::default() },
+ let scalar = ScalarInt::try_from_uint(value, size).unwrap();
+ ValTreeKind::Leaf(scalar)
+ }
+ (_, Literal::String(value)) => {
+ let u8_values = &interner.default_types().consts.u8_values;
+ ValTreeKind::Branch(Consts::new_from_iter(
+ interner,
+ value.as_str().as_bytes().iter().map(|&byte| u8_values[usize::from(byte)]),
))
}
- Literal::Bool(b) if ty.is_bool() => rustc_type_ir::ConstKind::Value(ValueConst::new(
- ty,
- ConstBytes { memory: Box::new([*b as u8]), memory_map: MemoryMap::default() },
- )),
- Literal::Char(c) if ty.is_char() => rustc_type_ir::ConstKind::Value(ValueConst::new(
- ty,
- ConstBytes {
- memory: (*c as u32).to_le_bytes().into(),
- memory_map: MemoryMap::default(),
- },
- )),
- Literal::String(symbol) if ty.is_str() => rustc_type_ir::ConstKind::Value(ValueConst::new(
- ty,
- ConstBytes {
- memory: symbol.as_str().as_bytes().into(),
- memory_map: MemoryMap::default(),
- },
- )),
- Literal::ByteString(items) if ty.as_slice().is_some_and(|ty| ty.is_u8()) => {
- rustc_type_ir::ConstKind::Value(ValueConst::new(
- ty,
- ConstBytes { memory: items.clone(), memory_map: MemoryMap::default() },
+ (_, Literal::ByteString(value)) => {
+ let u8_values = &interner.default_types().consts.u8_values;
+ ValTreeKind::Branch(Consts::new_from_iter(
+ interner,
+ value.iter().map(|&byte| u8_values[usize::from(byte)]),
))
}
- // FIXME
- Literal::CString(_items) => rustc_type_ir::ConstKind::Error(ErrorGuaranteed),
- _ => rustc_type_ir::ConstKind::Error(ErrorGuaranteed),
+ (_, Literal::CString(_)) => {
+ // FIXME:
+ return Const::error(interner);
+ }
+ _ => {
+ never!("mismatching type for literal");
+ return Const::error(interner);
+ }
};
- Const::new(interner, kind)
+ Const::new_valtree(interner, ty, valtree)
}
/// Interns a possibly-unknown target usize
pub fn usize_const<'db>(db: &'db dyn HirDatabase, value: Option<u128>, krate: Crate) -> Const<'db> {
- intern_const_ref(
- db,
- &match value {
- Some(value) => Literal::Uint(value, Some(BuiltinUint::Usize)),
- None => {
- return Const::new(
- DbInterner::new_no_crate(db),
- rustc_type_ir::ConstKind::Error(ErrorGuaranteed),
- );
- }
- },
- Ty::new_uint(DbInterner::new_no_crate(db), rustc_type_ir::UintTy::Usize),
- krate,
- )
+ let interner = DbInterner::new_no_crate(db);
+ let value = match value {
+ Some(value) => value,
+ None => {
+ return Const::error(interner);
+ }
+ };
+ let Ok(data_layout) = db.target_data_layout(krate) else {
+ return Const::error(interner);
+ };
+ let usize_ty = interner.default_types().types.usize;
+ let scalar = ScalarInt::try_from_uint(value, data_layout.pointer_size()).unwrap();
+ Const::new_valtree(interner, usize_ty, ValTreeKind::Leaf(scalar))
+}
+
+pub fn allocation_as_usize(ec: Allocation<'_>) -> u128 {
+ u128::from_le_bytes(pad16(&ec.memory, false))
}
pub fn try_const_usize<'db>(db: &'db dyn HirDatabase, c: Const<'db>) -> Option<u128> {
@@ -230,20 +179,30 @@ pub fn try_const_usize<'db>(db: &'db dyn HirDatabase, c: Const<'db>) -> Option<u
GeneralConstId::ConstId(id) => {
let subst = unevaluated_const.args;
let ec = db.const_eval(id, subst, None).ok()?;
- try_const_usize(db, ec)
+ Some(allocation_as_usize(ec))
}
GeneralConstId::StaticId(id) => {
let ec = db.const_eval_static(id).ok()?;
- try_const_usize(db, ec)
+ Some(allocation_as_usize(ec))
}
GeneralConstId::AnonConstId(_) => None,
},
- ConstKind::Value(val) => Some(u128::from_le_bytes(pad16(&val.value.inner().memory, false))),
+ ConstKind::Value(val) => {
+ if val.ty == default_types(db).types.usize {
+ Some(val.value.inner().to_leaf().to_uint_unchecked())
+ } else {
+ None
+ }
+ }
ConstKind::Error(_) => None,
ConstKind::Expr(_) => None,
}
}
+pub fn allocation_as_isize(ec: Allocation<'_>) -> i128 {
+ i128::from_le_bytes(pad16(&ec.memory, true))
+}
+
pub fn try_const_isize<'db>(db: &'db dyn HirDatabase, c: &Const<'db>) -> Option<i128> {
match (*c).kind() {
ConstKind::Param(_) => None,
@@ -254,15 +213,21 @@ pub fn try_const_isize<'db>(db: &'db dyn HirDatabase, c: &Const<'db>) -> Option<
GeneralConstId::ConstId(id) => {
let subst = unevaluated_const.args;
let ec = db.const_eval(id, subst, None).ok()?;
- try_const_isize(db, &ec)
+ Some(allocation_as_isize(ec))
}
GeneralConstId::StaticId(id) => {
let ec = db.const_eval_static(id).ok()?;
- try_const_isize(db, &ec)
+ Some(allocation_as_isize(ec))
}
GeneralConstId::AnonConstId(_) => None,
},
- ConstKind::Value(val) => Some(i128::from_le_bytes(pad16(&val.value.inner().memory, true))),
+ ConstKind::Value(val) => {
+ if val.ty == default_types(db).types.isize {
+ Some(val.value.inner().to_leaf().to_int_unchecked())
+ } else {
+ None
+ }
+ }
ConstKind::Error(_) => None,
ConstKind::Expr(_) => None,
}
@@ -299,11 +264,7 @@ pub(crate) fn const_eval_discriminant_variant(
.store(),
)?;
let c = interpret_mir(db, mir_body, false, None)?.0?;
- let c = if is_signed {
- try_const_isize(db, &c).unwrap()
- } else {
- try_const_usize(db, c).unwrap() as i128
- };
+ let c = if is_signed { allocation_as_isize(c) } else { allocation_as_usize(c) as i128 };
Ok(c)
}
@@ -341,7 +302,11 @@ pub(crate) fn eval_to_const<'db>(expr: ExprId, ctx: &mut InferenceContext<'_, 'd
lower_body_to_mir(ctx.db, body_owner, Body::of(ctx.db, body_owner), &infer, expr)
&& let Ok((Ok(result), _)) = interpret_mir(ctx.db, Arc::new(mir_body), true, None)
{
- return result;
+ return Const::new_from_allocation(
+ ctx.interner(),
+ &result,
+ ParamEnvAndCrate { param_env: ctx.table.param_env, krate: ctx.resolver.krate() },
+ );
}
Const::error(ctx.interner())
}
@@ -359,7 +324,7 @@ pub(crate) fn const_eval<'db>(
def: ConstId,
subst: GenericArgs<'db>,
trait_env: Option<ParamEnvAndCrate<'db>>,
-) -> Result<Const<'db>, ConstEvalError> {
+) -> Result<Allocation<'db>, ConstEvalError> {
return match const_eval_query(db, def, subst.store(), trait_env.map(|env| env.store())) {
Ok(konst) => Ok(konst.as_ref()),
Err(err) => Err(err.clone()),
@@ -371,7 +336,7 @@ pub(crate) fn const_eval<'db>(
def: ConstId,
subst: StoredGenericArgs,
trait_env: Option<StoredParamEnvAndCrate>,
- ) -> Result<StoredConst, ConstEvalError> {
+ ) -> Result<StoredAllocation, ConstEvalError> {
let body = db.monomorphized_mir_body(
def.into(),
subst,
@@ -392,7 +357,7 @@ pub(crate) fn const_eval<'db>(
_: ConstId,
_: StoredGenericArgs,
_: Option<StoredParamEnvAndCrate>,
- ) -> Result<StoredConst, ConstEvalError> {
+ ) -> Result<StoredAllocation, ConstEvalError> {
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
}
}
@@ -400,7 +365,7 @@ pub(crate) fn const_eval<'db>(
pub(crate) fn const_eval_static<'db>(
db: &'db dyn HirDatabase,
def: StaticId,
-) -> Result<Const<'db>, ConstEvalError> {
+) -> Result<Allocation<'db>, ConstEvalError> {
return match const_eval_static_query(db, def) {
Ok(konst) => Ok(konst.as_ref()),
Err(err) => Err(err.clone()),
@@ -410,7 +375,7 @@ pub(crate) fn const_eval_static<'db>(
pub(crate) fn const_eval_static_query<'db>(
db: &'db dyn HirDatabase,
def: StaticId,
- ) -> Result<StoredConst, ConstEvalError> {
+ ) -> Result<StoredAllocation, ConstEvalError> {
let interner = DbInterner::new_no_crate(db);
let body = db.monomorphized_mir_body(
def.into(),
@@ -430,7 +395,7 @@ pub(crate) fn const_eval_static<'db>(
_: &dyn HirDatabase,
_: salsa::Id,
_: StaticId,
- ) -> Result<StoredConst, ConstEvalError> {
+ ) -> Result<StoredAllocation, ConstEvalError> {
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
}
}
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index aee27dcfde..5d5b5a8e64 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -5,17 +5,16 @@ use rustc_apfloat::{
Float,
ieee::{Half as f16, Quad as f128},
};
-use rustc_type_ir::inherent::IntoKind;
use test_fixture::WithFixture;
use test_utils::skip_slow_tests;
use crate::{
MemoryMap,
- consteval::try_const_usize,
+ consteval::allocation_as_usize,
db::HirDatabase,
display::DisplayTarget,
mir::pad16,
- next_solver::{Const, ConstBytes, ConstKind, DbInterner, GenericArgs},
+ next_solver::{Allocation, DbInterner, GenericArgs},
setup_tracing,
test_db::TestDB,
};
@@ -45,7 +44,11 @@ fn check_fail(
crate::attach_db(&db, || match eval_goal(&db, file_id) {
Ok(_) => panic!("Expected fail, but it succeeded"),
Err(e) => {
- assert!(error(simplify(e.clone())), "Actual error was: {}", pretty_print_err(e, &db))
+ assert!(
+ error(simplify(e.clone())),
+ "Actual error was: {}\n{e:?}",
+ pretty_print_err(e.clone(), &db)
+ )
}
})
}
@@ -94,13 +97,7 @@ fn check_answer(
panic!("Error in evaluating goal: {err}");
}
};
- match r.kind() {
- ConstKind::Value(value) => {
- let ConstBytes { memory, memory_map } = value.value.inner();
- check(memory, memory_map);
- }
- _ => panic!("Expected number but found {r:?}"),
- }
+ check(&r.memory, &r.memory_map);
});
}
@@ -121,7 +118,7 @@ fn pretty_print_err(e: ConstEvalError, db: &TestDB) -> String {
err
}
-fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result<Const<'_>, ConstEvalError> {
+fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result<Allocation<'_>, ConstEvalError> {
let _tracing = setup_tracing();
let interner = DbInterner::new_no_crate(db);
let module_id = db.module_for_file(file_id.file_id(db));
@@ -2524,7 +2521,7 @@ fn enums() {
);
crate::attach_db(&db, || {
let r = eval_goal(&db, file_id).unwrap();
- assert_eq!(try_const_usize(&db, r), Some(1));
+ assert_eq!(allocation_as_usize(r), 1);
})
}
@@ -2537,7 +2534,15 @@ fn const_loop() {
const F2: i32 = 2 * F1;
const GOAL: i32 = F3;
"#,
- |e| e == ConstEvalError::MirLowerError(MirLowerError::Loop),
+ |e| {
+ if let ConstEvalError::MirEvalError(MirEvalError::ConstEvalError(_, inner)) = e
+ && let ConstEvalError::MirLowerError(MirLowerError::Loop) = *inner
+ {
+ true
+ } else {
+ false
+ }
+ },
);
}
@@ -2940,6 +2945,14 @@ fn recursive_adt() {
TAG_TREE
};
"#,
- |e| matches!(e, ConstEvalError::MirLowerError(MirLowerError::Loop)),
+ |e| {
+ if let ConstEvalError::MirEvalError(MirEvalError::ConstEvalError(_, inner)) = e
+ && let ConstEvalError::MirLowerError(MirLowerError::Loop) = *inner
+ {
+ true
+ } else {
+ false
+ }
+ },
);
}
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index 54c4b8d3ac..3bf2d9a6a6 100644
--- a/crates/hir-ty/src/db.rs
+++ b/crates/hir-ty/src/db.rs
@@ -21,8 +21,8 @@ use crate::{
lower::{Diagnostics, GenericDefaults},
mir::{BorrowckResult, MirBody, MirLowerError},
next_solver::{
- Const, EarlyBinder, GenericArgs, ParamEnv, PolyFnSig, StoredEarlyBinder, StoredGenericArgs,
- StoredTy, TraitRef, Ty, VariancesOf,
+ Allocation, EarlyBinder, GenericArgs, ParamEnv, PolyFnSig, StoredEarlyBinder,
+ StoredGenericArgs, StoredTy, TraitRef, Ty, VariancesOf,
},
traits::{ParamEnvAndCrate, StoredParamEnvAndCrate},
};
@@ -68,11 +68,11 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
def: ConstId,
subst: GenericArgs<'db>,
trait_env: Option<ParamEnvAndCrate<'db>>,
- ) -> Result<Const<'db>, ConstEvalError>;
+ ) -> Result<Allocation<'db>, ConstEvalError>;
#[salsa::invoke(crate::consteval::const_eval_static)]
#[salsa::transparent]
- fn const_eval_static<'db>(&'db self, def: StaticId) -> Result<Const<'db>, ConstEvalError>;
+ fn const_eval_static<'db>(&'db self, def: StaticId) -> Result<Allocation<'db>, ConstEvalError>;
#[salsa::invoke(crate::consteval::const_eval_discriminant_variant)]
#[salsa::cycle(cycle_result = crate::consteval::const_eval_discriminant_cycle_result)]
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 7f1b1ecbd2..1e9ac5dce6 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -54,9 +54,10 @@ use crate::{
lower::GenericPredicates,
mir::pad16,
next_solver::{
- AliasTy, Clause, ClauseKind, Const, ConstKind, DbInterner, ExistentialPredicate, FnSig,
- GenericArg, GenericArgKind, GenericArgs, ParamEnv, PolyFnSig, Region, SolverDefId,
- StoredEarlyBinder, StoredTy, Term, TermKind, TraitRef, Ty, TyKind, TypingMode,
+ AliasTy, Allocation, Clause, ClauseKind, Const, ConstKind, DbInterner,
+ ExistentialPredicate, FnSig, GenericArg, GenericArgKind, GenericArgs, ParamEnv, PolyFnSig,
+ Region, SolverDefId, StoredEarlyBinder, StoredTy, Term, TermKind, TraitRef, Ty, TyKind,
+ TypingMode, ValTree,
abi::Safety,
infer::{DbInternerInferExt, traits::ObligationCause},
},
@@ -646,7 +647,7 @@ fn write_projection<'db>(
ClauseKind::TypeOutlives(t) => t.0,
_ => return false,
};
- let TyKind::Alias(AliasTyKind::Projection, a) = ty.kind() else {
+ let TyKind::Alias(a) = ty.kind() else {
return false;
};
a == *alias
@@ -657,7 +658,7 @@ fn write_projection<'db>(
write_bounds_like_dyn_trait_with_prefix(
f,
"impl",
- Either::Left(Ty::new_alias(f.interner, AliasTyKind::Projection, *alias)),
+ Either::Left(Ty::new_alias(f.interner, *alias)),
&bounds,
SizedByDefault::NotSized,
needs_parens_if_multi,
@@ -673,7 +674,7 @@ fn write_projection<'db>(
write!(
f,
">::{}",
- TypeAliasSignature::of(f.db, alias.def_id.expect_type_alias())
+ TypeAliasSignature::of(f.db, alias.kind.def_id().expect_type_alias())
.name
.display(f.db, f.edition())
)?;
@@ -691,6 +692,12 @@ impl<'db> HirDisplay<'db> for GenericArg<'db> {
}
}
+impl<'db> HirDisplay<'db> for Allocation<'db> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
+ render_const_scalar(f, &self.memory, &self.memory_map, self.ty)
+ }
+}
+
impl<'db> HirDisplay<'db> for Const<'db> {
fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
match self.kind() {
@@ -710,12 +717,7 @@ impl<'db> HirDisplay<'db> for Const<'db> {
f.end_location_link();
Ok(())
}
- ConstKind::Value(const_bytes) => render_const_scalar(
- f,
- &const_bytes.value.inner().memory,
- &const_bytes.value.inner().memory_map,
- const_bytes.ty,
- ),
+ ConstKind::Value(value) => render_const_scalar_from_valtree(f, value.ty, value.value),
ConstKind::Unevaluated(unev) => {
let c = unev.def.0;
write!(f, "{}", c.name(f.db))?;
@@ -1005,7 +1007,7 @@ fn render_const_scalar_inner<'db>(
TyKind::Pat(_, _) => f.write_str("<pat>"),
TyKind::Error(..)
| TyKind::Placeholder(_)
- | TyKind::Alias(_, _)
+ | TyKind::Alias(..)
| TyKind::Param(_)
| TyKind::Bound(_, _)
| TyKind::Infer(_) => f.write_str("<placeholder-or-unknown-type>"),
@@ -1014,6 +1016,151 @@ fn render_const_scalar_inner<'db>(
}
}
+fn render_const_scalar_from_valtree<'db>(
+ f: &mut HirFormatter<'_, 'db>,
+ ty: Ty<'db>,
+ valtree: ValTree<'db>,
+) -> Result {
+ let param_env = ParamEnv::empty();
+ let infcx = f.interner.infer_ctxt().build(TypingMode::PostAnalysis);
+ let ty = infcx.at(&ObligationCause::new(), param_env).deeply_normalize(ty).unwrap_or(ty);
+ render_const_scalar_from_valtree_inner(f, ty, valtree, param_env)
+}
+
+fn render_const_scalar_from_valtree_inner<'db>(
+ f: &mut HirFormatter<'_, 'db>,
+ ty: Ty<'db>,
+ valtree: ValTree<'db>,
+ _param_env: ParamEnv<'db>,
+) -> Result {
+ use TyKind;
+ match ty.kind() {
+ TyKind::Bool => write!(f, "{}", valtree.inner().to_leaf().try_to_bool().unwrap()),
+ TyKind::Char => {
+ let it = valtree.inner().to_leaf().to_u32();
+ let Ok(c) = char::try_from(it) else {
+ return f.write_str("<unicode-error>");
+ };
+ write!(f, "{c:?}")
+ }
+ TyKind::Int(_) => {
+ let it = valtree.inner().to_leaf().to_int_unchecked();
+ write!(f, "{it}")
+ }
+ TyKind::Uint(_) => {
+ let it = valtree.inner().to_leaf().to_uint_unchecked();
+ write!(f, "{it}")
+ }
+ TyKind::Float(fl) => match fl {
+ FloatTy::F16 => {
+ // FIXME(#17451): Replace with builtins once they are stabilised.
+ let it = f16::from_bits(valtree.inner().to_leaf().to_u16() as u128);
+ let s = it.to_string();
+ if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {
+ // Match Rust debug formatting
+ write!(f, "{s}.0")
+ } else {
+ write!(f, "{s}")
+ }
+ }
+ FloatTy::F32 => {
+ let it = f32::from_bits(valtree.inner().to_leaf().to_u32());
+ write!(f, "{it:?}")
+ }
+ FloatTy::F64 => {
+ let it = f64::from_bits(valtree.inner().to_leaf().to_u64());
+ write!(f, "{it:?}")
+ }
+ FloatTy::F128 => {
+ // FIXME(#17451): Replace with builtins once they are stabilised.
+ let it = f128::from_bits(valtree.inner().to_leaf().to_u128());
+ let s = it.to_string();
+ if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {
+ // Match Rust debug formatting
+ write!(f, "{s}.0")
+ } else {
+ write!(f, "{s}")
+ }
+ }
+ },
+ TyKind::Ref(_, inner_ty, _) => {
+ render_const_scalar_from_valtree_inner(f, inner_ty, valtree, _param_env)
+ }
+ TyKind::Str => {
+ let bytes = valtree
+ .inner()
+ .to_branch()
+ .iter()
+ .map(|konst| match konst.kind() {
+ ConstKind::Value(value) => Some(value.value.inner().to_leaf().to_u8()),
+ _ => None,
+ })
+ .collect::<Option<Vec<_>>>();
+ let Some(bytes) = bytes else { return f.write_str("<invalid-str>") };
+ let s = std::str::from_utf8(&bytes).unwrap_or("<utf8-error>");
+ write!(f, "{s:?}")
+ }
+ TyKind::Slice(inner_ty) | TyKind::Array(inner_ty, _) => {
+ let mut first = true;
+ write!(f, "[")?;
+ for item in valtree.inner().to_branch() {
+ if !first {
+ write!(f, ", ")?;
+ } else {
+ first = false;
+ }
+ let ConstKind::Value(value) = item.kind() else {
+ return f.write_str("<invalid-const>");
+ };
+ render_const_scalar_from_valtree_inner(f, inner_ty, value.value, _param_env)?;
+ }
+ write!(f, "]")
+ }
+ TyKind::Tuple(tys) => {
+ let mut first = true;
+ write!(f, "(")?;
+ for (inner_ty, item) in std::iter::zip(tys, valtree.inner().to_branch()) {
+ if !first {
+ write!(f, ", ")?;
+ } else {
+ first = false;
+ }
+ let ConstKind::Value(value) = item.kind() else {
+ return f.write_str("<invalid-const>");
+ };
+ render_const_scalar_from_valtree_inner(f, inner_ty, value.value, _param_env)?;
+ }
+ write!(f, ")")
+ }
+ TyKind::Adt(..) => {
+ // FIXME: ADTs, requires `adt_const_params`.
+ f.write_str("<adt>")
+ }
+ TyKind::FnDef(..) => ty.hir_fmt(f),
+ TyKind::FnPtr(_, _) | TyKind::RawPtr(_, _) => {
+ let it = valtree.inner().to_leaf().to_uint_unchecked();
+ write!(f, "{it:#X} as ")?;
+ ty.hir_fmt(f)
+ }
+ TyKind::Never => f.write_str("!"),
+ TyKind::Closure(_, _) => f.write_str("<closure>"),
+ TyKind::Coroutine(_, _) => f.write_str("<coroutine>"),
+ TyKind::CoroutineWitness(_, _) => f.write_str("<coroutine-witness>"),
+ TyKind::CoroutineClosure(_, _) => f.write_str("<coroutine-closure>"),
+ TyKind::UnsafeBinder(_) => f.write_str("<unsafe-binder>"),
+ // The below arms are unreachable, since const eval will bail out before here.
+ TyKind::Foreign(_) => f.write_str("<extern-type>"),
+ TyKind::Pat(_, _) => f.write_str("<pat>"),
+ TyKind::Error(..)
+ | TyKind::Placeholder(_)
+ | TyKind::Alias(..)
+ | TyKind::Param(_)
+ | TyKind::Bound(_, _)
+ | TyKind::Infer(_) => f.write_str("<placeholder-or-unknown-type>"),
+ TyKind::Dynamic(_, _) => f.write_str("<dyn-trait>"),
+ }
+}
+
fn render_variant_after_name<'db>(
data: &VariantFields,
f: &mut HirFormatter<'_, 'db>,
@@ -1280,7 +1427,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
hir_fmt_generics(f, parameters.as_slice(), Some(def.def_id().0.into()), None)?;
}
- TyKind::Alias(AliasTyKind::Projection, alias_ty) => {
+ TyKind::Alias(alias_ty @ AliasTy { kind: AliasTyKind::Projection { .. }, .. }) => {
write_projection(f, &alias_ty, trait_bounds_need_parens)?
}
TyKind::Foreign(alias) => {
@@ -1289,8 +1436,8 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
write!(f, "{}", type_alias.name.display(f.db, f.edition()))?;
f.end_location_link();
}
- TyKind::Alias(AliasTyKind::Opaque, alias_ty) => {
- let opaque_ty_id = match alias_ty.def_id {
+ TyKind::Alias(alias_ty @ AliasTy { kind: AliasTyKind::Opaque { def_id }, .. }) => {
+ let opaque_ty_id = match def_id {
SolverDefId::InternedOpaqueTyId(id) => id,
_ => unreachable!(),
};
@@ -1585,7 +1732,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
TyKind::CoroutineWitness(..) => write!(f, "{{coroutine witness}}")?,
TyKind::Pat(_, _) => write!(f, "{{pat}}")?,
TyKind::UnsafeBinder(_) => write!(f, "{{unsafe binder}}")?,
- TyKind::Alias(_, _) => write!(f, "{{alias}}")?,
+ TyKind::Alias(..) => write!(f, "{{alias}}")?,
}
Ok(())
}
diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs
index e70918f8e1..ba63343d49 100644
--- a/crates/hir-ty/src/dyn_compatibility.rs
+++ b/crates/hir-ty/src/dyn_compatibility.rs
@@ -21,8 +21,9 @@ use crate::{
db::{HirDatabase, InternedOpaqueTyId},
lower::{GenericPredicates, associated_ty_item_bounds},
next_solver::{
- Binder, Clause, Clauses, DbInterner, EarlyBinder, GenericArgs, Goal, ParamEnv, ParamTy,
- SolverDefId, TraitPredicate, TraitRef, Ty, TypingMode, infer::DbInternerInferExt, mk_param,
+ AliasTy, Binder, Clause, Clauses, DbInterner, EarlyBinder, GenericArgs, Goal, ParamEnv,
+ ParamTy, SolverDefId, TraitPredicate, TraitRef, Ty, TypingMode, infer::DbInternerInferExt,
+ mk_param,
},
traits::next_trait_solve_in_ctxt,
};
@@ -239,30 +240,30 @@ fn contains_illegal_self_type_reference<'db, T: rustc_type_ir::TypeVisitable<DbI
match ty.kind() {
rustc_type_ir::TyKind::Param(param) if param.index == 0 => ControlFlow::Break(()),
rustc_type_ir::TyKind::Param(_) => ControlFlow::Continue(()),
- rustc_type_ir::TyKind::Alias(AliasTyKind::Projection, proj) => {
- match self.allow_self_projection {
- AllowSelfProjection::Yes => {
- let trait_ = proj.trait_def_id(interner);
- let trait_ = match trait_ {
- SolverDefId::TraitId(id) => id,
- _ => unreachable!(),
- };
- if self.super_traits.is_none() {
- self.super_traits = Some(
- elaborate::supertrait_def_ids(interner, self.trait_.into())
- .map(|super_trait| super_trait.0)
- .collect(),
- )
- }
- if self.super_traits.as_ref().is_some_and(|s| s.contains(&trait_)) {
- ControlFlow::Continue(())
- } else {
- ty.super_visit_with(self)
- }
+ rustc_type_ir::TyKind::Alias(
+ proj @ AliasTy { kind: AliasTyKind::Projection { .. }, .. },
+ ) => match self.allow_self_projection {
+ AllowSelfProjection::Yes => {
+ let trait_ = proj.trait_def_id(interner);
+ let trait_ = match trait_ {
+ SolverDefId::TraitId(id) => id,
+ _ => unreachable!(),
+ };
+ if self.super_traits.is_none() {
+ self.super_traits = Some(
+ elaborate::supertrait_def_ids(interner, self.trait_.into())
+ .map(|super_trait| super_trait.0)
+ .collect(),
+ )
+ }
+ if self.super_traits.as_ref().is_some_and(|s| s.contains(&trait_)) {
+ ControlFlow::Continue(())
+ } else {
+ ty.super_visit_with(self)
}
- AllowSelfProjection::No => ty.super_visit_with(self),
}
- }
+ AllowSelfProjection::No => ty.super_visit_with(self),
+ },
_ => ty.super_visit_with(self),
}
}
@@ -503,8 +504,12 @@ fn contains_illegal_impl_trait_in_trait<'db>(
&mut self,
ty: <DbInterner<'db> as rustc_type_ir::Interner>::Ty,
) -> Self::Result {
- if let rustc_type_ir::TyKind::Alias(AliasTyKind::Opaque, op) = ty.kind() {
- let id = match op.def_id {
+ if let rustc_type_ir::TyKind::Alias(AliasTy {
+ kind: AliasTyKind::Opaque { def_id },
+ ..
+ }) = ty.kind()
+ {
+ let id = match def_id {
SolverDefId::InternedOpaqueTyId(id) => id,
_ => unreachable!(),
};
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index bd897113bf..70083dbe3e 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -1674,10 +1674,9 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
Some(res_assoc_ty) => {
let alias = Ty::new_alias(
self.interner(),
- AliasTyKind::Projection,
AliasTy::new(
self.interner(),
- res_assoc_ty.into(),
+ AliasTyKind::Projection { def_id: res_assoc_ty.into() },
iter::once(inner_ty.into()).chain(params.iter().copied()),
),
);
@@ -1728,8 +1727,11 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
let args = self.infcx().fill_rest_fresh_args(assoc_type.into(), trait_ref.args);
let alias = Ty::new_alias(
self.interner(),
- AliasTyKind::Projection,
- AliasTy::new_from_args(self.interner(), assoc_type.into(), args),
+ AliasTy::new_from_args(
+ self.interner(),
+ AliasTyKind::Projection { def_id: assoc_type.into() },
+ args,
+ ),
);
ty = self.table.try_structurally_resolve_type(alias);
segments = segments.skip(1);
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index 2cb936fec3..bebf39b694 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/crates/hir-ty/src/infer/closure.rs
@@ -364,7 +364,7 @@ impl<'db> InferenceContext<'_, 'db> {
closure_kind: ClosureKind,
) -> (Option<PolyFnSig<'db>>, Option<rustc_type_ir::ClosureKind>) {
match expected_ty.kind() {
- TyKind::Alias(rustc_type_ir::Opaque, AliasTy { def_id, args, .. }) => self
+ TyKind::Alias(AliasTy { kind: rustc_type_ir::Opaque { def_id }, args, .. }) => self
.deduce_closure_signature_from_predicates(
expected_ty,
closure_kind,
diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs
index 47a7049248..f92503003b 100644
--- a/crates/hir-ty/src/infer/coerce.rs
+++ b/crates/hir-ty/src/infer/coerce.rs
@@ -1663,7 +1663,7 @@ fn coerce<'db>(
Const::new_bound(
self.interner,
self.debruijn,
- BoundConst { var: BoundVar::from_usize(i) },
+ BoundConst::new(BoundVar::from_usize(i)),
)
},
)
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index d093412b42..35b41f0bbd 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -538,8 +538,11 @@ impl<'db> InferenceTable<'db> {
let proj_args = self.infer_ctxt.fill_rest_fresh_args(output_assoc_type.into(), args);
let projection = Ty::new_alias(
self.interner(),
- rustc_type_ir::AliasTyKind::Projection,
- AliasTy::new_from_args(self.interner(), output_assoc_type.into(), proj_args),
+ AliasTy::new_from_args(
+ self.interner(),
+ rustc_type_ir::Projection { def_id: output_assoc_type.into() },
+ proj_args,
+ ),
);
let pred = Predicate::upcast_from(trait_ref, self.interner());
diff --git a/crates/hir-ty/src/layout/target.rs b/crates/hir-ty/src/layout/target.rs
index b0986c423b..1752b56b0f 100644
--- a/crates/hir-ty/src/layout/target.rs
+++ b/crates/hir-ty/src/layout/target.rs
@@ -2,7 +2,7 @@
use base_db::{Crate, target::TargetLoadError};
use hir_def::layout::TargetDataLayout;
-use rustc_abi::{AddressSpace, AlignFromBytesError, TargetDataLayoutErrors};
+use rustc_abi::{AddressSpace, AlignFromBytesError, TargetDataLayoutError};
use triomphe::Arc;
use crate::db::HirDatabase;
@@ -16,30 +16,29 @@ pub fn target_data_layout_query(
Ok(it) => Ok(Arc::new(it)),
Err(e) => {
Err(match e {
- TargetDataLayoutErrors::InvalidAddressSpace { addr_space, cause, err } => {
+ TargetDataLayoutError::InvalidAddressSpace { addr_space, cause, err } => {
format!(
r#"invalid address space `{addr_space}` for `{cause}` in "data-layout": {err}"#
)
}
- TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => format!(r#"invalid {kind} `{bit}` for `{cause}` in "data-layout": {err}"#),
- TargetDataLayoutErrors::MissingAlignment { cause } => format!(r#"missing alignment for `{cause}` in "data-layout""#),
- TargetDataLayoutErrors::InvalidAlignment { cause, err } => format!(
- r#"invalid alignment for `{cause}` in "data-layout": `{align}` is {err_kind}"#,
- align = err.align(),
- err_kind = match err {
- AlignFromBytesError::NotPowerOfTwo(_) => "not a power of two",
- AlignFromBytesError::TooLarge(_) => "too large",
- }
- ),
- TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => {
+ TargetDataLayoutError::InvalidBits { kind, bit, cause, err } => format!(r#"invalid {kind} `{bit}` for `{cause}` in "data-layout": {err}"#),
+ TargetDataLayoutError::MissingAlignment { cause } => format!(r#"missing alignment for `{cause}` in "data-layout""#),
+ TargetDataLayoutError::InvalidAlignment { cause, err } => {
+ let (align, err_kind) = match err {
+ AlignFromBytesError::NotPowerOfTwo(align) => (align, "not a power of two"),
+ AlignFromBytesError::TooLarge(align) => (align, "too large"),
+ };
+ format!(r#"invalid alignment for `{cause}` in "data-layout": `{align}` is {err_kind}"#)
+ },
+ TargetDataLayoutError::InconsistentTargetArchitecture { dl, target } => {
format!(r#"inconsistent target specification: "data-layout" claims architecture is {dl}-endian, while "target-endian" is `{target}`"#)
}
- TargetDataLayoutErrors::InconsistentTargetPointerWidth {
+ TargetDataLayoutError::InconsistentTargetPointerWidth {
pointer_size,
target,
} => format!(r#"inconsistent target specification: "data-layout" claims pointers are {pointer_size}-bit, while "target-pointer-width" is `{target}`"#),
- TargetDataLayoutErrors::InvalidBitsSize { err } => err,
- TargetDataLayoutErrors::UnknownPointerSpecification { err } => format!(r#"use of unknown pointer specifier in "data-layout": {err}"#),
+ TargetDataLayoutError::InvalidBitsSize { err } => err,
+ TargetDataLayoutError::UnknownPointerSpecification { err } => format!(r#"use of unknown pointer specifier in "data-layout": {err}"#),
}.into())
}
},
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 5086be7330..9198e8b424 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -84,7 +84,7 @@ use crate::{
lower::SupertraitsInfo,
next_solver::{
AliasTy, Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, Canonical,
- CanonicalVarKind, CanonicalVars, ClauseKind, Const, ConstKind, DbInterner, FnSig,
+ CanonicalVarKind, CanonicalVarKinds, ClauseKind, Const, ConstKind, DbInterner, FnSig,
GenericArgs, PolyFnSig, Predicate, Region, RegionKind, TraitRef, Ty, TyKind, Tys, abi,
},
};
@@ -435,7 +435,7 @@ where
ConstKind::Error(_) => {
let var = rustc_type_ir::BoundVar::from_usize(self.vars.len());
self.vars.push(CanonicalVarKind::Const(rustc_type_ir::UniverseIndex::ZERO));
- Ok(Const::new_bound(self.interner, self.binder, BoundConst { var }))
+ Ok(Const::new_bound(self.interner, self.binder, BoundConst::new(var)))
}
ConstKind::Infer(_) => error(),
ConstKind::Bound(BoundVarIndexKind::Bound(index), _) if index > self.binder => {
@@ -479,7 +479,7 @@ where
Canonical {
value,
max_universe: rustc_type_ir::UniverseIndex::ZERO,
- variables: CanonicalVars::new_from_slice(&error_replacer.vars),
+ var_kinds: CanonicalVarKinds::new_from_slice(&error_replacer.vars),
}
}
@@ -551,8 +551,11 @@ pub fn callable_sig_from_fn_trait<'db>(
let trait_ref = TraitRef::new_from_args(table.interner(), fn_once_trait.into(), args);
let projection = Ty::new_alias(
table.interner(),
- rustc_type_ir::AliasTyKind::Projection,
- AliasTy::new_from_args(table.interner(), output_assoc_type.into(), args),
+ AliasTy::new_from_args(
+ table.interner(),
+ rustc_type_ir::Projection { def_id: output_assoc_type.into() },
+ args,
+ ),
);
let pred = Predicate::upcast_from(trait_ref, table.interner());
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index a7b159a5c5..335aff2c1d 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -537,8 +537,11 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
let args = GenericArgs::identity_for_item(self.interner, opaque_ty_id);
Ty::new_alias(
self.interner,
- AliasTyKind::Opaque,
- AliasTy::new_from_args(self.interner, opaque_ty_id, args),
+ AliasTy::new_from_args(
+ self.interner,
+ AliasTyKind::Opaque { def_id: opaque_ty_id },
+ args,
+ ),
)
}
ImplTraitLoweringMode::Disallowed => {
@@ -1039,8 +1042,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
let args = GenericArgs::identity_for_item(interner, def_id);
let self_ty = Ty::new_alias(
self.interner,
- rustc_type_ir::AliasTyKind::Opaque,
- AliasTy::new_from_args(interner, def_id, args),
+ AliasTy::new_from_args(interner, rustc_type_ir::Opaque { def_id }, args),
);
let (predicates, assoc_ty_bounds_start) =
self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| {
diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs
index 889f0792d3..4f70732178 100644
--- a/crates/hir-ty/src/lower/path.rs
+++ b/crates/hir-ty/src/lower/path.rs
@@ -214,10 +214,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
);
Ty::new_alias(
self.ctx.interner,
- AliasTyKind::Projection,
AliasTy::new_from_args(
self.ctx.interner,
- associated_ty.into(),
+ AliasTyKind::Projection { def_id: associated_ty.into() },
args,
),
)
@@ -949,10 +948,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
bound,
Ty::new_alias(
self.ctx.interner,
- AliasTyKind::Projection,
AliasTy::new_from_args(
self.ctx.interner,
- associated_ty.into(),
+ AliasTyKind::Projection { def_id: associated_ty.into() },
args,
),
),
diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs
index a8865cd54e..837a9847af 100644
--- a/crates/hir-ty/src/mir.rs
+++ b/crates/hir-ty/src/mir.rs
@@ -23,8 +23,8 @@ use crate::{
display::{DisplayTarget, HirDisplay},
infer::PointerCast,
next_solver::{
- Const, DbInterner, ErrorGuaranteed, GenericArgs, ParamEnv, StoredConst, StoredGenericArgs,
- StoredTy, Ty, TyKind,
+ Allocation, AllocationData, DbInterner, ErrorGuaranteed, GenericArgs, ParamEnv,
+ StoredAllocation, StoredConst, StoredGenericArgs, StoredTy, Ty, TyKind,
infer::{InferCtxt, traits::ObligationCause},
obligation_ctxt::ObligationCtxt,
},
@@ -107,7 +107,13 @@ pub enum OperandKind {
/// [UCG#188]: https://github.com/rust-lang/unsafe-code-guidelines/issues/188
Move(Place),
/// Constants are already semantically values, and remain unchanged.
- Constant { konst: StoredConst, ty: StoredTy },
+ Constant {
+ konst: StoredConst,
+ ty: StoredTy,
+ },
+ Allocation {
+ allocation: StoredAllocation,
+ },
/// NON STANDARD: This kind of operand returns an immutable reference to that static memory. Rustc
/// handles it with the `Constant` variant somehow.
Static(StaticId),
@@ -115,11 +121,10 @@ pub enum OperandKind {
impl<'db> Operand {
fn from_concrete_const(data: Box<[u8]>, memory_map: MemoryMap<'db>, ty: Ty<'db>) -> Self {
- let interner = DbInterner::conjure();
Operand {
- kind: OperandKind::Constant {
- konst: Const::new_valtree(interner, ty, data, memory_map).store(),
- ty: ty.store(),
+ kind: OperandKind::Allocation {
+ allocation: Allocation::new(AllocationData { ty, memory: data, memory_map })
+ .store(),
},
span: None,
}
@@ -1095,7 +1100,9 @@ impl MirBody {
OperandKind::Copy(p) | OperandKind::Move(p) => {
f(p, store);
}
- OperandKind::Constant { .. } | OperandKind::Static(_) => (),
+ OperandKind::Constant { .. }
+ | OperandKind::Static(_)
+ | OperandKind::Allocation { .. } => (),
}
}
for (_, block) in self.basic_blocks.iter_mut() {
diff --git a/crates/hir-ty/src/mir/borrowck.rs b/crates/hir-ty/src/mir/borrowck.rs
index d843359dcb..664734c85e 100644
--- a/crates/hir-ty/src/mir/borrowck.rs
+++ b/crates/hir-ty/src/mir/borrowck.rs
@@ -160,7 +160,7 @@ fn moved_out_of_ref<'db>(
result.push(MovedOutOfRef { span: op.span.unwrap_or(span), ty: ty.store() });
}
}
- OperandKind::Constant { .. } | OperandKind::Static(_) => (),
+ OperandKind::Constant { .. } | OperandKind::Static(_) | OperandKind::Allocation { .. } => {}
};
for (_, block) in body.basic_blocks.iter() {
db.unwind_if_revision_cancelled();
@@ -254,7 +254,7 @@ fn partially_moved<'db>(
result.push(PartiallyMoved { span, ty: ty.store(), local: p.local });
}
}
- OperandKind::Constant { .. } | OperandKind::Static(_) => (),
+ OperandKind::Constant { .. } | OperandKind::Static(_) | OperandKind::Allocation { .. } => {}
};
for (_, block) in body.basic_blocks.iter() {
db.unwind_if_revision_cancelled();
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index 79b1c5cb7c..22ecbe2fa2 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -21,7 +21,7 @@ use hir_expand::{InFile, mod_path::path, name::Name};
use intern::sym;
use la_arena::ArenaMap;
use macros::GenericTypeVisitable;
-use rustc_abi::TargetDataLayout;
+use rustc_abi::{Size, TargetDataLayout};
use rustc_apfloat::{
Float,
ieee::{Half as f16, Quad as f128},
@@ -46,8 +46,8 @@ use crate::{
layout::{Layout, LayoutError, RustcEnumVariantIdx},
method_resolution::{is_dyn_method, lookup_impl_const},
next_solver::{
- Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArgs, Region,
- StoredConst, StoredTy, Ty, TyKind, TypingMode, UnevaluatedConst, ValueConst,
+ AliasTy, Allocation, AllocationData, Const, ConstKind, DbInterner, ErrorGuaranteed,
+ GenericArgs, Region, StoredTy, Ty, TyKind, TypingMode, UnevaluatedConst, ValTree,
infer::{DbInternerInferExt, InferCtxt, traits::ObligationCause},
obligation_ctxt::ObligationCtxt,
},
@@ -359,7 +359,7 @@ pub enum MirEvalError {
MirLowerErrorForClosure(InternedClosureId, MirLowerError),
TypeIsUnsized(StoredTy, &'static str),
NotSupported(String),
- InvalidConst(StoredConst),
+ InvalidConst,
InFunction(
Box<MirEvalError>,
Vec<(Either<FunctionId, InternedClosureId>, MirSpan, DefWithBodyId)>,
@@ -484,7 +484,7 @@ impl MirEvalError {
| MirEvalError::MirLowerErrorForClosure(_, _)
| MirEvalError::TypeIsUnsized(_, _)
| MirEvalError::NotSupported(_)
- | MirEvalError::InvalidConst(_)
+ | MirEvalError::InvalidConst
| MirEvalError::ExecutionLimitExceeded
| MirEvalError::StackOverflow
| MirEvalError::CoerceUnsizedError(_)
@@ -537,7 +537,7 @@ impl std::fmt::Debug for MirEvalError {
Self::InternalError(arg0) => f.debug_tuple("InternalError").field(arg0).finish(),
Self::InvalidVTableId(arg0) => f.debug_tuple("InvalidVTableId").field(arg0).finish(),
Self::NotSupported(arg0) => f.debug_tuple("NotSupported").field(arg0).finish(),
- Self::InvalidConst(arg0) => f.debug_tuple("InvalidConst").field(&arg0).finish(),
+ Self::InvalidConst => f.write_str("InvalidConst"),
Self::InFunction(e, stack) => {
f.debug_struct("WithStack").field("error", e).field("stack", &stack).finish()
}
@@ -606,10 +606,10 @@ pub fn interpret_mir<'db>(
// (and probably should) do better here, for example by excluding bindings outside of the target expression.
assert_placeholder_ty_is_unused: bool,
trait_env: Option<ParamEnvAndCrate<'db>>,
-) -> Result<'db, (Result<'db, Const<'db>>, MirOutput)> {
+) -> Result<'db, (Result<'db, Allocation<'db>>, MirOutput)> {
let ty = body.locals[return_slot()].ty.as_ref();
let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env)?;
- let it: Result<'db, Const<'db>> = (|| {
+ let it: Result<'db, Allocation<'db>> = (|| {
if evaluator.ptr_size() != size_of::<usize>() {
not_supported!("targets with different pointer size from host");
}
@@ -620,7 +620,7 @@ pub fn interpret_mir<'db>(
ty,
&Locals { ptr: ArenaMap::new(), body, drop_flags: DropFlags::default() },
)?;
- let bytes = bytes.into();
+ let bytes = Box::from(bytes);
let memory_map = if memory_map.memory.is_empty() && evaluator.vtable_map.is_empty() {
MemoryMap::Empty
} else {
@@ -628,7 +628,7 @@ pub fn interpret_mir<'db>(
memory_map.vtable.shrink_to_fit();
MemoryMap::Complex(Box::new(memory_map))
};
- Ok(Const::new_valtree(evaluator.interner(), ty, bytes, memory_map))
+ Ok(Allocation::new(AllocationData { ty, memory: bytes, memory_map }))
})();
Ok((it, MirOutput { stdout: evaluator.stdout, stderr: evaluator.stderr }))
}
@@ -898,6 +898,7 @@ impl<'db> Evaluator<'db> {
Ok(match &o.kind {
OperandKind::Copy(p) | OperandKind::Move(p) => self.place_ty(p, locals)?,
OperandKind::Constant { konst: _, ty } => ty.as_ref(),
+ OperandKind::Allocation { allocation } => allocation.as_ref().ty,
&OperandKind::Static(s) => {
let ty = InferenceResult::of(self.db, DefWithBodyId::from(s))
.expr_ty(Body::of(self.db, s.into()).root_expr());
@@ -1927,19 +1928,152 @@ impl<'db> Evaluator<'db> {
OperandKind::Constant { konst, .. } => {
self.allocate_const_in_heap(locals, konst.as_ref())?
}
+ OperandKind::Allocation { allocation } => {
+ self.allocate_allocation_in_heap(locals, allocation.as_ref())?
+ }
})
}
+ fn allocate_valtree_in_heap(
+ &mut self,
+ ty: Ty<'db>,
+ valtree: ValTree<'db>,
+ ) -> Result<'db, Interval> {
+ match ty.kind() {
+ TyKind::Bool => {
+ let value = valtree.inner().to_leaf().try_to_bool().unwrap();
+ let addr = self.heap_allocate(1, 1)?;
+ self.write_memory(addr, &[u8::from(value)])?;
+ Ok(Interval::new(addr, 1))
+ }
+ TyKind::Char => {
+ let value = valtree.inner().to_leaf().to_u32();
+ let addr = self.heap_allocate(4, 4)?;
+ self.write_memory(addr, &value.to_le_bytes())?;
+ Ok(Interval::new(addr, 4))
+ }
+ TyKind::Int(int_ty) => {
+ let size = int_ty.bit_width().unwrap_or(self.ptr_size() as u64);
+ let value = valtree.inner().to_leaf().to_int(Size::from_bytes(size));
+ let addr = self.heap_allocate(size as usize, size as usize)?;
+ self.write_memory(addr, &value.to_le_bytes()[..size as usize])?;
+ Ok(Interval::new(addr, size as usize))
+ }
+ TyKind::Uint(uint_ty) => {
+ let size = uint_ty.bit_width().unwrap_or(self.ptr_size() as u64);
+ let value = valtree.inner().to_leaf().to_uint(Size::from_bytes(size));
+ let addr = self.heap_allocate(size as usize, size as usize)?;
+ self.write_memory(addr, &value.to_le_bytes()[..size as usize])?;
+ Ok(Interval::new(addr, size as usize))
+ }
+ TyKind::Float(float_ty) => {
+ let size = float_ty.bit_width();
+ let value = valtree.inner().to_leaf().to_uint(Size::from_bytes(size));
+ let addr = self.heap_allocate(size as usize, size as usize)?;
+ self.write_memory(addr, &value.to_le_bytes()[..size as usize])?;
+ Ok(Interval::new(addr, size as usize))
+ }
+ TyKind::RawPtr(..) => {
+ let size = self.ptr_size();
+ let value = valtree.inner().to_leaf().to_uint(Size::from_bytes(size));
+ let addr = self.heap_allocate(size, size)?;
+ self.write_memory(addr, &value.to_le_bytes()[..size])?;
+ Ok(Interval::new(addr, size))
+ }
+ TyKind::Ref(_, inner_ty, _) => match inner_ty.kind() {
+ TyKind::Str => {
+ let bytes = valtree
+ .inner()
+ .to_branch()
+ .iter()
+ .map(|konst| match konst.kind() {
+ ConstKind::Value(value) => Ok(value.value.inner().to_leaf().to_u8()),
+ _ => not_supported!("unsupported const"),
+ })
+ .collect::<Result<'_, Vec<_>>>()?;
+ let bytes_addr = self.heap_allocate(bytes.len(), 1)?;
+ self.write_memory(bytes_addr, &bytes)?;
+ let ref_addr = self.heap_allocate(self.ptr_size() * 2, self.ptr_size())?;
+ self.write_memory(ref_addr, &bytes_addr.to_bytes())?;
+ let mut len = [0; 16];
+ len[..size_of::<usize>()].copy_from_slice(&bytes.len().to_le_bytes());
+ self.write_memory(ref_addr.offset(self.ptr_size()), &len[..self.ptr_size()])?;
+ Ok(Interval::new(ref_addr, self.ptr_size() * 2))
+ }
+ TyKind::Slice(inner_ty) => {
+ let item_layout = self.layout(inner_ty)?;
+ let items = valtree
+ .inner()
+ .to_branch()
+ .iter()
+ .map(|konst| match konst.kind() {
+ ConstKind::Value(value) => {
+ self.allocate_valtree_in_heap(value.ty, value.value)
+ }
+ _ => not_supported!("unsupported const"),
+ })
+ .collect::<Result<'_, Vec<_>>>()?;
+ let items_addr = self.heap_allocate(
+ items.len() * (item_layout.size.bits() as usize),
+ item_layout.align.bits_usize(),
+ )?;
+ for (i, item) in items.iter().enumerate() {
+ self.copy_from_interval(
+ items_addr.offset(i * (item_layout.size.bits() as usize)),
+ *item,
+ )?;
+ }
+ let ref_addr = self.heap_allocate(self.ptr_size() * 2, self.ptr_size())?;
+ self.write_memory(ref_addr, &items_addr.to_bytes())?;
+ let mut len = [0; 16];
+ len[..size_of::<usize>()].copy_from_slice(&items.len().to_le_bytes());
+ self.write_memory(ref_addr.offset(self.ptr_size()), &len[..self.ptr_size()])?;
+ Ok(Interval::new(ref_addr, self.ptr_size() * 2))
+ }
+ TyKind::Dynamic(..) => not_supported!("`dyn Trait` consts not supported yet"),
+ _ => {
+ let inner_addr = self.allocate_valtree_in_heap(inner_ty, valtree)?;
+ let ref_addr = self.heap_allocate(self.ptr_size(), self.ptr_size())?;
+ self.write_memory(ref_addr, &inner_addr.addr.to_bytes())?;
+ Ok(Interval::new(ref_addr, self.ptr_size()))
+ }
+ },
+ TyKind::Adt(_, _) | TyKind::Array(_, _) | TyKind::Tuple(_) => {
+ not_supported!(
+ "ADTs, arrays and tuples are unsupported in consts currently (requires `adt_const_params`)"
+ )
+ }
+ TyKind::Pat(_, _)
+ | TyKind::Slice(_)
+ | TyKind::FnDef(_, _)
+ | TyKind::Foreign(_)
+ | TyKind::Dynamic(_, _)
+ | TyKind::UnsafeBinder(..)
+ | TyKind::FnPtr(..)
+ | TyKind::Closure(_, _)
+ | TyKind::CoroutineClosure(_, _)
+ | TyKind::Coroutine(_, _)
+ | TyKind::CoroutineWitness(_, _)
+ | TyKind::Never
+ | TyKind::Alias(..)
+ | TyKind::Param(_)
+ | TyKind::Bound(..)
+ | TyKind::Placeholder(_)
+ | TyKind::Infer(_)
+ | TyKind::Str
+ | TyKind::Error(_) => not_supported!("unsupported const"),
+ }
+ }
+
#[allow(clippy::double_parens)]
fn allocate_const_in_heap(
&mut self,
locals: &Locals,
konst: Const<'db>,
) -> Result<'db, Interval> {
- let result_owner;
- let value = match konst.kind() {
- ConstKind::Value(value) => value,
- ConstKind::Unevaluated(UnevaluatedConst { def: const_id, args: subst }) => 'b: {
+ match konst.kind() {
+ ConstKind::Value(value) => self.allocate_valtree_in_heap(value.ty, value.value),
+ ConstKind::Unevaluated(UnevaluatedConst { def: const_id, args: subst }) => {
let mut id = const_id.0;
let mut subst = subst;
if let hir_def::GeneralConstId::ConstId(c) = id {
@@ -1947,7 +2081,7 @@ impl<'db> Evaluator<'db> {
id = hir_def::GeneralConstId::ConstId(c);
subst = s;
}
- result_owner = match id {
+ let allocation = match id {
GeneralConstId::ConstId(const_id) => {
self.db.const_eval(const_id, subst, Some(self.param_env)).map_err(|e| {
let name = id.name(self.db);
@@ -1964,21 +2098,24 @@ impl<'db> Evaluator<'db> {
not_supported!("anonymous const evaluation")
}
};
- if let ConstKind::Value(value) = result_owner.kind() {
- break 'b value;
- }
- not_supported!("unevaluatable constant");
+ self.allocate_allocation_in_heap(locals, allocation)
}
_ => not_supported!("evaluating unknown const"),
- };
- let ValueConst { ty, value } = value;
- let ConstBytes { memory: v, memory_map } = value.inner();
+ }
+ }
+
+ fn allocate_allocation_in_heap(
+ &mut self,
+ locals: &Locals,
+ allocation: Allocation<'db>,
+ ) -> Result<'db, Interval> {
+ let AllocationData { ty, memory: ref v, ref memory_map } = *allocation;
let patch_map = memory_map.transform_addresses(|b, align| {
let addr = self.heap_allocate(b.len(), align)?;
self.write_memory(addr, b)?;
Ok(addr.to_usize())
})?;
- let (size, align) = self.size_align_of(ty, locals)?.unwrap_or((v.len(), 1));
+ let (size, align) = self.size_align_of(allocation.ty, locals)?.unwrap_or((v.len(), 1));
let v: Cow<'_, [u8]> = if size != v.len() {
// Handle self enum
if size == 16 && v.len() < 16 {
@@ -1986,7 +2123,7 @@ impl<'db> Evaluator<'db> {
} else if size < 16 && v.len() == 16 {
Cow::Borrowed(&v[0..size])
} else {
- return Err(MirEvalError::InvalidConst(konst.store()));
+ return Err(MirEvalError::InvalidConst);
}
} else {
Cow::Borrowed(v)
@@ -2340,7 +2477,7 @@ impl<'db> Evaluator<'db> {
}
AdtId::UnionId(_) => (),
},
- TyKind::Alias(AliasTyKind::Projection, _) => {
+ TyKind::Alias(AliasTy { kind: AliasTyKind::Projection { .. }, .. }) => {
let mut ocx = ObligationCtxt::new(&this.infcx);
let ty = ocx
.structurally_normalize_ty(
@@ -2483,7 +2620,7 @@ impl<'db> Evaluator<'db> {
| TyKind::Error(_)
| TyKind::Placeholder(_)
| TyKind::Dynamic(_, _)
- | TyKind::Alias(_, _)
+ | TyKind::Alias(..)
| TyKind::Bound(_, _)
| TyKind::Infer(_)
| TyKind::Pat(_, _)
@@ -2840,10 +2977,10 @@ impl<'db> Evaluator<'db> {
};
let static_data = StaticSignature::of(self.db, st);
let result = if !static_data.flags.contains(StaticFlags::EXTERN) {
- let konst = self.db.const_eval_static(st).map_err(|e| {
+ let allocation = self.db.const_eval_static(st).map_err(|e| {
MirEvalError::ConstEvalError(static_data.name.as_str().to_owned(), Box::new(e))
})?;
- self.allocate_const_in_heap(locals, konst)?
+ self.allocate_allocation_in_heap(locals, allocation)?
} else {
let ty = InferenceResult::of(self.db, DefWithBodyId::from(st))
.expr_ty(Body::of(self.db, st.into()).root_expr());
@@ -3003,7 +3140,7 @@ impl<'db> Evaluator<'db> {
pub fn render_const_using_debug_impl<'db>(
db: &'db dyn HirDatabase,
owner: DefWithBodyId,
- c: Const<'db>,
+ c: Allocation<'db>,
ty: Ty<'db>,
) -> Result<'db, String> {
let mut evaluator = Evaluator::new(db, owner, false, None)?;
@@ -3014,7 +3151,7 @@ pub fn render_const_using_debug_impl<'db>(
.map_err(|_| MirEvalError::NotSupported("unreachable".to_owned()))?,
drop_flags: DropFlags::default(),
};
- let data = evaluator.allocate_const_in_heap(locals, c)?;
+ let data = evaluator.allocate_allocation_in_heap(locals, c)?;
let resolver = owner.resolver(db);
let Some(TypeNs::TraitId(debug_trait)) = resolver.resolve_path_in_type_ns_fully(
db,
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index d044019629..f1365e4df8 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -1493,8 +1493,8 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
hir_def::hir::Literal::Uint(it, _) => Box::from(&it.to_le_bytes()[0..size()?]),
hir_def::hir::Literal::Float(f, _) => match size()? {
16 => Box::new(f.to_f128().to_bits().to_le_bytes()),
- 8 => Box::new(f.to_f64().to_le_bytes()),
- 4 => Box::new(f.to_f32().to_le_bytes()),
+ 8 => Box::new(f.to_f64().to_bits().to_le_bytes()),
+ 4 => Box::new(f.to_f32().to_bits().to_le_bytes()),
2 => Box::new(u16::try_from(f.to_f16().to_bits()).unwrap().to_le_bytes()),
_ => {
return Err(MirLowerError::TypeError(
@@ -1528,31 +1528,14 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
subst: GenericArgs<'db>,
const_id: GeneralConstId,
) -> Result<'db, Operand> {
- let konst = if !subst.is_empty() {
- // We can't evaluate constant with substitution now, as generics are not monomorphized in lowering.
- Const::new_unevaluated(
- self.interner(),
- UnevaluatedConst { def: const_id.into(), args: subst },
- )
- } else {
- match const_id {
- id @ GeneralConstId::ConstId(const_id) => {
- self.db.const_eval(const_id, subst, None).map_err(|e| {
- let name = id.name(self.db);
- MirLowerError::ConstEvalError(name.into(), Box::new(e))
- })?
- }
- GeneralConstId::StaticId(static_id) => {
- self.db.const_eval_static(static_id).map_err(|e| {
- let name = const_id.name(self.db);
- MirLowerError::ConstEvalError(name.into(), Box::new(e))
- })?
- }
- GeneralConstId::AnonConstId(_) => {
- return Err(MirLowerError::IncompleteExpr);
- }
- }
- };
+ if matches!(const_id, GeneralConstId::AnonConstId(_)) {
+ // FIXME:
+ not_supported!("anon consts are not supported yet in const eval");
+ }
+ let konst = Const::new_unevaluated(
+ self.interner(),
+ UnevaluatedConst { def: const_id.into(), args: subst },
+ );
let ty = self
.db
.value_ty(match const_id {
diff --git a/crates/hir-ty/src/mir/monomorphization.rs b/crates/hir-ty/src/mir/monomorphization.rs
index 5752a3d7fa..41044f00c2 100644
--- a/crates/hir-ty/src/mir/monomorphization.rs
+++ b/crates/hir-ty/src/mir/monomorphization.rs
@@ -16,7 +16,10 @@ use triomphe::Arc;
use crate::{
ParamEnvAndCrate,
- next_solver::{Const, ConstKind, Region, RegionKind, StoredConst, StoredGenericArgs, StoredTy},
+ next_solver::{
+ Allocation, AllocationData, Const, ConstKind, Region, RegionKind, StoredConst,
+ StoredGenericArgs, StoredTy,
+ },
traits::StoredParamEnvAndCrate,
};
use crate::{
@@ -138,6 +141,18 @@ impl<'db> Filler<'db> {
self.fill_const(konst)?;
self.fill_ty(ty)?;
}
+ OperandKind::Allocation { allocation } => {
+ let alloc = allocation.as_ref();
+ let mut ty = alloc.ty.store();
+ self.fill_ty(&mut ty)?;
+ *allocation = Allocation::new(AllocationData {
+ ty: ty.as_ref(),
+ memory: alloc.memory.clone(),
+ // FIXME: Do we need to fill the memory map too?
+ memory_map: alloc.memory_map.clone(),
+ })
+ .store();
+ }
OperandKind::Copy(_) | OperandKind::Move(_) | OperandKind::Static(_) => (),
}
Ok(())
diff --git a/crates/hir-ty/src/mir/pretty.rs b/crates/hir-ty/src/mir/pretty.rs
index 4b654a0fbe..de5ee223a1 100644
--- a/crates/hir-ty/src/mir/pretty.rs
+++ b/crates/hir-ty/src/mir/pretty.rs
@@ -387,6 +387,9 @@ impl<'a, 'db> MirPrettyCtx<'a, 'db> {
w!(self, "Const({})", self.hir_display(&konst.as_ref()))
}
OperandKind::Static(s) => w!(self, "Static({:?})", s),
+ OperandKind::Allocation { allocation } => {
+ w!(self, "Allocation({})", self.hir_display(&allocation.as_ref()))
+ }
}
}
diff --git a/crates/hir-ty/src/next_solver.rs b/crates/hir-ty/src/next_solver.rs
index 605e31404c..161a3142df 100644
--- a/crates/hir-ty/src/next_solver.rs
+++ b/crates/hir-ty/src/next_solver.rs
@@ -5,6 +5,7 @@
// incorrect lifetime here.
pub mod abi;
+mod allocation;
mod binder;
mod consts;
mod def_id;
@@ -29,6 +30,7 @@ pub mod util;
use std::{mem::ManuallyDrop, sync::OnceLock};
+pub use allocation::*;
pub use binder::*;
pub use consts::*;
pub use def_id::*;
@@ -89,6 +91,7 @@ pub struct DefaultTypes<'db> {
pub struct DefaultConsts<'db> {
pub error: Const<'db>,
+ pub u8_values: [Const<'db>; 256],
}
pub struct DefaultRegions<'db> {
@@ -101,7 +104,7 @@ pub struct DefaultEmpty<'db> {
pub tys: Tys<'db>,
pub generic_args: GenericArgs<'db>,
pub bound_var_kinds: BoundVarKinds<'db>,
- pub canonical_vars: CanonicalVars<'db>,
+ pub canonical_vars: CanonicalVarKinds<'db>,
pub variances: VariancesOf<'db>,
pub pat_list: PatList<'db>,
pub predefined_opaques: PredefinedOpaques<'db>,
@@ -109,6 +112,7 @@ pub struct DefaultEmpty<'db> {
pub bound_existential_predicates: BoundExistentialPredicates<'db>,
pub clauses: Clauses<'db>,
pub region_assumptions: RegionAssumptions<'db>,
+ pub consts: Consts<'db>,
}
pub struct DefaultAny<'db> {
@@ -167,7 +171,7 @@ pub fn default_types<'a, 'db>(db: &'db dyn HirDatabase) -> &'a DefaultAny<'db> {
ty.as_ref()
};
let create_canonical_vars = |slice| {
- let ty = CanonicalVars::new_from_slice(slice);
+ let ty = CanonicalVarKinds::new_from_slice(slice);
// We need to increase the refcount (forever), so that the types won't be freed.
let ty = ManuallyDrop::new(ty.store());
ty.as_ref()
@@ -220,15 +224,22 @@ pub fn default_types<'a, 'db>(db: &'db dyn HirDatabase) -> &'a DefaultAny<'db> {
let ty = ManuallyDrop::new(ty.store());
ty.as_ref()
};
+ let create_consts = |slice| {
+ let ty = Consts::new_from_slice(slice);
+ // We need to increase the refcount (forever), so that the types won't be freed.
+ let ty = ManuallyDrop::new(ty.store());
+ ty.as_ref()
+ };
let str = create_ty(TyKind::Str);
let statik = create_region(RegionKind::ReStatic);
let empty_tys = create_tys(&[]);
let unit = create_ty(TyKind::Tuple(empty_tys));
+ let u8 = create_ty(TyKind::Uint(rustc_ast_ir::UintTy::U8));
DefaultAny {
types: DefaultTypes {
usize: create_ty(TyKind::Uint(rustc_ast_ir::UintTy::Usize)),
- u8: create_ty(TyKind::Uint(rustc_ast_ir::UintTy::U8)),
+ u8,
u16: create_ty(TyKind::Uint(rustc_ast_ir::UintTy::U16)),
u32: create_ty(TyKind::Uint(rustc_ast_ir::UintTy::U32)),
u64: create_ty(TyKind::Uint(rustc_ast_ir::UintTy::U64)),
@@ -252,7 +263,15 @@ pub fn default_types<'a, 'db>(db: &'db dyn HirDatabase) -> &'a DefaultAny<'db> {
static_str_ref: create_ty(TyKind::Ref(statik, str, rustc_ast_ir::Mutability::Not)),
mut_unit_ptr: create_ty(TyKind::RawPtr(unit, rustc_ast_ir::Mutability::Mut)),
},
- consts: DefaultConsts { error: create_const(ConstKind::Error(ErrorGuaranteed)) },
+ consts: DefaultConsts {
+ error: create_const(ConstKind::Error(ErrorGuaranteed)),
+ u8_values: std::array::from_fn(|u8_value| {
+ create_const(ConstKind::Value(ValueConst {
+ ty: u8,
+ value: ValTree::new(ValTreeKind::Leaf(ScalarInt::from(u8_value as u8))),
+ }))
+ }),
+ },
regions: DefaultRegions {
error: create_region(RegionKind::ReError(ErrorGuaranteed)),
statik,
@@ -270,11 +289,12 @@ pub fn default_types<'a, 'db>(db: &'db dyn HirDatabase) -> &'a DefaultAny<'db> {
bound_existential_predicates: create_bound_existential_predicates(&[]),
clauses: create_clauses(&[]),
region_assumptions: create_region_assumptions(&[]),
+ consts: create_consts(&[]),
},
one_invariant: create_variances_of(&[rustc_type_ir::Variance::Invariant]),
one_covariant: create_variances_of(&[rustc_type_ir::Variance::Covariant]),
coroutine_captures_by_ref_bound_var_kinds: create_bound_var_kinds(&[
- BoundVarKind::Region(BoundRegionKind::ClosureEnv),
+ BoundVariableKind::Region(BoundRegionKind::ClosureEnv),
]),
}
})
diff --git a/crates/hir-ty/src/next_solver/allocation.rs b/crates/hir-ty/src/next_solver/allocation.rs
new file mode 100644
index 0000000000..d299c89c12
--- /dev/null
+++ b/crates/hir-ty/src/next_solver/allocation.rs
@@ -0,0 +1,73 @@
+use std::{fmt, hash::Hash};
+
+use intern::{Interned, InternedRef, impl_internable};
+use macros::GenericTypeVisitable;
+use rustc_type_ir::GenericTypeVisitable;
+
+use crate::{
+ MemoryMap,
+ next_solver::{Ty, impl_stored_interned},
+};
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+pub struct Allocation<'db> {
+ interned: InternedRef<'db, AllocationInterned>,
+}
+
+impl<'db> Allocation<'db> {
+ pub fn new(data: AllocationData<'db>) -> Self {
+ let data =
+ unsafe { std::mem::transmute::<AllocationData<'db>, AllocationData<'static>>(data) };
+ Self { interned: Interned::new_gc(AllocationInterned(data)) }
+ }
+}
+
+impl<'db> std::ops::Deref for Allocation<'db> {
+ type Target = AllocationData<'db>;
+
+ #[inline]
+ fn deref(&self) -> &Self::Target {
+ let inner = &self.interned.0;
+ unsafe { std::mem::transmute::<&AllocationData<'static>, &AllocationData<'db>>(inner) }
+ }
+}
+
+impl<'db, V: super::WorldExposer> GenericTypeVisitable<V> for Allocation<'db> {
+ fn generic_visit_with(&self, visitor: &mut V) {
+ if visitor.on_interned(self.interned).is_continue() {
+ (**self).generic_visit_with(visitor);
+ }
+ }
+}
+
+impl fmt::Debug for Allocation<'_> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let AllocationData { ty, memory, memory_map } = &**self;
+ f.debug_struct("Allocation")
+ .field("ty", ty)
+ .field("memory", memory)
+ .field("memory_map", memory_map)
+ .finish()
+ }
+}
+
+#[derive(PartialEq, Eq, Hash, GenericTypeVisitable)]
+pub(super) struct AllocationInterned(AllocationData<'static>);
+
+#[derive(Debug, PartialEq, Eq, GenericTypeVisitable)]
+pub struct AllocationData<'db> {
+ pub ty: Ty<'db>,
+ pub memory: Box<[u8]>,
+ pub memory_map: MemoryMap<'db>,
+}
+
+impl<'db> Hash for AllocationData<'db> {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ let Self { ty, memory, memory_map: _ } = self;
+ ty.hash(state);
+ memory.hash(state);
+ }
+}
+
+impl_internable!(gc; AllocationInterned);
+impl_stored_interned!(AllocationInterned, Allocation, StoredAllocation);
diff --git a/crates/hir-ty/src/next_solver/consts.rs b/crates/hir-ty/src/next_solver/consts.rs
index 9643f1ba4c..fa90e3d8a0 100644
--- a/crates/hir-ty/src/next_solver/consts.rs
+++ b/crates/hir-ty/src/next_solver/consts.rs
@@ -1,5 +1,7 @@
//! Things related to consts in the next-trait-solver.
+mod valtree;
+
use std::hash::Hash;
use hir_def::ConstParamId;
@@ -9,17 +11,19 @@ use rustc_ast_ir::visit::VisitorResult;
use rustc_type_ir::{
BoundVar, BoundVarIndexKind, ConstVid, DebruijnIndex, FlagComputation, Flags,
GenericTypeVisitable, InferConst, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable,
- TypeVisitable, TypeVisitableExt, WithCachedTypeInfo,
- inherent::{IntoKind, ParamEnv as _, PlaceholderLike, SliceLike},
- relate::Relate,
+ TypeVisitable, WithCachedTypeInfo, inherent::IntoKind, relate::Relate,
};
use crate::{
- MemoryMap,
- next_solver::{ClauseKind, ParamEnv, impl_stored_interned},
+ ParamEnvAndCrate,
+ next_solver::{
+ AllocationData, impl_foldable_for_interned_slice, impl_stored_interned, interned_slice,
+ },
};
-use super::{BoundVarKind, DbInterner, ErrorGuaranteed, GenericArgs, Placeholder, Ty};
+use super::{DbInterner, ErrorGuaranteed, GenericArgs, Ty};
+
+pub use self::valtree::*;
pub type ConstKind<'db> = rustc_type_ir::ConstKind<DbInterner<'db>>;
pub type UnevaluatedConst<'db> = rustc_type_ir::UnevaluatedConst<DbInterner<'db>>;
@@ -71,26 +75,33 @@ impl<'db> Const<'db> {
Const::new(interner, ConstKind::Param(param))
}
- pub fn new_placeholder(interner: DbInterner<'db>, placeholder: PlaceholderConst) -> Self {
+ pub fn new_placeholder(interner: DbInterner<'db>, placeholder: PlaceholderConst<'db>) -> Self {
Const::new(interner, ConstKind::Placeholder(placeholder))
}
- pub fn new_bound(interner: DbInterner<'db>, index: DebruijnIndex, bound: BoundConst) -> Self {
+ pub fn new_bound(
+ interner: DbInterner<'db>,
+ index: DebruijnIndex,
+ bound: BoundConst<'db>,
+ ) -> Self {
Const::new(interner, ConstKind::Bound(BoundVarIndexKind::Bound(index), bound))
}
- pub fn new_valtree(
+ pub fn new_valtree(interner: DbInterner<'db>, ty: Ty<'db>, kind: ValTreeKind<'db>) -> Self {
+ Const::new(interner, ConstKind::Value(ValueConst { ty, value: ValTree::new(kind) }))
+ }
+
+ pub fn new_from_allocation(
interner: DbInterner<'db>,
- ty: Ty<'db>,
- memory: Box<[u8]>,
- memory_map: MemoryMap<'db>,
+ allocation: &AllocationData<'db>,
+ param_env: ParamEnvAndCrate<'db>,
) -> Self {
- Const::new(
+ allocation_to_const(
interner,
- ConstKind::Value(ValueConst {
- ty,
- value: Valtree::new(ConstBytes { memory, memory_map }),
- }),
+ allocation.ty,
+ &allocation.memory,
+ &allocation.memory_map,
+ param_env,
)
}
@@ -120,7 +131,7 @@ impl<'db> std::fmt::Debug for Const<'db> {
}
}
-pub type PlaceholderConst = Placeholder<BoundConst>;
+pub type PlaceholderConst<'db> = rustc_type_ir::PlaceholderConst<DbInterner<'db>>;
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
pub struct ParamConst {
@@ -135,126 +146,6 @@ impl std::fmt::Debug for ParamConst {
}
}
-impl ParamConst {
- pub fn find_const_ty_from_env<'db>(self, env: ParamEnv<'db>) -> Ty<'db> {
- let mut candidates = env.caller_bounds().iter().filter_map(|clause| {
- // `ConstArgHasType` are never desugared to be higher ranked.
- match clause.kind().skip_binder() {
- ClauseKind::ConstArgHasType(param_ct, ty) => {
- assert!(!(param_ct, ty).has_escaping_bound_vars());
-
- match param_ct.kind() {
- ConstKind::Param(param_ct) if param_ct.index == self.index => Some(ty),
- _ => None,
- }
- }
- _ => None,
- }
- });
-
- // N.B. it may be tempting to fix ICEs by making this function return
- // `Option<Ty<'db>>` instead of `Ty<'db>`; however, this is generally
- // considered to be a bandaid solution, since it hides more important
- // underlying issues with how we construct generics and predicates of
- // items. It's advised to fix the underlying issue rather than trying
- // to modify this function.
- let ty = candidates.next().unwrap_or_else(|| {
- panic!("cannot find `{self:?}` in param-env: {env:#?}");
- });
- assert!(
- candidates.next().is_none(),
- "did not expect duplicate `ConstParamHasTy` for `{self:?}` in param-env: {env:#?}"
- );
- ty
- }
-}
-
-/// A type-level constant value.
-///
-/// Represents a typed, fully evaluated constant.
-#[derive(
- Debug, Copy, Clone, Eq, PartialEq, Hash, TypeFoldable, TypeVisitable, GenericTypeVisitable,
-)]
-pub struct ValueConst<'db> {
- pub ty: Ty<'db>,
- // FIXME: Should we ignore this for TypeVisitable, TypeFoldable?
- #[type_visitable(ignore)]
- #[type_foldable(identity)]
- pub value: Valtree<'db>,
-}
-
-impl<'db> ValueConst<'db> {
- pub fn new(ty: Ty<'db>, bytes: ConstBytes<'db>) -> Self {
- let value = Valtree::new(bytes);
- ValueConst { ty, value }
- }
-}
-
-impl<'db> rustc_type_ir::inherent::ValueConst<DbInterner<'db>> for ValueConst<'db> {
- fn ty(self) -> Ty<'db> {
- self.ty
- }
-
- fn valtree(self) -> Valtree<'db> {
- self.value
- }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, GenericTypeVisitable)]
-pub struct ConstBytes<'db> {
- pub memory: Box<[u8]>,
- pub memory_map: MemoryMap<'db>,
-}
-
-impl Hash for ConstBytes<'_> {
- fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
- self.memory.hash(state)
- }
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub struct Valtree<'db> {
- interned: InternedRef<'db, ValtreeInterned>,
-}
-
-impl<'db, V: super::WorldExposer> GenericTypeVisitable<V> for Valtree<'db> {
- fn generic_visit_with(&self, visitor: &mut V) {
- if visitor.on_interned(self.interned).is_continue() {
- self.inner().generic_visit_with(visitor);
- }
- }
-}
-
-#[derive(Debug, PartialEq, Eq, Hash, GenericTypeVisitable)]
-pub(super) struct ValtreeInterned(ConstBytes<'static>);
-
-impl_internable!(gc; ValtreeInterned);
-
-const _: () = {
- const fn is_copy<T: Copy>() {}
- is_copy::<Valtree<'static>>();
-};
-
-impl<'db> Valtree<'db> {
- #[inline]
- pub fn new(bytes: ConstBytes<'db>) -> Self {
- let bytes = unsafe { std::mem::transmute::<ConstBytes<'db>, ConstBytes<'static>>(bytes) };
- Self { interned: Interned::new_gc(ValtreeInterned(bytes)) }
- }
-
- #[inline]
- pub fn inner(&self) -> &ConstBytes<'db> {
- let inner = &self.interned.0;
- unsafe { std::mem::transmute::<&ConstBytes<'static>, &ConstBytes<'db>>(inner) }
- }
-}
-
-impl std::fmt::Debug for Valtree<'_> {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- self.interned.fmt(f)
- }
-}
-
#[derive(
Copy, Clone, Debug, Hash, PartialEq, Eq, TypeVisitable, TypeFoldable, GenericTypeVisitable,
)]
@@ -388,25 +279,22 @@ impl<'db> rustc_type_ir::inherent::Const<DbInterner<'db>> for Const<'db> {
Const::new(interner, ConstKind::Infer(InferConst::Var(var)))
}
- fn new_bound(interner: DbInterner<'db>, debruijn: DebruijnIndex, var: BoundConst) -> Self {
+ fn new_bound(interner: DbInterner<'db>, debruijn: DebruijnIndex, var: BoundConst<'db>) -> Self {
Const::new(interner, ConstKind::Bound(BoundVarIndexKind::Bound(debruijn), var))
}
fn new_anon_bound(interner: DbInterner<'db>, debruijn: DebruijnIndex, var: BoundVar) -> Self {
Const::new(
interner,
- ConstKind::Bound(BoundVarIndexKind::Bound(debruijn), BoundConst { var }),
+ ConstKind::Bound(BoundVarIndexKind::Bound(debruijn), BoundConst::new(var)),
)
}
fn new_canonical_bound(interner: DbInterner<'db>, var: BoundVar) -> Self {
- Const::new(interner, ConstKind::Bound(BoundVarIndexKind::Canonical, BoundConst { var }))
+ Const::new(interner, ConstKind::Bound(BoundVarIndexKind::Canonical, BoundConst::new(var)))
}
- fn new_placeholder(
- interner: DbInterner<'db>,
- param: <DbInterner<'db> as rustc_type_ir::Interner>::PlaceholderConst,
- ) -> Self {
+ fn new_placeholder(interner: DbInterner<'db>, param: PlaceholderConst<'db>) -> Self {
Const::new(interner, ConstKind::Placeholder(param))
}
@@ -426,43 +314,7 @@ impl<'db> rustc_type_ir::inherent::Const<DbInterner<'db>> for Const<'db> {
}
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub struct BoundConst {
- pub var: BoundVar,
-}
-
-impl<'db> rustc_type_ir::inherent::BoundVarLike<DbInterner<'db>> for BoundConst {
- fn var(self) -> BoundVar {
- self.var
- }
-
- fn assert_eq(self, var: BoundVarKind) {
- var.expect_const()
- }
-}
-
-impl<'db> PlaceholderLike<DbInterner<'db>> for PlaceholderConst {
- type Bound = BoundConst;
-
- fn universe(self) -> rustc_type_ir::UniverseIndex {
- self.universe
- }
-
- fn var(self) -> rustc_type_ir::BoundVar {
- self.bound.var
- }
-
- fn with_updated_universe(self, ui: rustc_type_ir::UniverseIndex) -> Self {
- Placeholder { universe: ui, bound: self.bound }
- }
-
- fn new(ui: rustc_type_ir::UniverseIndex, var: BoundConst) -> Self {
- Placeholder { universe: ui, bound: var }
- }
- fn new_anon(ui: rustc_type_ir::UniverseIndex, var: rustc_type_ir::BoundVar) -> Self {
- Placeholder { universe: ui, bound: BoundConst { var } }
- }
-}
+pub type BoundConst<'db> = rustc_type_ir::BoundConst<DbInterner<'db>>;
impl<'db> Relate<DbInterner<'db>> for ExprConst {
fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>(
@@ -483,3 +335,6 @@ impl<'db> rustc_type_ir::inherent::ExprConst<DbInterner<'db>> for ExprConst {
GenericArgs::default()
}
}
+
+interned_slice!(ConstsStorage, Consts, StoredConsts, consts, Const<'db>, Const<'static>);
+impl_foldable_for_interned_slice!(Consts);
diff --git a/crates/hir-ty/src/next_solver/consts/valtree.rs b/crates/hir-ty/src/next_solver/consts/valtree.rs
new file mode 100644
index 0000000000..b856ee5a85
--- /dev/null
+++ b/crates/hir-ty/src/next_solver/consts/valtree.rs
@@ -0,0 +1,712 @@
+use std::{fmt, hash::Hash, num::NonZero};
+
+use intern::{Interned, InternedRef, impl_internable};
+use macros::{GenericTypeVisitable, TypeFoldable, TypeVisitable};
+use rustc_abi::{Size, TargetDataLayout};
+use rustc_type_ir::{GenericTypeVisitable, TypeFoldable, TypeVisitable, inherent::IntoKind};
+use stdx::never;
+
+use crate::{
+ MemoryMap, ParamEnvAndCrate, consteval,
+ mir::pad16,
+ next_solver::{Const, Consts, TyKind, WorldExposer},
+};
+
+use super::{DbInterner, Ty};
+
+pub type ValTreeKind<'db> = rustc_type_ir::ValTreeKind<DbInterner<'db>>;
+
+/// A type-level constant value.
+///
+/// Represents a typed, fully evaluated constant.
+#[derive(
+ Debug, Copy, Clone, Eq, PartialEq, Hash, TypeFoldable, TypeVisitable, GenericTypeVisitable,
+)]
+pub struct ValueConst<'db> {
+ pub ty: Ty<'db>,
+ pub value: ValTree<'db>,
+}
+
+impl<'db> ValueConst<'db> {
+ pub fn new(ty: Ty<'db>, kind: ValTreeKind<'db>) -> Self {
+ let value = ValTree::new(kind);
+ ValueConst { ty, value }
+ }
+}
+
+pub(super) fn allocation_to_const<'db>(
+ interner: DbInterner<'db>,
+ ty: Ty<'db>,
+ memory: &[u8],
+ memory_map: &MemoryMap<'db>,
+ param_env: ParamEnvAndCrate<'db>,
+) -> Const<'db> {
+ let Ok(data_layout) = interner.db.target_data_layout(param_env.krate) else {
+ return Const::error(interner);
+ };
+ let valtree = match ty.kind() {
+ TyKind::Bool => ValTreeKind::Leaf(ScalarInt::from(memory[0] != 0)),
+ TyKind::Char => {
+ let it = u128::from_le_bytes(pad16(memory, false)) as u32;
+ let Ok(c) = char::try_from(it) else {
+ return Const::error(interner);
+ };
+ ValTreeKind::Leaf(ScalarInt::from(c))
+ }
+ TyKind::Int(int) => {
+ let it = i128::from_le_bytes(pad16(memory, true));
+ let size = int.bit_width().map(Size::from_bits).unwrap_or(data_layout.pointer_size());
+ let scalar = ScalarInt::try_from_int(it, size).unwrap();
+ ValTreeKind::Leaf(scalar)
+ }
+ TyKind::Uint(uint) => {
+ let it = u128::from_le_bytes(pad16(memory, false));
+ let size = uint.bit_width().map(Size::from_bits).unwrap_or(data_layout.pointer_size());
+ let scalar = ScalarInt::try_from_uint(it, size).unwrap();
+ ValTreeKind::Leaf(scalar)
+ }
+ TyKind::Float(float) => {
+ let scalar = match float {
+ rustc_ast_ir::FloatTy::F16 => {
+ ScalarInt::from(u16::from_le_bytes(memory.try_into().unwrap()))
+ }
+ rustc_ast_ir::FloatTy::F32 => {
+ ScalarInt::from(u32::from_le_bytes(memory.try_into().unwrap()))
+ }
+ rustc_ast_ir::FloatTy::F64 => {
+ ScalarInt::from(u64::from_le_bytes(memory.try_into().unwrap()))
+ }
+ rustc_ast_ir::FloatTy::F128 => {
+ ScalarInt::from(u128::from_le_bytes(memory.try_into().unwrap()))
+ }
+ };
+ ValTreeKind::Leaf(scalar)
+ }
+ TyKind::Ref(_, t, _) => match t.kind() {
+ TyKind::Str => {
+ let addr = usize::from_le_bytes(memory[0..memory.len() / 2].try_into().unwrap());
+ let size = usize::from_le_bytes(memory[memory.len() / 2..].try_into().unwrap());
+ let Some(bytes) = memory_map.get(addr, size) else {
+ return Const::error(interner);
+ };
+ let u8_values = &interner.default_types().consts.u8_values;
+ ValTreeKind::Branch(Consts::new_from_iter(
+ interner,
+ bytes.iter().map(|&byte| u8_values[usize::from(byte)]),
+ ))
+ }
+ TyKind::Slice(ty) => {
+ let addr = usize::from_le_bytes(memory[0..memory.len() / 2].try_into().unwrap());
+ let count = usize::from_le_bytes(memory[memory.len() / 2..].try_into().unwrap());
+ let Ok(layout) = interner.db.layout_of_ty(ty.store(), param_env.store()) else {
+ return Const::error(interner);
+ };
+ let size_one = layout.size.bytes_usize();
+ let Some(bytes) = memory_map.get(addr, size_one * count) else {
+ return Const::error(interner);
+ };
+ let expected_len = count * size_one;
+ if bytes.len() < expected_len {
+ never!(
+ "Memory map size is too small. Expected {expected_len}, got {}",
+ bytes.len(),
+ );
+ return Const::error(interner);
+ }
+ let items = (0..count).map(|i| {
+ let offset = size_one * i;
+ let bytes = &bytes[offset..offset + size_one];
+ allocation_to_const(interner, ty, bytes, memory_map, param_env)
+ });
+ ValTreeKind::Branch(Consts::new_from_iter(interner, items))
+ }
+ TyKind::Dynamic(_, _) => {
+ let addr = usize::from_le_bytes(memory[0..memory.len() / 2].try_into().unwrap());
+ let ty_id = usize::from_le_bytes(memory[memory.len() / 2..].try_into().unwrap());
+ let Ok(t) = memory_map.vtable_ty(ty_id) else {
+ return Const::error(interner);
+ };
+ let Ok(layout) = interner.db.layout_of_ty(t.store(), param_env.store()) else {
+ return Const::error(interner);
+ };
+ let size = layout.size.bytes_usize();
+ let Some(bytes) = memory_map.get(addr, size) else {
+ return Const::error(interner);
+ };
+ return allocation_to_const(interner, t, bytes, memory_map, param_env);
+ }
+ TyKind::Adt(..) if memory.len() == 2 * size_of::<usize>() => {
+ // FIXME: Unsized ADT.
+ return Const::error(interner);
+ }
+ _ => {
+ let addr = usize::from_le_bytes(match memory.try_into() {
+ Ok(b) => b,
+ Err(_) => {
+ never!(
+ "tried rendering ty {:?} in const ref with incorrect byte count {}",
+ t,
+ memory.len()
+ );
+ return Const::error(interner);
+ }
+ });
+ let Ok(layout) = interner.db.layout_of_ty(t.store(), param_env.store()) else {
+ return Const::error(interner);
+ };
+ let size = layout.size.bytes_usize();
+ let Some(bytes) = memory_map.get(addr, size) else {
+ return Const::error(interner);
+ };
+ return allocation_to_const(interner, t, bytes, memory_map, param_env);
+ }
+ },
+ TyKind::Tuple(tys) => {
+ let Ok(layout) = interner.db.layout_of_ty(ty.store(), param_env.store()) else {
+ return Const::error(interner);
+ };
+ let items = tys.iter().enumerate().map(|(id, ty)| {
+ let offset = layout.fields.offset(id).bytes_usize();
+ let Ok(layout) = interner.db.layout_of_ty(ty.store(), param_env.store()) else {
+ return Const::error(interner);
+ };
+ let size = layout.size.bytes_usize();
+ allocation_to_const(
+ interner,
+ ty,
+ &memory[offset..offset + size],
+ memory_map,
+ param_env,
+ )
+ });
+ ValTreeKind::Branch(Consts::new_from_iter(interner, items))
+ }
+ TyKind::Adt(..) => {
+ // FIXME: This requires `adt_const_params`.
+ return Const::error(interner);
+ }
+ TyKind::FnDef(..) => {
+ // FIXME: Fn items.
+ return Const::error(interner);
+ }
+ TyKind::FnPtr(_, _) | TyKind::RawPtr(_, _) => {
+ let it = u128::from_le_bytes(pad16(memory, false));
+ // FIXME: Unsized pointers.
+ let scalar = ScalarInt::try_from_uint(it, data_layout.pointer_size()).unwrap();
+ ValTreeKind::Leaf(scalar)
+ }
+ TyKind::Array(ty, len) => {
+ let Some(len) = consteval::try_const_usize(interner.db, len) else {
+ return Const::error(interner);
+ };
+ let Ok(layout) = interner.db.layout_of_ty(ty.store(), param_env.store()) else {
+ return Const::error(interner);
+ };
+ let size_one = layout.size.bytes_usize();
+ let items = (0..len as usize).map(|i| {
+ let offset = size_one * i;
+ allocation_to_const(
+ interner,
+ ty,
+ &memory[offset..offset + size_one],
+ memory_map,
+ param_env,
+ )
+ });
+ ValTreeKind::Branch(Consts::new_from_iter(interner, items))
+ }
+ TyKind::Never => return Const::error(interner),
+ // FIXME:
+ TyKind::Closure(_, _)
+ | TyKind::Coroutine(_, _)
+ | TyKind::CoroutineWitness(_, _)
+ | TyKind::CoroutineClosure(_, _)
+ | TyKind::UnsafeBinder(_) => return Const::error(interner),
+ // The below arms are unreachable, since const eval will bail out before here.
+ TyKind::Foreign(_) => return Const::error(interner),
+ TyKind::Pat(_, _) => return Const::error(interner),
+ TyKind::Error(..)
+ | TyKind::Placeholder(_)
+ | TyKind::Alias(..)
+ | TyKind::Param(_)
+ | TyKind::Bound(_, _)
+ | TyKind::Infer(_) => return Const::error(interner),
+ // The below arms are unreachable, since we handled them in ref case.
+ TyKind::Slice(_) | TyKind::Str | TyKind::Dynamic(_, _) => {
+ return Const::error(interner);
+ }
+ };
+ Const::new_valtree(interner, ty, valtree)
+}
+
+impl<'db> rustc_type_ir::inherent::ValueConst<DbInterner<'db>> for ValueConst<'db> {
+ fn ty(self) -> Ty<'db> {
+ self.ty
+ }
+
+ fn valtree(self) -> ValTree<'db> {
+ self.value
+ }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+pub struct ValTree<'db> {
+ interned: InternedRef<'db, ValTreeInterned>,
+}
+
+impl<'db, V: WorldExposer> GenericTypeVisitable<V> for ValTree<'db> {
+ fn generic_visit_with(&self, visitor: &mut V) {
+ if visitor.on_interned(self.interned).is_continue() {
+ self.inner().generic_visit_with(visitor);
+ }
+ }
+}
+
+impl<'db> TypeVisitable<DbInterner<'db>> for ValTree<'db> {
+ fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
+ &self,
+ visitor: &mut V,
+ ) -> V::Result {
+ self.inner().visit_with(visitor)
+ }
+}
+
+impl<'db> TypeFoldable<DbInterner<'db>> for ValTree<'db> {
+ fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
+ self.inner().try_fold_with(folder).map(ValTree::new)
+ }
+
+ fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
+ ValTree::new(self.inner().fold_with(folder))
+ }
+}
+
+#[derive(Debug, PartialEq, Eq, Hash, GenericTypeVisitable)]
+pub(in super::super) struct ValTreeInterned(ValTreeKind<'static>);
+
+impl_internable!(gc; ValTreeInterned);
+
+const _: () = {
+ const fn is_copy<T: Copy>() {}
+ is_copy::<ValTree<'static>>();
+};
+
+impl<'db> IntoKind for ValTree<'db> {
+ type Kind = ValTreeKind<'db>;
+
+ fn kind(self) -> Self::Kind {
+ *self.inner()
+ }
+}
+
+impl<'db> ValTree<'db> {
+ #[inline]
+ pub fn new(kind: ValTreeKind<'db>) -> Self {
+ let kind = unsafe { std::mem::transmute::<ValTreeKind<'db>, ValTreeKind<'static>>(kind) };
+ Self { interned: Interned::new_gc(ValTreeInterned(kind)) }
+ }
+
+ #[inline]
+ pub fn inner(&self) -> &ValTreeKind<'db> {
+ let inner = &self.interned.0;
+ unsafe { std::mem::transmute::<&ValTreeKind<'static>, &ValTreeKind<'db>>(inner) }
+ }
+}
+
+impl std::fmt::Debug for ValTree<'_> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.interned.fmt(f)
+ }
+}
+
+/// The raw bytes of a simple value.
+///
+/// This is a packed struct in order to allow this type to be optimally embedded in enums
+/// (like Scalar).
+#[derive(Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(Rust, packed)]
+pub struct ScalarInt {
+ /// The first `size` bytes of `data` are the value.
+ /// Do not try to read less or more bytes than that. The remaining bytes must be 0.
+ data: u128,
+ size: NonZero<u8>,
+}
+
+impl ScalarInt {
+ pub const TRUE: ScalarInt = ScalarInt { data: 1_u128, size: NonZero::new(1).unwrap() };
+ pub const FALSE: ScalarInt = ScalarInt { data: 0_u128, size: NonZero::new(1).unwrap() };
+
+ fn raw(data: u128, size: Size) -> Self {
+ Self { data, size: NonZero::new(size.bytes() as u8).unwrap() }
+ }
+
+ #[inline]
+ pub fn size(self) -> Size {
+ Size::from_bytes(self.size.get())
+ }
+
+ /// Make sure the `data` fits in `size`.
+ /// This is guaranteed by all constructors here, but having had this check saved us from
+ /// bugs many times in the past, so keeping it around is definitely worth it.
+ #[inline(always)]
+ fn check_data(self) {
+ // Using a block `{self.data}` here to force a copy instead of using `self.data`
+ // directly, because `debug_assert_eq` takes references to its arguments and formatting
+ // arguments and would thus borrow `self.data`. Since `Self`
+ // is a packed struct, that would create a possibly unaligned reference, which
+ // is UB.
+ debug_assert_eq!(
+ self.size().truncate(self.data),
+ { self.data },
+ "Scalar value {:#x} exceeds size of {} bytes",
+ { self.data },
+ self.size
+ );
+ }
+
+ #[inline]
+ pub fn null(size: Size) -> Self {
+ Self::raw(0, size)
+ }
+
+ #[inline]
+ pub fn is_null(self) -> bool {
+ self.data == 0
+ }
+
+ #[inline]
+ pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
+ let (r, overflow) = Self::truncate_from_uint(i, size);
+ if overflow { None } else { Some(r) }
+ }
+
+ /// Returns the truncated result, and whether truncation changed the value.
+ #[inline]
+ pub fn truncate_from_uint(i: impl Into<u128>, size: Size) -> (Self, bool) {
+ let data = i.into();
+ let r = Self::raw(size.truncate(data), size);
+ (r, r.data != data)
+ }
+
+ #[inline]
+ pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
+ let (r, overflow) = Self::truncate_from_int(i, size);
+ if overflow { None } else { Some(r) }
+ }
+
+ /// Returns the truncated result, and whether truncation changed the value.
+ #[inline]
+ pub fn truncate_from_int(i: impl Into<i128>, size: Size) -> (Self, bool) {
+ let data = i.into();
+ // `into` performed sign extension, we have to truncate
+ let r = Self::raw(size.truncate(data as u128), size);
+ (r, size.sign_extend(r.data) != data)
+ }
+
+ #[inline]
+ pub fn try_from_target_usize(
+ i: impl Into<u128>,
+ data_layout: &TargetDataLayout,
+ ) -> Option<Self> {
+ Self::try_from_uint(i, data_layout.pointer_size())
+ }
+
+ /// Try to convert this ScalarInt to the raw underlying bits.
+ /// Fails if the size is wrong. Generally a wrong size should lead to a panic,
+ /// but Miri sometimes wants to be resilient to size mismatches,
+ /// so the interpreter will generally use this `try` method.
+ #[inline]
+ pub fn try_to_bits(self, target_size: Size) -> Result<u128, Size> {
+ assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
+ if target_size.bytes() == u64::from(self.size.get()) {
+ self.check_data();
+ Ok(self.data)
+ } else {
+ Err(self.size())
+ }
+ }
+
+ #[inline]
+ pub fn to_bits(self, target_size: Size) -> u128 {
+ self.try_to_bits(target_size).unwrap_or_else(|size| {
+ panic!("expected int of size {}, but got size {}", target_size.bytes(), size.bytes())
+ })
+ }
+
+ /// Extracts the bits from the scalar without checking the size.
+ #[inline]
+ pub fn to_bits_unchecked(self) -> u128 {
+ self.check_data();
+ self.data
+ }
+
+ /// Converts the `ScalarInt` to an unsigned integer of the given size.
+ /// Panics if the size of the `ScalarInt` is not equal to `size`.
+ #[inline]
+ pub fn to_uint(self, size: Size) -> u128 {
+ self.to_bits(size)
+ }
+
+ #[inline]
+ pub fn to_uint_unchecked(self) -> u128 {
+ self.data
+ }
+
+ /// Converts the `ScalarInt` to `u8`.
+ /// Panics if the `size` of the `ScalarInt`in not equal to 1 byte.
+ #[inline]
+ pub fn to_u8(self) -> u8 {
+ self.to_uint(Size::from_bits(8)).try_into().unwrap()
+ }
+
+ /// Converts the `ScalarInt` to `u16`.
+ /// Panics if the size of the `ScalarInt` in not equal to 2 bytes.
+ #[inline]
+ pub fn to_u16(self) -> u16 {
+ self.to_uint(Size::from_bits(16)).try_into().unwrap()
+ }
+
+ /// Converts the `ScalarInt` to `u32`.
+ /// Panics if the `size` of the `ScalarInt` in not equal to 4 bytes.
+ #[inline]
+ pub fn to_u32(self) -> u32 {
+ self.to_uint(Size::from_bits(32)).try_into().unwrap()
+ }
+
+ /// Converts the `ScalarInt` to `u64`.
+ /// Panics if the `size` of the `ScalarInt` in not equal to 8 bytes.
+ #[inline]
+ pub fn to_u64(self) -> u64 {
+ self.to_uint(Size::from_bits(64)).try_into().unwrap()
+ }
+
+ /// Converts the `ScalarInt` to `u128`.
+ /// Panics if the `size` of the `ScalarInt` in not equal to 16 bytes.
+ #[inline]
+ pub fn to_u128(self) -> u128 {
+ self.to_uint(Size::from_bits(128))
+ }
+
+ #[inline]
+ pub fn to_target_usize(&self, data_layout: &TargetDataLayout) -> u64 {
+ self.to_uint(data_layout.pointer_size()).try_into().unwrap()
+ }
+
+ /// Converts the `ScalarInt` to `bool`.
+ /// Panics if the `size` of the `ScalarInt` is not equal to 1 byte.
+ /// Errors if it is not a valid `bool`.
+ #[inline]
+ pub fn try_to_bool(self) -> Result<bool, ()> {
+ match self.to_u8() {
+ 0 => Ok(false),
+ 1 => Ok(true),
+ _ => Err(()),
+ }
+ }
+
+ /// Converts the `ScalarInt` to a signed integer of the given size.
+ /// Panics if the size of the `ScalarInt` is not equal to `size`.
+ #[inline]
+ pub fn to_int(self, size: Size) -> i128 {
+ let b = self.to_bits(size);
+ size.sign_extend(b)
+ }
+
+ #[inline]
+ pub fn to_int_unchecked(self) -> i128 {
+ self.size().sign_extend(self.data)
+ }
+
+ /// Converts the `ScalarInt` to i8.
+ /// Panics if the size of the `ScalarInt` is not equal to 1 byte.
+ pub fn to_i8(self) -> i8 {
+ self.to_int(Size::from_bits(8)).try_into().unwrap()
+ }
+
+ /// Converts the `ScalarInt` to i16.
+ /// Panics if the size of the `ScalarInt` is not equal to 2 bytes.
+ pub fn to_i16(self) -> i16 {
+ self.to_int(Size::from_bits(16)).try_into().unwrap()
+ }
+
+ /// Converts the `ScalarInt` to i32.
+ /// Panics if the size of the `ScalarInt` is not equal to 4 bytes.
+ pub fn to_i32(self) -> i32 {
+ self.to_int(Size::from_bits(32)).try_into().unwrap()
+ }
+
+ /// Converts the `ScalarInt` to i64.
+ /// Panics if the size of the `ScalarInt` is not equal to 8 bytes.
+ pub fn to_i64(self) -> i64 {
+ self.to_int(Size::from_bits(64)).try_into().unwrap()
+ }
+
+ /// Converts the `ScalarInt` to i128.
+ /// Panics if the size of the `ScalarInt` is not equal to 16 bytes.
+ pub fn to_i128(self) -> i128 {
+ self.to_int(Size::from_bits(128))
+ }
+
+ #[inline]
+ pub fn to_target_isize(&self, data_layout: &TargetDataLayout) -> i64 {
+ self.to_int(data_layout.pointer_size()).try_into().unwrap()
+ }
+}
+
+macro_rules! from_x_for_scalar_int {
+ ($($ty:ty),*) => {
+ $(
+ impl From<$ty> for ScalarInt {
+ #[inline]
+ fn from(u: $ty) -> Self {
+ Self {
+ data: u128::from(u),
+ size: NonZero::new(size_of::<$ty>() as u8).unwrap(),
+ }
+ }
+ }
+ )*
+ }
+}
+
+macro_rules! from_scalar_int_for_x {
+ ($($ty:ty),*) => {
+ $(
+ impl From<ScalarInt> for $ty {
+ #[inline]
+ fn from(int: ScalarInt) -> Self {
+ // The `unwrap` cannot fail because to_uint (if it succeeds)
+ // is guaranteed to return a value that fits into the size.
+ int.to_uint(Size::from_bytes(size_of::<$ty>()))
+ .try_into().unwrap()
+ }
+ }
+ )*
+ }
+}
+
+from_x_for_scalar_int!(u8, u16, u32, u64, u128, bool);
+from_scalar_int_for_x!(u8, u16, u32, u64, u128);
+
+impl TryFrom<ScalarInt> for bool {
+ type Error = ();
+ #[inline]
+ fn try_from(int: ScalarInt) -> Result<Self, ()> {
+ int.try_to_bool()
+ }
+}
+
+impl From<char> for ScalarInt {
+ #[inline]
+ fn from(c: char) -> Self {
+ (c as u32).into()
+ }
+}
+
+macro_rules! from_x_for_scalar_int_signed {
+ ($($ty:ty),*) => {
+ $(
+ impl From<$ty> for ScalarInt {
+ #[inline]
+ fn from(u: $ty) -> Self {
+ Self {
+ data: u128::from(u.cast_unsigned()), // go via the unsigned type of the same size
+ size: NonZero::new(size_of::<$ty>() as u8).unwrap(),
+ }
+ }
+ }
+ )*
+ }
+}
+
+macro_rules! from_scalar_int_for_x_signed {
+ ($($ty:ty),*) => {
+ $(
+ impl From<ScalarInt> for $ty {
+ #[inline]
+ fn from(int: ScalarInt) -> Self {
+ // The `unwrap` cannot fail because to_int (if it succeeds)
+ // is guaranteed to return a value that fits into the size.
+ int.to_int(Size::from_bytes(size_of::<$ty>()))
+ .try_into().unwrap()
+ }
+ }
+ )*
+ }
+}
+
+from_x_for_scalar_int_signed!(i8, i16, i32, i64, i128);
+from_scalar_int_for_x_signed!(i8, i16, i32, i64, i128);
+
+impl From<std::cmp::Ordering> for ScalarInt {
+ #[inline]
+ fn from(c: std::cmp::Ordering) -> Self {
+ // Here we rely on `cmp::Ordering` having the same values in host and target!
+ ScalarInt::from(c as i8)
+ }
+}
+
+/// Error returned when a conversion from ScalarInt to char fails.
+#[derive(Debug)]
+pub struct CharTryFromScalarInt;
+
+impl TryFrom<ScalarInt> for char {
+ type Error = CharTryFromScalarInt;
+
+ #[inline]
+ fn try_from(int: ScalarInt) -> Result<Self, Self::Error> {
+ match char::from_u32(int.to_u32()) {
+ Some(c) => Ok(c),
+ None => Err(CharTryFromScalarInt),
+ }
+ }
+}
+
+impl fmt::Debug for ScalarInt {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // Dispatch to LowerHex below.
+ write!(f, "0x{self:x}")
+ }
+}
+
+impl fmt::LowerHex for ScalarInt {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.check_data();
+ if f.alternate() {
+ // Like regular ints, alternate flag adds leading `0x`.
+ write!(f, "0x")?;
+ }
+ // Format as hex number wide enough to fit any value of the given `size`.
+ // So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
+ // Using a block `{self.data}` here to force a copy instead of using `self.data`
+ // directly, because `write!` takes references to its formatting arguments and
+ // would thus borrow `self.data`. Since `Self`
+ // is a packed struct, that would create a possibly unaligned reference, which
+ // is UB.
+ write!(f, "{:01$x}", { self.data }, self.size.get() as usize * 2)
+ }
+}
+
+impl fmt::UpperHex for ScalarInt {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.check_data();
+ // Format as hex number wide enough to fit any value of the given `size`.
+ // So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
+ // Using a block `{self.data}` here to force a copy instead of using `self.data`
+ // directly, because `write!` takes references to its formatting arguments and
+ // would thus borrow `self.data`. Since `Self`
+ // is a packed struct, that would create a possibly unaligned reference, which
+ // is UB.
+ write!(f, "{:01$X}", { self.data }, self.size.get() as usize * 2)
+ }
+}
+
+impl fmt::Display for ScalarInt {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.check_data();
+ write!(f, "{}", { self.data })
+ }
+}
diff --git a/crates/hir-ty/src/next_solver/fold.rs b/crates/hir-ty/src/next_solver/fold.rs
index 7836419e8b..af823aa005 100644
--- a/crates/hir-ty/src/next_solver/fold.rs
+++ b/crates/hir-ty/src/next_solver/fold.rs
@@ -17,28 +17,28 @@ use super::{
/// gets mapped to the same result. `BoundVarReplacer` caches by using
/// a `DelayedMap` which does not cache the first few types it encounters.
pub trait BoundVarReplacerDelegate<'db> {
- fn replace_region(&mut self, br: BoundRegion) -> Region<'db>;
- fn replace_ty(&mut self, bt: BoundTy) -> Ty<'db>;
- fn replace_const(&mut self, bv: BoundConst) -> Const<'db>;
+ fn replace_region(&mut self, br: BoundRegion<'db>) -> Region<'db>;
+ fn replace_ty(&mut self, bt: BoundTy<'db>) -> Ty<'db>;
+ fn replace_const(&mut self, bv: BoundConst<'db>) -> Const<'db>;
}
/// A simple delegate taking 3 mutable functions. The used functions must
/// always return the same result for each bound variable, no matter how
/// frequently they are called.
pub struct FnMutDelegate<'db, 'a> {
- pub regions: &'a mut (dyn FnMut(BoundRegion) -> Region<'db> + 'a),
- pub types: &'a mut (dyn FnMut(BoundTy) -> Ty<'db> + 'a),
- pub consts: &'a mut (dyn FnMut(BoundConst) -> Const<'db> + 'a),
+ pub regions: &'a mut (dyn FnMut(BoundRegion<'db>) -> Region<'db> + 'a),
+ pub types: &'a mut (dyn FnMut(BoundTy<'db>) -> Ty<'db> + 'a),
+ pub consts: &'a mut (dyn FnMut(BoundConst<'db>) -> Const<'db> + 'a),
}
impl<'db, 'a> BoundVarReplacerDelegate<'db> for FnMutDelegate<'db, 'a> {
- fn replace_region(&mut self, br: BoundRegion) -> Region<'db> {
+ fn replace_region(&mut self, br: BoundRegion<'db>) -> Region<'db> {
(self.regions)(br)
}
- fn replace_ty(&mut self, bt: BoundTy) -> Ty<'db> {
+ fn replace_ty(&mut self, bt: BoundTy<'db>) -> Ty<'db> {
(self.types)(bt)
}
- fn replace_const(&mut self, bv: BoundConst) -> Const<'db> {
+ fn replace_const(&mut self, bv: BoundConst<'db>) -> Const<'db> {
(self.consts)(bv)
}
}
@@ -177,13 +177,13 @@ impl<'db> DbInterner<'db> {
self,
value: Binder<'db, T>,
mut fld_r: F,
- ) -> (T, FxIndexMap<BoundRegion, Region<'db>>)
+ ) -> (T, FxIndexMap<BoundRegion<'db>, Region<'db>>)
where
- F: FnMut(BoundRegion) -> Region<'db>,
+ F: FnMut(BoundRegion<'db>) -> Region<'db>,
T: TypeFoldable<DbInterner<'db>>,
{
let mut region_map = FxIndexMap::default();
- let real_fld_r = |br: BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br));
+ let real_fld_r = |br: BoundRegion<'db>| *region_map.entry(br).or_insert_with(|| fld_r(br));
let value = self.instantiate_bound_regions_uncached(value, real_fld_r);
(value, region_map)
}
@@ -194,7 +194,7 @@ impl<'db> DbInterner<'db> {
mut replace_regions: F,
) -> T
where
- F: FnMut(BoundRegion) -> Region<'db>,
+ F: FnMut(BoundRegion<'db>) -> Region<'db>,
T: TypeFoldable<DbInterner<'db>>,
{
let value = value.skip_binder();
diff --git a/crates/hir-ty/src/next_solver/fulfill.rs b/crates/hir-ty/src/next_solver/fulfill.rs
index a8bff44a02..6739795a00 100644
--- a/crates/hir-ty/src/next_solver/fulfill.rs
+++ b/crates/hir-ty/src/next_solver/fulfill.rs
@@ -1,7 +1,5 @@
//! Fulfill loop for next-solver.
-mod errors;
-
use std::ops::ControlFlow;
use rustc_hash::FxHashSet;
diff --git a/crates/hir-ty/src/next_solver/fulfill/errors.rs b/crates/hir-ty/src/next_solver/fulfill/errors.rs
deleted file mode 100644
index 0e8218b33a..0000000000
--- a/crates/hir-ty/src/next_solver/fulfill/errors.rs
+++ /dev/null
@@ -1,1173 +0,0 @@
-//! Trait solving error diagnosis and reporting.
-//!
-//! This code isn't used by rust-analyzer (it should, but then it'll probably be better to re-port it from rustc).
-//! It's only there because without it, debugging trait solver errors is a nightmare.
-
-use std::{fmt::Debug, ops::ControlFlow};
-
-use rustc_next_trait_solver::solve::{GoalEvaluation, SolverDelegateEvalExt};
-use rustc_type_ir::{
- AliasRelationDirection, AliasTermKind, HostEffectPredicate, Interner, PredicatePolarity,
- error::ExpectedFound,
- inherent::{IntoKind, Span as _},
- lang_items::SolverTraitLangItem,
- solve::{Certainty, GoalSource, MaybeCause, NoSolution},
-};
-use tracing::{instrument, trace};
-
-use crate::next_solver::{
- AliasTerm, Binder, ClauseKind, Const, ConstKind, DbInterner, PolyTraitPredicate, PredicateKind,
- SolverContext, Span, Term, TraitPredicate, Ty, TyKind, TypeError,
- fulfill::NextSolverError,
- infer::{
- InferCtxt,
- select::SelectionError,
- traits::{Obligation, ObligationCause, PredicateObligation, PredicateObligations},
- },
- inspect::{self, ProofTreeVisitor},
- normalize::deeply_normalize_for_diagnostics,
-};
-
-#[derive(Debug)]
-pub struct FulfillmentError<'db> {
- pub obligation: PredicateObligation<'db>,
- pub code: FulfillmentErrorCode<'db>,
- /// Diagnostics only: the 'root' obligation which resulted in
- /// the failure to process `obligation`. This is the obligation
- /// that was initially passed to `register_predicate_obligation`
- pub root_obligation: PredicateObligation<'db>,
-}
-
-impl<'db> FulfillmentError<'db> {
- pub fn new(
- obligation: PredicateObligation<'db>,
- code: FulfillmentErrorCode<'db>,
- root_obligation: PredicateObligation<'db>,
- ) -> FulfillmentError<'db> {
- FulfillmentError { obligation, code, root_obligation }
- }
-
- pub fn is_true_error(&self) -> bool {
- match self.code {
- FulfillmentErrorCode::Select(_)
- | FulfillmentErrorCode::Project(_)
- | FulfillmentErrorCode::Subtype(_, _)
- | FulfillmentErrorCode::ConstEquate(_, _) => true,
- FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => {
- false
- }
- }
- }
-}
-
-#[derive(Debug, Clone)]
-pub enum FulfillmentErrorCode<'db> {
- /// Inherently impossible to fulfill; this trait is implemented if and only
- /// if it is already implemented.
- Cycle(PredicateObligations<'db>),
- Select(SelectionError<'db>),
- Project(MismatchedProjectionTypes<'db>),
- Subtype(ExpectedFound<Ty<'db>>, TypeError<'db>), // always comes from a SubtypePredicate
- ConstEquate(ExpectedFound<Const<'db>>, TypeError<'db>),
- Ambiguity {
- /// Overflow is only `Some(suggest_recursion_limit)` when using the next generation
- /// trait solver `-Znext-solver`. With the old solver overflow is eagerly handled by
- /// emitting a fatal error instead.
- overflow: Option<bool>,
- },
-}
-
-#[derive(Debug, Clone)]
-pub struct MismatchedProjectionTypes<'db> {
- pub err: TypeError<'db>,
-}
-
-pub(super) fn fulfillment_error_for_no_solution<'db>(
- infcx: &InferCtxt<'db>,
- root_obligation: PredicateObligation<'db>,
-) -> FulfillmentError<'db> {
- let obligation = find_best_leaf_obligation(infcx, &root_obligation, false);
-
- let code = match obligation.predicate.kind().skip_binder() {
- PredicateKind::Clause(ClauseKind::Projection(_)) => {
- FulfillmentErrorCode::Project(
- // FIXME: This could be a `Sorts` if the term is a type
- MismatchedProjectionTypes { err: TypeError::Mismatch },
- )
- }
- PredicateKind::Clause(ClauseKind::ConstArgHasType(ct, expected_ty)) => {
- let ct_ty = match ct.kind() {
- ConstKind::Unevaluated(uv) => {
- infcx.interner.type_of(uv.def.into()).instantiate(infcx.interner, uv.args)
- }
- ConstKind::Param(param_ct) => param_ct.find_const_ty_from_env(obligation.param_env),
- ConstKind::Value(cv) => cv.ty,
- kind => panic!(
- "ConstArgHasWrongType failed but we don't know how to compute type for {kind:?}"
- ),
- };
- FulfillmentErrorCode::Select(SelectionError::ConstArgHasWrongType {
- ct,
- ct_ty,
- expected_ty,
- })
- }
- PredicateKind::NormalizesTo(..) => {
- FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch })
- }
- PredicateKind::AliasRelate(_, _, _) => {
- FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch })
- }
- PredicateKind::Subtype(pred) => {
- let (a, b) = infcx.enter_forall_and_leak_universe(
- obligation.predicate.kind().rebind((pred.a, pred.b)),
- );
- let expected_found = ExpectedFound::new(a, b);
- FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
- }
- PredicateKind::Coerce(pred) => {
- let (a, b) = infcx.enter_forall_and_leak_universe(
- obligation.predicate.kind().rebind((pred.a, pred.b)),
- );
- let expected_found = ExpectedFound::new(b, a);
- FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
- }
- PredicateKind::Clause(_) | PredicateKind::DynCompatible(_) | PredicateKind::Ambiguous => {
- FulfillmentErrorCode::Select(SelectionError::Unimplemented)
- }
- PredicateKind::ConstEquate(..) => {
- panic!("unexpected goal: {obligation:?}")
- }
- };
-
- FulfillmentError { obligation, code, root_obligation }
-}
-
-pub(super) fn fulfillment_error_for_stalled<'db>(
- infcx: &InferCtxt<'db>,
- root_obligation: PredicateObligation<'db>,
-) -> FulfillmentError<'db> {
- let (code, refine_obligation) = infcx.probe(|_| {
- match <&SolverContext<'db>>::from(infcx).evaluate_root_goal(
- root_obligation.as_goal(),
- Span::dummy(),
- None,
- ) {
- Ok(GoalEvaluation {
- certainty: Certainty::Maybe { cause: MaybeCause::Ambiguity, .. },
- ..
- }) => (FulfillmentErrorCode::Ambiguity { overflow: None }, true),
- Ok(GoalEvaluation {
- certainty:
- Certainty::Maybe {
- cause:
- MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: _ },
- ..
- },
- ..
- }) => (
- FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) },
- // Don't look into overflows because we treat overflows weirdly anyways.
- // We discard the inference constraints from overflowing goals, so
- // recomputing the goal again during `find_best_leaf_obligation` may apply
- // inference guidance that makes other goals go from ambig -> pass, for example.
- //
- // FIXME: We should probably just look into overflows here.
- false,
- ),
- Ok(GoalEvaluation { certainty: Certainty::Yes, .. }) => {
- panic!(
- "did not expect successful goal when collecting ambiguity errors for `{:?}`",
- infcx.resolve_vars_if_possible(root_obligation.predicate),
- )
- }
- Err(_) => {
- panic!(
- "did not expect selection error when collecting ambiguity errors for `{:?}`",
- infcx.resolve_vars_if_possible(root_obligation.predicate),
- )
- }
- }
- });
-
- FulfillmentError {
- obligation: if refine_obligation {
- find_best_leaf_obligation(infcx, &root_obligation, true)
- } else {
- root_obligation.clone()
- },
- code,
- root_obligation,
- }
-}
-
-pub(super) fn fulfillment_error_for_overflow<'db>(
- infcx: &InferCtxt<'db>,
- root_obligation: PredicateObligation<'db>,
-) -> FulfillmentError<'db> {
- FulfillmentError {
- obligation: find_best_leaf_obligation(infcx, &root_obligation, true),
- code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
- root_obligation,
- }
-}
-
-#[instrument(level = "debug", skip(infcx), ret)]
-fn find_best_leaf_obligation<'db>(
- infcx: &InferCtxt<'db>,
- obligation: &PredicateObligation<'db>,
- consider_ambiguities: bool,
-) -> PredicateObligation<'db> {
- let obligation = infcx.resolve_vars_if_possible(obligation.clone());
- // FIXME: we use a probe here as the `BestObligation` visitor does not
- // check whether it uses candidates which get shadowed by where-bounds.
- //
- // We should probably fix the visitor to not do so instead, as this also
- // means the leaf obligation may be incorrect.
- let obligation = infcx
- .fudge_inference_if_ok(|| {
- infcx
- .visit_proof_tree(
- obligation.as_goal(),
- &mut BestObligation { obligation: obligation.clone(), consider_ambiguities },
- )
- .break_value()
- .ok_or(())
- })
- .unwrap_or(obligation);
- deeply_normalize_for_diagnostics(infcx, obligation.param_env, obligation)
-}
-
-struct BestObligation<'db> {
- obligation: PredicateObligation<'db>,
- consider_ambiguities: bool,
-}
-
-impl<'db> BestObligation<'db> {
- fn with_derived_obligation(
- &mut self,
- derived_obligation: PredicateObligation<'db>,
- and_then: impl FnOnce(&mut Self) -> <Self as ProofTreeVisitor<'db>>::Result,
- ) -> <Self as ProofTreeVisitor<'db>>::Result {
- let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation);
- let res = and_then(self);
- self.obligation = old_obligation;
- res
- }
-
- /// Filter out the candidates that aren't interesting to visit for the
- /// purposes of reporting errors. For ambiguities, we only consider
- /// candidates that may hold. For errors, we only consider candidates that
- /// *don't* hold and which have impl-where clauses that also don't hold.
- fn non_trivial_candidates<'a>(
- &self,
- goal: &'a inspect::InspectGoal<'a, 'db>,
- ) -> Vec<inspect::InspectCandidate<'a, 'db>> {
- let mut candidates = goal.candidates();
- match self.consider_ambiguities {
- true => {
- // If we have an ambiguous obligation, we must consider *all* candidates
- // that hold, or else we may guide inference causing other goals to go
- // from ambig -> pass/fail.
- candidates.retain(|candidate| candidate.result().is_ok());
- }
- false => {
- // We always handle rigid alias candidates separately as we may not add them for
- // aliases whose trait bound doesn't hold.
- candidates.retain(|c| !matches!(c.kind(), inspect::ProbeKind::RigidAlias { .. }));
- // If we have >1 candidate, one may still be due to "boring" reasons, like
- // an alias-relate that failed to hold when deeply evaluated. We really
- // don't care about reasons like this.
- if candidates.len() > 1 {
- candidates.retain(|candidate| {
- goal.infcx().probe(|_| {
- candidate.instantiate_nested_goals().iter().any(|nested_goal| {
- matches!(
- nested_goal.source(),
- GoalSource::ImplWhereBound
- | GoalSource::AliasBoundConstCondition
- | GoalSource::AliasWellFormed
- ) && nested_goal.result().is_err()
- })
- })
- });
- }
- }
- }
-
- candidates
- }
-
- /// HACK: We walk the nested obligations for a well-formed arg manually,
- /// since there's nontrivial logic in `wf.rs` to set up an obligation cause.
- /// Ideally we'd be able to track this better.
- fn visit_well_formed_goal(
- &mut self,
- candidate: &inspect::InspectCandidate<'_, 'db>,
- term: Term<'db>,
- ) -> ControlFlow<PredicateObligation<'db>> {
- let infcx = candidate.goal().infcx();
- let param_env = candidate.goal().goal().param_env;
-
- for obligation in wf::unnormalized_obligations(infcx, param_env, term).into_iter().flatten()
- {
- let nested_goal = candidate
- .instantiate_proof_tree_for_nested_goal(GoalSource::Misc, obligation.as_goal());
- // Skip nested goals that aren't the *reason* for our goal's failure.
- match (self.consider_ambiguities, nested_goal.result()) {
- (true, Ok(Certainty::Maybe { cause: MaybeCause::Ambiguity, .. }))
- | (false, Err(_)) => {}
- _ => continue,
- }
-
- self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
- }
-
- ControlFlow::Break(self.obligation.clone())
- }
-
- /// If a normalization of an associated item or a trait goal fails without trying any
- /// candidates it's likely that normalizing its self type failed. We manually detect
- /// such cases here.
- fn detect_error_in_self_ty_normalization(
- &mut self,
- goal: &inspect::InspectGoal<'_, 'db>,
- self_ty: Ty<'db>,
- ) -> ControlFlow<PredicateObligation<'db>> {
- assert!(!self.consider_ambiguities);
- let interner = goal.infcx().interner;
- if let TyKind::Alias(..) = self_ty.kind() {
- let infer_term = goal.infcx().next_ty_var();
- let pred = PredicateKind::AliasRelate(
- self_ty.into(),
- infer_term.into(),
- AliasRelationDirection::Equate,
- );
- let obligation = Obligation::new(
- interner,
- self.obligation.cause.clone(),
- goal.goal().param_env,
- pred,
- );
- self.with_derived_obligation(obligation, |this| {
- goal.infcx().visit_proof_tree_at_depth(
- goal.goal().with(interner, pred),
- goal.depth() + 1,
- this,
- )
- })
- } else {
- ControlFlow::Continue(())
- }
- }
-
- /// When a higher-ranked projection goal fails, check that the corresponding
- /// higher-ranked trait goal holds or not. This is because the process of
- /// instantiating and then re-canonicalizing the binder of the projection goal
- /// forces us to be unable to see that the leak check failed in the nested
- /// `NormalizesTo` goal, so we don't fall back to the rigid projection check
- /// that should catch when a projection goal fails due to an unsatisfied trait
- /// goal.
- fn detect_trait_error_in_higher_ranked_projection(
- &mut self,
- goal: &inspect::InspectGoal<'_, 'db>,
- ) -> ControlFlow<PredicateObligation<'db>> {
- let interner = goal.infcx().interner;
- if let Some(projection_clause) = goal.goal().predicate.as_projection_clause()
- && !projection_clause.bound_vars().is_empty()
- {
- let pred = projection_clause.map_bound(|proj| proj.projection_term.trait_ref(interner));
- let obligation = Obligation::new(
- interner,
- self.obligation.cause.clone(),
- goal.goal().param_env,
- deeply_normalize_for_diagnostics(goal.infcx(), goal.goal().param_env, pred),
- );
- self.with_derived_obligation(obligation, |this| {
- goal.infcx().visit_proof_tree_at_depth(
- goal.goal().with(interner, pred),
- goal.depth() + 1,
- this,
- )
- })
- } else {
- ControlFlow::Continue(())
- }
- }
-
- /// It is likely that `NormalizesTo` failed without any applicable candidates
- /// because the alias is not well-formed.
- ///
- /// As we only enter `RigidAlias` candidates if the trait bound of the associated type
- /// holds, we discard these candidates in `non_trivial_candidates` and always manually
- /// check this here.
- fn detect_non_well_formed_assoc_item(
- &mut self,
- goal: &inspect::InspectGoal<'_, 'db>,
- alias: AliasTerm<'db>,
- ) -> ControlFlow<PredicateObligation<'db>> {
- let interner = goal.infcx().interner;
- let obligation = Obligation::new(
- interner,
- self.obligation.cause.clone(),
- goal.goal().param_env,
- alias.trait_ref(interner),
- );
- self.with_derived_obligation(obligation, |this| {
- goal.infcx().visit_proof_tree_at_depth(
- goal.goal().with(interner, alias.trait_ref(interner)),
- goal.depth() + 1,
- this,
- )
- })
- }
-
- /// If we have no candidates, then it's likely that there is a
- /// non-well-formed alias in the goal.
- fn detect_error_from_empty_candidates(
- &mut self,
- goal: &inspect::InspectGoal<'_, 'db>,
- ) -> ControlFlow<PredicateObligation<'db>> {
- let interner = goal.infcx().interner;
- let pred_kind = goal.goal().predicate.kind();
-
- match pred_kind.no_bound_vars() {
- Some(PredicateKind::Clause(ClauseKind::Trait(pred))) => {
- self.detect_error_in_self_ty_normalization(goal, pred.self_ty())?;
- }
- Some(PredicateKind::NormalizesTo(pred)) => {
- if let AliasTermKind::ProjectionTy | AliasTermKind::ProjectionConst =
- pred.alias.kind(interner)
- {
- self.detect_error_in_self_ty_normalization(goal, pred.alias.self_ty())?;
- self.detect_non_well_formed_assoc_item(goal, pred.alias)?;
- }
- }
- Some(_) | None => {}
- }
-
- ControlFlow::Break(self.obligation.clone())
- }
-}
-
-impl<'db> ProofTreeVisitor<'db> for BestObligation<'db> {
- type Result = ControlFlow<PredicateObligation<'db>>;
-
- #[instrument(level = "trace", skip(self, goal), fields(goal = ?goal.goal()))]
- fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'db>) -> Self::Result {
- let interner = goal.infcx().interner;
- // Skip goals that aren't the *reason* for our goal's failure.
- match (self.consider_ambiguities, goal.result()) {
- (true, Ok(Certainty::Maybe { cause: MaybeCause::Ambiguity, .. })) | (false, Err(_)) => {
- }
- _ => return ControlFlow::Continue(()),
- }
-
- let pred = goal.goal().predicate;
-
- let candidates = self.non_trivial_candidates(goal);
- let candidate = match candidates.as_slice() {
- [candidate] => candidate,
- [] => return self.detect_error_from_empty_candidates(goal),
- _ => return ControlFlow::Break(self.obligation.clone()),
- };
-
- // // Don't walk into impls that have `do_not_recommend`.
- // if let inspect::ProbeKind::TraitCandidate {
- // source: CandidateSource::Impl(impl_def_id),
- // result: _,
- // } = candidate.kind()
- // && interner.do_not_recommend_impl(impl_def_id)
- // {
- // trace!("#[do_not_recommend] -> exit");
- // return ControlFlow::Break(self.obligation.clone());
- // }
-
- // FIXME: Also, what about considering >1 layer up the stack? May be necessary
- // for normalizes-to.
- let child_mode = match pred.kind().skip_binder() {
- PredicateKind::Clause(ClauseKind::Trait(trait_pred)) => {
- ChildMode::Trait(pred.kind().rebind(trait_pred))
- }
- PredicateKind::Clause(ClauseKind::HostEffect(host_pred)) => {
- ChildMode::Host(pred.kind().rebind(host_pred))
- }
- PredicateKind::NormalizesTo(normalizes_to)
- if matches!(
- normalizes_to.alias.kind(interner),
- AliasTermKind::ProjectionTy | AliasTermKind::ProjectionConst
- ) =>
- {
- ChildMode::Trait(pred.kind().rebind(TraitPredicate {
- trait_ref: normalizes_to.alias.trait_ref(interner),
- polarity: PredicatePolarity::Positive,
- }))
- }
- PredicateKind::Clause(ClauseKind::WellFormed(term)) => {
- return self.visit_well_formed_goal(candidate, term);
- }
- _ => ChildMode::PassThrough,
- };
-
- let nested_goals = candidate.instantiate_nested_goals();
-
- // If the candidate requires some `T: FnPtr` bound which does not hold should not be treated as
- // an actual candidate, instead we should treat them as if the impl was never considered to
- // have potentially applied. As if `impl<A, R> Trait for for<..> fn(..A) -> R` was written
- // instead of `impl<T: FnPtr> Trait for T`.
- //
- // We do this as a separate loop so that we do not choose to tell the user about some nested
- // goal before we encounter a `T: FnPtr` nested goal.
- for nested_goal in &nested_goals {
- if let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause()
- && interner
- .is_trait_lang_item(poly_trait_pred.def_id(), SolverTraitLangItem::FnPtrTrait)
- && let Err(NoSolution) = nested_goal.result()
- {
- return ControlFlow::Break(self.obligation.clone());
- }
- }
-
- for nested_goal in nested_goals {
- trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result()));
-
- let nested_pred = nested_goal.goal().predicate;
-
- let make_obligation = || Obligation {
- cause: ObligationCause::dummy(),
- param_env: nested_goal.goal().param_env,
- predicate: nested_pred,
- recursion_depth: self.obligation.recursion_depth + 1,
- };
-
- let obligation = match (child_mode, nested_goal.source()) {
- (
- ChildMode::Trait(_) | ChildMode::Host(_),
- GoalSource::Misc | GoalSource::TypeRelating | GoalSource::NormalizeGoal(_),
- ) => {
- continue;
- }
- (ChildMode::Trait(_parent_trait_pred), GoalSource::ImplWhereBound) => {
- make_obligation()
- }
- (
- ChildMode::Host(_parent_host_pred),
- GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition,
- ) => make_obligation(),
- (ChildMode::PassThrough, _)
- | (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => {
- make_obligation()
- }
- };
-
- self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
- }
-
- // alias-relate may fail because the lhs or rhs can't be normalized,
- // and therefore is treated as rigid.
- if let Some(PredicateKind::AliasRelate(lhs, rhs, _)) = pred.kind().no_bound_vars() {
- goal.infcx().visit_proof_tree_at_depth(
- goal.goal().with(interner, ClauseKind::WellFormed(lhs)),
- goal.depth() + 1,
- self,
- )?;
- goal.infcx().visit_proof_tree_at_depth(
- goal.goal().with(interner, ClauseKind::WellFormed(rhs)),
- goal.depth() + 1,
- self,
- )?;
- }
-
- self.detect_trait_error_in_higher_ranked_projection(goal)?;
-
- ControlFlow::Break(self.obligation.clone())
- }
-}
-
-#[derive(Debug, Copy, Clone)]
-enum ChildMode<'db> {
- // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`,
- // and skip all `GoalSource::Misc`, which represent useless obligations
- // such as alias-eq which may not hold.
- Trait(PolyTraitPredicate<'db>),
- // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`,
- // and skip all `GoalSource::Misc`, which represent useless obligations
- // such as alias-eq which may not hold.
- Host(Binder<'db, HostEffectPredicate<DbInterner<'db>>>),
- // Skip trying to derive an `ObligationCause` from this obligation, and
- // report *all* sub-obligations as if they came directly from the parent
- // obligation.
- PassThrough,
-}
-
-impl<'db> NextSolverError<'db> {
- pub fn to_debuggable_error(&self, infcx: &InferCtxt<'db>) -> FulfillmentError<'db> {
- match self {
- NextSolverError::TrueError(obligation) => {
- fulfillment_error_for_no_solution(infcx, obligation.clone())
- }
- NextSolverError::Ambiguity(obligation) => {
- fulfillment_error_for_stalled(infcx, obligation.clone())
- }
- NextSolverError::Overflow(obligation) => {
- fulfillment_error_for_overflow(infcx, obligation.clone())
- }
- }
- }
-}
-
-mod wf {
- use hir_def::signatures::ImplSignature;
- use hir_def::{GeneralConstId, ItemContainerId};
- use rustc_type_ir::inherent::{
- AdtDef, BoundExistentialPredicates, GenericArgs as _, IntoKind, SliceLike, Term as _,
- Ty as _,
- };
- use rustc_type_ir::lang_items::SolverTraitLangItem;
- use rustc_type_ir::{
- Interner, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
- };
- use tracing::{debug, instrument};
-
- use crate::next_solver::infer::InferCtxt;
- use crate::next_solver::infer::traits::{Obligation, ObligationCause, PredicateObligations};
- use crate::next_solver::{
- Binder, ClauseKind, Const, ConstKind, Ctor, DbInterner, ExistentialPredicate, GenericArgs,
- ParamEnv, Predicate, PredicateKind, Region, SolverDefId, Term, TraitRef, Ty, TyKind,
- };
-
- /// Compute the predicates that are required for a type to be well-formed.
- ///
- /// This is only intended to be used in the new solver, since it does not
- /// take into account recursion depth or proper error-reporting spans.
- pub(crate) fn unnormalized_obligations<'db>(
- infcx: &InferCtxt<'db>,
- param_env: ParamEnv<'db>,
- term: Term<'db>,
- ) -> Option<PredicateObligations<'db>> {
- debug_assert_eq!(term, infcx.resolve_vars_if_possible(term));
-
- // However, if `arg` IS an unresolved inference variable, returns `None`,
- // because we are not able to make any progress at all. This is to prevent
- // cycles where we say "?0 is WF if ?0 is WF".
- if term.is_infer() {
- return None;
- }
-
- let mut wf =
- WfPredicates { infcx, param_env, out: PredicateObligations::new(), recursion_depth: 0 };
- wf.add_wf_preds_for_term(term);
- Some(wf.out)
- }
-
- struct WfPredicates<'a, 'db> {
- infcx: &'a InferCtxt<'db>,
- param_env: ParamEnv<'db>,
- out: PredicateObligations<'db>,
- recursion_depth: usize,
- }
-
- impl<'a, 'db> WfPredicates<'a, 'db> {
- fn interner(&self) -> DbInterner<'db> {
- self.infcx.interner
- }
-
- fn require_sized(&mut self, subty: Ty<'db>) {
- if !subty.has_escaping_bound_vars() {
- let cause = ObligationCause::new();
- let trait_ref = TraitRef::new(
- self.interner(),
- self.interner().require_trait_lang_item(SolverTraitLangItem::Sized),
- [subty],
- );
- self.out.push(Obligation::with_depth(
- self.interner(),
- cause,
- self.recursion_depth,
- self.param_env,
- Binder::dummy(trait_ref),
- ));
- }
- }
-
- /// Pushes all the predicates needed to validate that `term` is WF into `out`.
- #[instrument(level = "debug", skip(self))]
- fn add_wf_preds_for_term(&mut self, term: Term<'db>) {
- term.visit_with(self);
- debug!(?self.out);
- }
-
- #[instrument(level = "debug", skip(self))]
- fn nominal_obligations(
- &mut self,
- def_id: SolverDefId,
- args: GenericArgs<'db>,
- ) -> PredicateObligations<'db> {
- // PERF: `Sized`'s predicates include `MetaSized`, but both are compiler implemented marker
- // traits, so `MetaSized` will always be WF if `Sized` is WF and vice-versa. Determining
- // the nominal obligations of `Sized` would in-effect just elaborate `MetaSized` and make
- // the compiler do a bunch of work needlessly.
- if let SolverDefId::TraitId(def_id) = def_id
- && self.interner().is_trait_lang_item(def_id.into(), SolverTraitLangItem::Sized)
- {
- return Default::default();
- }
-
- self.interner()
- .predicates_of(def_id)
- .iter_instantiated(self.interner(), args)
- .map(|pred| {
- let cause = ObligationCause::new();
- Obligation::with_depth(
- self.interner(),
- cause,
- self.recursion_depth,
- self.param_env,
- pred,
- )
- })
- .filter(|pred| !pred.has_escaping_bound_vars())
- .collect()
- }
-
- fn add_wf_preds_for_dyn_ty(
- &mut self,
- _ty: Ty<'db>,
- data: &[Binder<'db, ExistentialPredicate<'db>>],
- region: Region<'db>,
- ) {
- // Imagine a type like this:
- //
- // trait Foo { }
- // trait Bar<'c> : 'c { }
- //
- // &'b (Foo+'c+Bar<'d>)
- // ^
- //
- // In this case, the following relationships must hold:
- //
- // 'b <= 'c
- // 'd <= 'c
- //
- // The first conditions is due to the normal region pointer
- // rules, which say that a reference cannot outlive its
- // referent.
- //
- // The final condition may be a bit surprising. In particular,
- // you may expect that it would have been `'c <= 'd`, since
- // usually lifetimes of outer things are conservative
- // approximations for inner things. However, it works somewhat
- // differently with trait objects: here the idea is that if the
- // user specifies a region bound (`'c`, in this case) it is the
- // "master bound" that *implies* that bounds from other traits are
- // all met. (Remember that *all bounds* in a type like
- // `Foo+Bar+Zed` must be met, not just one, hence if we write
- // `Foo<'x>+Bar<'y>`, we know that the type outlives *both* 'x and
- // 'y.)
- //
- // Note: in fact we only permit builtin traits, not `Bar<'d>`, I
- // am looking forward to the future here.
- if !data.has_escaping_bound_vars() && !region.has_escaping_bound_vars() {
- let implicit_bounds = object_region_bounds(self.interner(), data);
-
- let explicit_bound = region;
-
- self.out.reserve(implicit_bounds.len());
- for implicit_bound in implicit_bounds {
- let cause = ObligationCause::new();
- let outlives = Binder::dummy(rustc_type_ir::OutlivesPredicate(
- explicit_bound,
- implicit_bound,
- ));
- self.out.push(Obligation::with_depth(
- self.interner(),
- cause,
- self.recursion_depth,
- self.param_env,
- outlives,
- ));
- }
-
- // We don't add any wf predicates corresponding to the trait ref's generic arguments
- // which allows code like this to compile:
- // ```rust
- // trait Trait<T: Sized> {}
- // fn foo(_: &dyn Trait<[u32]>) {}
- // ```
- }
- }
- }
-
- impl<'a, 'db> TypeVisitor<DbInterner<'db>> for WfPredicates<'a, 'db> {
- type Result = ();
-
- fn visit_ty(&mut self, t: Ty<'db>) -> Self::Result {
- debug!("wf bounds for t={:?} t.kind={:#?}", t, t.kind());
-
- let tcx = self.interner();
-
- match t.kind() {
- TyKind::Bool
- | TyKind::Char
- | TyKind::Int(..)
- | TyKind::Uint(..)
- | TyKind::Float(..)
- | TyKind::Error(_)
- | TyKind::Str
- | TyKind::CoroutineWitness(..)
- | TyKind::Never
- | TyKind::Param(_)
- | TyKind::Bound(..)
- | TyKind::Placeholder(..)
- | TyKind::Foreign(..) => {
- // WfScalar, WfParameter, etc
- }
-
- // Can only infer to `TyKind::Int(_) | TyKind::Uint(_)`.
- TyKind::Infer(rustc_type_ir::IntVar(_)) => {}
-
- // Can only infer to `TyKind::Float(_)`.
- TyKind::Infer(rustc_type_ir::FloatVar(_)) => {}
-
- TyKind::Slice(subty) => {
- self.require_sized(subty);
- }
-
- TyKind::Array(subty, len) => {
- self.require_sized(subty);
- // Note that the len being WF is implicitly checked while visiting.
- // Here we just check that it's of type usize.
- let cause = ObligationCause::new();
- self.out.push(Obligation::with_depth(
- tcx,
- cause,
- self.recursion_depth,
- self.param_env,
- Binder::dummy(PredicateKind::Clause(ClauseKind::ConstArgHasType(
- len,
- Ty::new_unit(self.interner()),
- ))),
- ));
- }
-
- TyKind::Pat(base_ty, _pat) => {
- self.require_sized(base_ty);
- }
-
- TyKind::Tuple(tys) => {
- if let Some((_last, rest)) = tys.split_last() {
- for &elem in rest {
- self.require_sized(elem);
- }
- }
- }
-
- TyKind::RawPtr(_, _) => {
- // Simple cases that are WF if their type args are WF.
- }
-
- TyKind::Alias(
- rustc_type_ir::Projection | rustc_type_ir::Opaque | rustc_type_ir::Free,
- data,
- ) => {
- let obligations = self.nominal_obligations(data.def_id, data.args);
- self.out.extend(obligations);
- }
- TyKind::Alias(rustc_type_ir::Inherent, _data) => {
- return;
- }
-
- TyKind::Adt(def, args) => {
- // WfNominalType
- let obligations = self.nominal_obligations(def.def_id().0.into(), args);
- self.out.extend(obligations);
- }
-
- TyKind::FnDef(did, args) => {
- // HACK: Check the return type of function definitions for
- // well-formedness to mostly fix #84533. This is still not
- // perfect and there may be ways to abuse the fact that we
- // ignore requirements with escaping bound vars. That's a
- // more general issue however.
- let fn_sig = tcx.fn_sig(did).instantiate(tcx, args);
- fn_sig.output().skip_binder().visit_with(self);
-
- let did = match did.0 {
- hir_def::CallableDefId::FunctionId(id) => id.into(),
- hir_def::CallableDefId::StructId(id) => SolverDefId::Ctor(Ctor::Struct(id)),
- hir_def::CallableDefId::EnumVariantId(id) => {
- SolverDefId::Ctor(Ctor::Enum(id))
- }
- };
- let obligations = self.nominal_obligations(did, args);
- self.out.extend(obligations);
- }
-
- TyKind::Ref(r, rty, _) => {
- // WfReference
- if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
- let cause = ObligationCause::new();
- self.out.push(Obligation::with_depth(
- tcx,
- cause,
- self.recursion_depth,
- self.param_env,
- Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(
- rustc_type_ir::OutlivesPredicate(rty, r),
- ))),
- ));
- }
- }
-
- TyKind::Coroutine(did, args, ..) => {
- // Walk ALL the types in the coroutine: this will
- // include the upvar types as well as the yield
- // type. Note that this is mildly distinct from
- // the closure case, where we have to be careful
- // about the signature of the closure. We don't
- // have the problem of implied bounds here since
- // coroutines don't take arguments.
- let obligations = self.nominal_obligations(did.0.into(), args);
- self.out.extend(obligations);
- }
-
- TyKind::Closure(did, args) => {
- // Note that we cannot skip the generic types
- // types. Normally, within the fn
- // body where they are created, the generics will
- // always be WF, and outside of that fn body we
- // are not directly inspecting closure types
- // anyway, except via auto trait matching (which
- // only inspects the upvar types).
- // But when a closure is part of a type-alias-impl-trait
- // then the function that created the defining site may
- // have had more bounds available than the type alias
- // specifies. This may cause us to have a closure in the
- // hidden type that is not actually well formed and
- // can cause compiler crashes when the user abuses unsafe
- // code to procure such a closure.
- // See tests/ui/type-alias-impl-trait/wf_check_closures.rs
- let obligations = self.nominal_obligations(did.0.into(), args);
- self.out.extend(obligations);
- // Only check the upvar types for WF, not the rest
- // of the types within. This is needed because we
- // capture the signature and it may not be WF
- // without the implied bounds. Consider a closure
- // like `|x: &'a T|` -- it may be that `T: 'a` is
- // not known to hold in the creator's context (and
- // indeed the closure may not be invoked by its
- // creator, but rather turned to someone who *can*
- // verify that).
- //
- // The special treatment of closures here really
- // ought not to be necessary either; the problem
- // is related to #25860 -- there is no way for us
- // to express a fn type complete with the implied
- // bounds that it is assuming. I think in reality
- // the WF rules around fn are a bit messed up, and
- // that is the rot problem: `fn(&'a T)` should
- // probably always be WF, because it should be
- // shorthand for something like `where(T: 'a) {
- // fn(&'a T) }`, as discussed in #25860.
- let upvars = args.as_closure().tupled_upvars_ty();
- return upvars.visit_with(self);
- }
-
- TyKind::CoroutineClosure(did, args) => {
- // See the above comments. The same apply to coroutine-closures.
- let obligations = self.nominal_obligations(did.0.into(), args);
- self.out.extend(obligations);
- let upvars = args.as_coroutine_closure().tupled_upvars_ty();
- return upvars.visit_with(self);
- }
-
- TyKind::FnPtr(..) => {
- // Let the visitor iterate into the argument/return
- // types appearing in the fn signature.
- }
- TyKind::UnsafeBinder(_ty) => {}
-
- TyKind::Dynamic(data, r) => {
- // WfObject
- //
- // Here, we defer WF checking due to higher-ranked
- // regions. This is perhaps not ideal.
- self.add_wf_preds_for_dyn_ty(t, data.as_slice(), r);
-
- // FIXME(#27579) RFC also considers adding trait
- // obligations that don't refer to Self and
- // checking those
- if let Some(principal) = data.principal_def_id() {
- self.out.push(Obligation::with_depth(
- tcx,
- ObligationCause::new(),
- self.recursion_depth,
- self.param_env,
- Binder::dummy(PredicateKind::DynCompatible(principal)),
- ));
- }
- }
-
- // Inference variables are the complicated case, since we don't
- // know what type they are. We do two things:
- //
- // 1. Check if they have been resolved, and if so proceed with
- // THAT type.
- // 2. If not, we've at least simplified things (e.g., we went
- // from `Vec?0>: WF` to `?0: WF`), so we can
- // register a pending obligation and keep
- // moving. (Goal is that an "inductive hypothesis"
- // is satisfied to ensure termination.)
- // See also the comment on `fn obligations`, describing cycle
- // prevention, which happens before this can be reached.
- TyKind::Infer(_) => {
- let cause = ObligationCause::new();
- self.out.push(Obligation::with_depth(
- tcx,
- cause,
- self.recursion_depth,
- self.param_env,
- Binder::dummy(PredicateKind::Clause(ClauseKind::WellFormed(t.into()))),
- ));
- }
- }
-
- t.super_visit_with(self)
- }
-
- fn visit_const(&mut self, c: Const<'db>) -> Self::Result {
- let tcx = self.interner();
-
- match c.kind() {
- ConstKind::Unevaluated(uv) => {
- if !c.has_escaping_bound_vars() {
- let predicate =
- Binder::dummy(PredicateKind::Clause(ClauseKind::ConstEvaluatable(c)));
- let cause = ObligationCause::new();
- self.out.push(Obligation::with_depth(
- tcx,
- cause,
- self.recursion_depth,
- self.param_env,
- predicate,
- ));
-
- if let GeneralConstId::ConstId(uv_def) = uv.def.0
- && let ItemContainerId::ImplId(impl_) =
- uv_def.loc(self.interner().db).container
- && ImplSignature::of(self.interner().db, impl_).target_trait.is_none()
- {
- return; // Subtree is handled by above function
- } else {
- let obligations = self.nominal_obligations(uv.def.into(), uv.args);
- self.out.extend(obligations);
- }
- }
- }
- ConstKind::Infer(_) => {
- let cause = ObligationCause::new();
-
- self.out.push(Obligation::with_depth(
- tcx,
- cause,
- self.recursion_depth,
- self.param_env,
- Binder::dummy(PredicateKind::Clause(ClauseKind::WellFormed(c.into()))),
- ));
- }
- ConstKind::Expr(_) => {
- // FIXME(generic_const_exprs): this doesn't verify that given `Expr(N + 1)` the
- // trait bound `typeof(N): Add<typeof(1)>` holds. This is currently unnecessary
- // as `ConstKind::Expr` is only produced via normalization of `ConstKind::Unevaluated`
- // which means that the `DefId` would have been typeck'd elsewhere. However in
- // the future we may allow directly lowering to `ConstKind::Expr` in which case
- // we would not be proving bounds we should.
-
- let predicate =
- Binder::dummy(PredicateKind::Clause(ClauseKind::ConstEvaluatable(c)));
- let cause = ObligationCause::new();
- self.out.push(Obligation::with_depth(
- tcx,
- cause,
- self.recursion_depth,
- self.param_env,
- predicate,
- ));
- }
-
- ConstKind::Error(_)
- | ConstKind::Param(_)
- | ConstKind::Bound(..)
- | ConstKind::Placeholder(..) => {
- // These variants are trivially WF, so nothing to do here.
- }
- ConstKind::Value(..) => {
- // FIXME: Enforce that values are structurally-matchable.
- }
- }
-
- c.super_visit_with(self)
- }
-
- fn visit_predicate(&mut self, _p: Predicate<'db>) -> Self::Result {
- panic!("predicate should not be checked for well-formedness");
- }
- }
-
- /// Given an object type like `SomeTrait + Send`, computes the lifetime
- /// bounds that must hold on the elided self type. These are derived
- /// from the declarations of `SomeTrait`, `Send`, and friends -- if
- /// they declare `trait SomeTrait : 'static`, for example, then
- /// `'static` would appear in the list.
- ///
- /// N.B., in some cases, particularly around higher-ranked bounds,
- /// this function returns a kind of conservative approximation.
- /// That is, all regions returned by this function are definitely
- /// required, but there may be other region bounds that are not
- /// returned, as well as requirements like `for<'a> T: 'a`.
- ///
- /// Requires that trait definitions have been processed so that we can
- /// elaborate predicates and walk supertraits.
- pub(crate) fn object_region_bounds<'db>(
- interner: DbInterner<'db>,
- existential_predicates: &[Binder<'db, ExistentialPredicate<'db>>],
- ) -> Vec<Region<'db>> {
- let erased_self_ty = Ty::new_unit(interner);
-
- let predicates = existential_predicates
- .iter()
- .map(|predicate| predicate.with_self_ty(interner, erased_self_ty));
-
- rustc_type_ir::elaborate::elaborate(interner, predicates)
- .filter_map(|pred| {
- debug!(?pred);
- match pred.kind().skip_binder() {
- ClauseKind::TypeOutlives(rustc_type_ir::OutlivesPredicate(ref t, ref r)) => {
- // Search for a bound of the form `erased_self_ty
- // : 'a`, but be wary of something like `for<'a>
- // erased_self_ty : 'a` (we interpret a
- // higher-ranked bound like that as 'static,
- // though at present the code in `fulfill.rs`
- // considers such bounds to be unsatisfiable, so
- // it's kind of a moot point since you could never
- // construct such an object, but this seems
- // correct even if that code changes).
- if t == &erased_self_ty && !r.has_escaping_bound_vars() {
- Some(*r)
- } else {
- None
- }
- }
- ClauseKind::Trait(_)
- | ClauseKind::HostEffect(..)
- | ClauseKind::RegionOutlives(_)
- | ClauseKind::Projection(_)
- | ClauseKind::ConstArgHasType(_, _)
- | ClauseKind::WellFormed(_)
- | ClauseKind::UnstableFeature(_)
- | ClauseKind::ConstEvaluatable(_) => None,
- }
- })
- .collect()
- }
-}
diff --git a/crates/hir-ty/src/next_solver/infer/canonical/canonicalizer.rs b/crates/hir-ty/src/next_solver/infer/canonical/canonicalizer.rs
index ccd9359010..33e4c175d0 100644
--- a/crates/hir-ty/src/next_solver/infer/canonical/canonicalizer.rs
+++ b/crates/hir-ty/src/next_solver/infer/canonical/canonicalizer.rs
@@ -16,11 +16,11 @@ use rustc_type_ir::{
use smallvec::SmallVec;
use tracing::debug;
-use crate::next_solver::infer::InferCtxt;
use crate::next_solver::{
- Binder, Canonical, CanonicalVarKind, CanonicalVars, Const, ConstKind, DbInterner, GenericArg,
- Placeholder, Region, Ty, TyKind,
+ Binder, Canonical, CanonicalVarKind, CanonicalVarKinds, Const, ConstKind, DbInterner,
+ GenericArg, PlaceholderConst, PlaceholderRegion, Region, Ty, TyKind,
};
+use crate::next_solver::{PlaceholderType, infer::InferCtxt};
/// When we canonicalize a value to form a query, we wind up replacing
/// various parts of it with canonical variables. This struct stores
@@ -498,7 +498,7 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
{
let base = Canonical {
max_universe: UniverseIndex::ROOT,
- variables: CanonicalVars::empty(tcx),
+ var_kinds: CanonicalVarKinds::empty(tcx),
value: (),
};
Canonicalizer::canonicalize_with_base(
@@ -539,7 +539,7 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
tcx,
canonicalize_mode: canonicalize_region_mode,
needs_canonical_flags,
- variables: SmallVec::from_slice(base.variables.as_slice()),
+ variables: SmallVec::from_slice(base.var_kinds.as_slice()),
query_state,
indices: FxHashMap::default(),
sub_root_lookup_table: Default::default(),
@@ -562,7 +562,7 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
debug_assert!(!out_value.has_infer() && !out_value.has_placeholders());
let canonical_variables =
- CanonicalVars::new_from_slice(&canonicalizer.universe_canonicalized_variables());
+ CanonicalVarKinds::new_from_slice(&canonicalizer.universe_canonicalized_variables());
let max_universe = canonical_variables
.iter()
@@ -570,7 +570,7 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
.max()
.unwrap_or(UniverseIndex::ROOT);
- Canonical { max_universe, variables: canonical_variables, value: (base.value, out_value) }
+ Canonical { max_universe, var_kinds: canonical_variables, value: (base.value, out_value) }
}
/// Creates a canonical variable replacing `kind` from the input,
@@ -670,22 +670,22 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
CanonicalVarKind::Region(u) => CanonicalVarKind::Region(reverse_universe_map[&u]),
CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]),
CanonicalVarKind::PlaceholderTy(placeholder) => {
- CanonicalVarKind::PlaceholderTy(Placeholder {
- universe: reverse_universe_map[&placeholder.universe],
- ..placeholder
- })
+ CanonicalVarKind::PlaceholderTy(PlaceholderType::new(
+ reverse_universe_map[&placeholder.universe],
+ placeholder.bound,
+ ))
}
CanonicalVarKind::PlaceholderRegion(placeholder) => {
- CanonicalVarKind::PlaceholderRegion(Placeholder {
- universe: reverse_universe_map[&placeholder.universe],
- ..placeholder
- })
+ CanonicalVarKind::PlaceholderRegion(PlaceholderRegion::new(
+ reverse_universe_map[&placeholder.universe],
+ placeholder.bound,
+ ))
}
CanonicalVarKind::PlaceholderConst(placeholder) => {
- CanonicalVarKind::PlaceholderConst(Placeholder {
- universe: reverse_universe_map[&placeholder.universe],
- ..placeholder
- })
+ CanonicalVarKind::PlaceholderConst(PlaceholderConst::new(
+ reverse_universe_map[&placeholder.universe],
+ placeholder.bound,
+ ))
}
})
.collect()
diff --git a/crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs b/crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs
index 61d1e97746..1738552a8e 100644
--- a/crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs
+++ b/crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs
@@ -69,7 +69,7 @@ impl<'db, V> CanonicalExt<'db, V> for Canonical<'db, V> {
where
T: TypeFoldable<DbInterner<'db>>,
{
- assert_eq!(self.variables.len(), var_values.len());
+ assert_eq!(self.var_kinds.len(), var_values.len());
let value = projection_fn(&self.value);
instantiate_value(tcx, var_values, value)
}
@@ -90,15 +90,15 @@ where
value
} else {
let delegate = FnMutDelegate {
- regions: &mut |br: BoundRegion| match var_values[br.var].kind() {
+ regions: &mut |br: BoundRegion<'db>| match var_values[br.var].kind() {
GenericArgKind::Lifetime(l) => l,
r => panic!("{br:?} is a region but value is {r:?}"),
},
- types: &mut |bound_ty: BoundTy| match var_values[bound_ty.var].kind() {
+ types: &mut |bound_ty: BoundTy<'db>| match var_values[bound_ty.var].kind() {
GenericArgKind::Type(ty) => ty,
r => panic!("{bound_ty:?} is a type but value is {r:?}"),
},
- consts: &mut |bound_ct: BoundConst| match var_values[bound_ct.var].kind() {
+ consts: &mut |bound_ct: BoundConst<'db>| match var_values[bound_ct.var].kind() {
GenericArgKind::Const(ct) => ct,
c => panic!("{bound_ct:?} is a const but value is {c:?}"),
},
@@ -356,7 +356,7 @@ impl<'db> InferCtxt<'db> {
// result, then we can type the corresponding value from the
// input. See the example above.
let mut opt_values: IndexVec<BoundVar, Option<GenericArg<'db>>> =
- IndexVec::from_elem_n(None, query_response.variables.len());
+ IndexVec::from_elem_n(None, query_response.var_kinds.len());
for (original_value, result_value) in iter::zip(&original_values.var_values, result_values)
{
@@ -368,7 +368,7 @@ impl<'db> InferCtxt<'db> {
// more involved. They are also a lot rarer than region variables.
if let TyKind::Bound(index_kind, b) = result_value.kind()
&& !matches!(
- query_response.variables.as_slice()[b.var.as_usize()],
+ query_response.var_kinds.as_slice()[b.var.as_usize()],
CanonicalVarKind::Ty { .. }
)
{
@@ -398,7 +398,7 @@ impl<'db> InferCtxt<'db> {
// given variable in the loop above, use that. Otherwise, use
// a fresh inference variable.
let interner = self.interner;
- let variables = query_response.variables;
+ let variables = query_response.var_kinds;
let var_values =
CanonicalVarValues::instantiate(interner, variables, |var_values, kind| {
if kind.universe() != UniverseIndex::ROOT {
diff --git a/crates/hir-ty/src/next_solver/infer/canonical/mod.rs b/crates/hir-ty/src/next_solver/infer/canonical/mod.rs
index a0420a5a00..1fefc0f265 100644
--- a/crates/hir-ty/src/next_solver/infer/canonical/mod.rs
+++ b/crates/hir-ty/src/next_solver/infer/canonical/mod.rs
@@ -23,7 +23,7 @@
use crate::next_solver::{
ArgOutlivesPredicate, Canonical, CanonicalVarValues, Const, DbInterner, GenericArg,
- OpaqueTypeKey, PlaceholderConst, PlaceholderRegion, PlaceholderTy, Region, Ty, TyKind,
+ OpaqueTypeKey, PlaceholderConst, PlaceholderRegion, PlaceholderType, Region, Ty, TyKind,
infer::InferCtxt,
};
use instantiate::CanonicalExt;
@@ -70,7 +70,7 @@ impl<'db> InferCtxt<'db> {
let var_values = CanonicalVarValues::instantiate(
self.interner,
- canonical.variables,
+ canonical.var_kinds,
|var_values, info| self.instantiate_canonical_var(info, var_values, |ui| universes[ui]),
);
let result = canonical.instantiate(self.interner, &var_values);
@@ -110,9 +110,9 @@ impl<'db> InferCtxt<'db> {
CanonicalVarKind::Float => self.next_float_var().into(),
- CanonicalVarKind::PlaceholderTy(PlaceholderTy { universe, bound }) => {
+ CanonicalVarKind::PlaceholderTy(PlaceholderType { universe, bound, .. }) => {
let universe_mapped = universe_map(universe);
- let placeholder_mapped = PlaceholderTy { universe: universe_mapped, bound };
+ let placeholder_mapped = PlaceholderType::new(universe_mapped, bound);
Ty::new_placeholder(self.interner, placeholder_mapped).into()
}
@@ -120,18 +120,16 @@ impl<'db> InferCtxt<'db> {
self.next_region_var_in_universe(universe_map(ui)).into()
}
- CanonicalVarKind::PlaceholderRegion(PlaceholderRegion { universe, bound }) => {
+ CanonicalVarKind::PlaceholderRegion(PlaceholderRegion { universe, bound, .. }) => {
let universe_mapped = universe_map(universe);
- let placeholder_mapped: crate::next_solver::Placeholder<
- crate::next_solver::BoundRegion,
- > = PlaceholderRegion { universe: universe_mapped, bound };
+ let placeholder_mapped = PlaceholderRegion::new(universe_mapped, bound);
Region::new_placeholder(self.interner, placeholder_mapped).into()
}
CanonicalVarKind::Const(ui) => self.next_const_var_in_universe(universe_map(ui)).into(),
- CanonicalVarKind::PlaceholderConst(PlaceholderConst { universe, bound }) => {
+ CanonicalVarKind::PlaceholderConst(PlaceholderConst { universe, bound, .. }) => {
let universe_mapped = universe_map(universe);
- let placeholder_mapped = PlaceholderConst { universe: universe_mapped, bound };
+ let placeholder_mapped = PlaceholderConst::new(universe_mapped, bound);
Const::new_placeholder(self.interner, placeholder_mapped).into()
}
}
diff --git a/crates/hir-ty/src/next_solver/infer/mod.rs b/crates/hir-ty/src/next_solver/infer/mod.rs
index 21baacb116..a6957c66ff 100644
--- a/crates/hir-ty/src/next_solver/infer/mod.rs
+++ b/crates/hir-ty/src/next_solver/infer/mod.rs
@@ -30,7 +30,7 @@ use unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey};
pub use crate::next_solver::infer::traits::ObligationInspector;
use crate::next_solver::{
- ArgOutlivesPredicate, BoundConst, BoundRegion, BoundTy, BoundVarKind, Goal, Predicate,
+ ArgOutlivesPredicate, BoundConst, BoundRegion, BoundTy, BoundVariableKind, Goal, Predicate,
SolverContext,
fold::BoundVarReplacerDelegate,
infer::{at::ToTrace, select::EvaluationResult, traits::PredicateObligation},
@@ -53,7 +53,7 @@ mod outlives;
pub mod region_constraints;
pub mod relate;
pub mod resolve;
-pub(crate) mod select;
+pub mod select;
pub(crate) mod snapshot;
pub(crate) mod traits;
mod type_variable;
@@ -366,7 +366,7 @@ impl<'db> InferCtxtBuilder<'db> {
where
T: TypeFoldable<DbInterner<'db>>,
{
- let infcx = self.build(input.typing_mode);
+ let infcx = self.build(input.typing_mode.0);
let (value, args) = infcx.instantiate_canonical(&input.canonical);
(infcx, value, args)
}
@@ -1098,9 +1098,9 @@ impl<'db> InferCtxt<'db> {
for bound_var_kind in bound_vars {
let arg: GenericArg<'db> = match bound_var_kind {
- BoundVarKind::Ty(_) => self.next_ty_var().into(),
- BoundVarKind::Region(_) => self.next_region_var().into(),
- BoundVarKind::Const => self.next_const_var().into(),
+ BoundVariableKind::Ty(_) => self.next_ty_var().into(),
+ BoundVariableKind::Region(_) => self.next_region_var().into(),
+ BoundVariableKind::Const => self.next_const_var().into(),
};
args.push(arg);
}
@@ -1110,13 +1110,13 @@ impl<'db> InferCtxt<'db> {
}
impl<'db> BoundVarReplacerDelegate<'db> for ToFreshVars<'db> {
- fn replace_region(&mut self, br: BoundRegion) -> Region<'db> {
+ fn replace_region(&mut self, br: BoundRegion<'db>) -> Region<'db> {
self.args[br.var.index()].expect_region()
}
- fn replace_ty(&mut self, bt: BoundTy) -> Ty<'db> {
+ fn replace_ty(&mut self, bt: BoundTy<'db>) -> Ty<'db> {
self.args[bt.var.index()].expect_ty()
}
- fn replace_const(&mut self, bv: BoundConst) -> Const<'db> {
+ fn replace_const(&mut self, bv: BoundConst<'db>) -> Const<'db> {
self.args[bv.var.index()].expect_const()
}
}
diff --git a/crates/hir-ty/src/next_solver/infer/region_constraints/mod.rs b/crates/hir-ty/src/next_solver/infer/region_constraints/mod.rs
index ae5930d55c..7bb39519f5 100644
--- a/crates/hir-ty/src/next_solver/infer/region_constraints/mod.rs
+++ b/crates/hir-ty/src/next_solver/infer/region_constraints/mod.rs
@@ -17,7 +17,7 @@ use super::MemberConstraint;
use super::unify_key::RegionVidKey;
use crate::next_solver::infer::snapshot::undo_log::{InferCtxtUndoLogs, Snapshot};
use crate::next_solver::infer::unify_key::RegionVariableValue;
-use crate::next_solver::{AliasTy, Binder, DbInterner, ParamTy, PlaceholderTy, Region, Ty};
+use crate::next_solver::{AliasTy, Binder, DbInterner, ParamTy, PlaceholderType, Region, Ty};
#[derive(Debug, Clone, Default)]
pub struct RegionConstraintStorage<'db> {
@@ -122,7 +122,7 @@ pub struct Verify<'db> {
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum GenericKind<'db> {
Param(ParamTy),
- Placeholder(PlaceholderTy),
+ Placeholder(PlaceholderType<'db>),
Alias(AliasTy<'db>),
}
diff --git a/crates/hir-ty/src/next_solver/infer/relate/generalize.rs b/crates/hir-ty/src/next_solver/infer/relate/generalize.rs
index 0f7ae99fa4..d621dd4906 100644
--- a/crates/hir-ty/src/next_solver/infer/relate/generalize.rs
+++ b/crates/hir-ty/src/next_solver/infer/relate/generalize.rs
@@ -531,7 +531,7 @@ impl<'db> TypeRelation<DbInterner<'db>> for Generalizer<'_, 'db> {
}
}
- TyKind::Alias(_, data) => match self.structurally_relate_aliases {
+ TyKind::Alias(data) => match self.structurally_relate_aliases {
StructurallyRelateAliases::No => self.generalize_alias_ty(data),
StructurallyRelateAliases::Yes => relate::structurally_relate_tys(self, t, t),
},
diff --git a/crates/hir-ty/src/next_solver/infer/relate/higher_ranked.rs b/crates/hir-ty/src/next_solver/infer/relate/higher_ranked.rs
index c523751e03..cfa864406c 100644
--- a/crates/hir-ty/src/next_solver/infer/relate/higher_ranked.rs
+++ b/crates/hir-ty/src/next_solver/infer/relate/higher_ranked.rs
@@ -8,7 +8,7 @@ use crate::next_solver::fold::FnMutDelegate;
use crate::next_solver::infer::InferCtxt;
use crate::next_solver::{
Binder, BoundConst, BoundRegion, BoundTy, Const, DbInterner, PlaceholderConst,
- PlaceholderRegion, PlaceholderTy, Region, Ty,
+ PlaceholderRegion, PlaceholderType, Region, Ty,
};
impl<'db> InferCtxt<'db> {
@@ -35,23 +35,14 @@ impl<'db> InferCtxt<'db> {
let next_universe = self.create_next_universe();
let delegate = FnMutDelegate {
- regions: &mut |br: BoundRegion| {
- Region::new_placeholder(
- self.interner,
- PlaceholderRegion { universe: next_universe, bound: br },
- )
+ regions: &mut |br: BoundRegion<'db>| {
+ Region::new_placeholder(self.interner, PlaceholderRegion::new(next_universe, br))
},
- types: &mut |bound_ty: BoundTy| {
- Ty::new_placeholder(
- self.interner,
- PlaceholderTy { universe: next_universe, bound: bound_ty },
- )
+ types: &mut |bound_ty: BoundTy<'db>| {
+ Ty::new_placeholder(self.interner, PlaceholderType::new(next_universe, bound_ty))
},
- consts: &mut |bound: BoundConst| {
- Const::new_placeholder(
- self.interner,
- PlaceholderConst { universe: next_universe, bound },
- )
+ consts: &mut |bound: BoundConst<'db>| {
+ Const::new_placeholder(self.interner, PlaceholderConst::new(next_universe, bound))
},
};
diff --git a/crates/hir-ty/src/next_solver/infer/relate/lattice.rs b/crates/hir-ty/src/next_solver/infer/relate/lattice.rs
index 1abe6a93f4..3522827a9e 100644
--- a/crates/hir-ty/src/next_solver/infer/relate/lattice.rs
+++ b/crates/hir-ty/src/next_solver/infer/relate/lattice.rs
@@ -165,8 +165,8 @@ impl<'db> TypeRelation<DbInterner<'db>> for LatticeOp<'_, 'db> {
}
(
- TyKind::Alias(rustc_type_ir::Opaque, AliasTy { def_id: a_def_id, .. }),
- TyKind::Alias(rustc_type_ir::Opaque, AliasTy { def_id: b_def_id, .. }),
+ TyKind::Alias(AliasTy { kind: rustc_type_ir::Opaque { def_id: a_def_id }, .. }),
+ TyKind::Alias(AliasTy { kind: rustc_type_ir::Opaque { def_id: b_def_id }, .. }),
) if a_def_id == b_def_id => super_combine_tys(infcx, self, a, b),
_ => super_combine_tys(infcx, self, a, b),
diff --git a/crates/hir-ty/src/next_solver/inspect.rs b/crates/hir-ty/src/next_solver/inspect.rs
index 5286977549..f30589d91b 100644
--- a/crates/hir-ty/src/next_solver/inspect.rs
+++ b/crates/hir-ty/src/next_solver/inspect.rs
@@ -1,5 +1,3 @@
-pub(crate) use rustc_next_trait_solver::solve::inspect::*;
-
use rustc_ast_ir::try_visit;
use rustc_next_trait_solver::{
canonical::instantiate_canonical_state,
@@ -329,10 +327,6 @@ impl<'a, 'db> InspectGoal<'a, 'db> {
self.result
}
- pub(crate) fn source(&self) -> GoalSource {
- self.source
- }
-
pub(crate) fn depth(&self) -> usize {
self.depth
}
diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs
index 4f30fc7a89..1078a6af42 100644
--- a/crates/hir-ty/src/next_solver/interner.rs
+++ b/crates/hir-ty/src/next_solver/interner.rs
@@ -25,9 +25,9 @@ use rustc_abi::{ReprFlags, ReprOptions};
use rustc_hash::FxHashSet;
use rustc_index::bit_set::DenseBitSet;
use rustc_type_ir::{
- AliasTermKind, AliasTyKind, BoundVar, CoroutineWitnessTypes, DebruijnIndex, EarlyBinder,
- FlagComputation, Flags, GenericArgKind, GenericTypeVisitable, ImplPolarity, InferTy, Interner,
- TraitRef, TypeFlags, TypeVisitableExt, UniverseIndex, Upcast, Variance,
+ AliasTermKind, AliasTy, AliasTyKind, BoundVar, CoroutineWitnessTypes, DebruijnIndex,
+ EarlyBinder, FlagComputation, Flags, GenericArgKind, GenericTypeVisitable, ImplPolarity,
+ InferTy, Interner, TraitRef, TypeFlags, TypeVisitableExt, Upcast, Variance,
elaborate::elaborate,
error::TypeError,
fast_reject,
@@ -43,9 +43,10 @@ use crate::{
method_resolution::TraitImpls,
next_solver::{
AdtIdWrapper, AnyImplId, BoundConst, CallableIdWrapper, CanonicalVarKind, ClosureIdWrapper,
- CoroutineClosureIdWrapper, CoroutineIdWrapper, Ctor, FnSig, FxIndexMap,
- GeneralConstIdWrapper, OpaqueTypeKey, RegionAssumptions, SimplifiedType, SolverContext,
- SolverDefIds, TraitIdWrapper, TypeAliasIdWrapper, UnevaluatedConst,
+ Consts, CoroutineClosureIdWrapper, CoroutineIdWrapper, Ctor, FnSig, FxIndexMap,
+ GeneralConstIdWrapper, LateParamRegion, OpaqueTypeKey, RegionAssumptions, ScalarInt,
+ SimplifiedType, SolverContext, SolverDefIds, TraitIdWrapper, TypeAliasIdWrapper,
+ UnevaluatedConst,
util::{explicit_item_bounds, explicit_item_self_bounds},
},
};
@@ -53,14 +54,11 @@ use crate::{
use super::{
Binder, BoundExistentialPredicates, BoundTy, BoundTyKind, Clause, ClauseKind, Clauses, Const,
ErrorGuaranteed, ExprConst, ExternalConstraints, GenericArg, GenericArgs, ParamConst, ParamEnv,
- ParamTy, PlaceholderConst, PlaceholderTy, PredefinedOpaques, Predicate, SolverDefId, Term, Ty,
- TyKind, Tys, Valtree, ValueConst,
+ ParamTy, PredefinedOpaques, Predicate, SolverDefId, Term, Ty, TyKind, Tys, ValTree, ValueConst,
abi::Safety,
fold::{BoundVarReplacer, BoundVarReplacerDelegate, FnMutDelegate},
generics::{Generics, generics},
- region::{
- BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, PlaceholderRegion, Region,
- },
+ region::{BoundRegion, BoundRegionKind, EarlyParamRegion, Region},
util::sizedness_constraint_for_ty,
};
@@ -373,6 +371,11 @@ impl<'db> DbInterner<'db> {
pub fn default_types<'a>(&self) -> &'a crate::next_solver::DefaultAny<'db> {
crate::next_solver::default_types(self.db)
}
+
+ #[inline]
+ pub(crate) fn expect_crate(&self) -> Crate {
+ self.krate.expect("should have a crate")
+ }
}
// This is intentionally left as `()`
@@ -390,43 +393,15 @@ interned_slice!(
BoundVarKinds,
StoredBoundVarKinds,
bound_var_kinds,
- BoundVarKind,
- BoundVarKind,
+ BoundVariableKind<'db>,
+ BoundVariableKind<'static>,
);
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum BoundVarKind {
- Ty(BoundTyKind),
- Region(BoundRegionKind),
- Const,
-}
-
-impl BoundVarKind {
- pub fn expect_region(self) -> BoundRegionKind {
- match self {
- BoundVarKind::Region(lt) => lt,
- _ => panic!("expected a region, but found another kind"),
- }
- }
-
- pub fn expect_ty(self) -> BoundTyKind {
- match self {
- BoundVarKind::Ty(ty) => ty,
- _ => panic!("expected a type, but found another kind"),
- }
- }
-
- pub fn expect_const(self) {
- match self {
- BoundVarKind::Const => (),
- _ => panic!("expected a const, but found another kind"),
- }
- }
-}
+pub type BoundVariableKind<'db> = rustc_type_ir::BoundVariableKind<DbInterner<'db>>;
interned_slice!(
CanonicalVarsStorage,
- CanonicalVars,
+ CanonicalVarKinds,
StoredCanonicalVars,
canonical_vars,
CanonicalVarKind<'db>,
@@ -438,22 +413,6 @@ pub struct DepNodeIndex;
#[derive(Debug)]
pub struct Tracked<T: fmt::Debug + Clone>(T);
-#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub struct Placeholder<T> {
- pub universe: UniverseIndex,
- pub bound: T,
-}
-
-impl<T: std::fmt::Debug> std::fmt::Debug for Placeholder<T> {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
- if self.universe == UniverseIndex::ROOT {
- write!(f, "!{:?}", self.bound)
- } else {
- write!(f, "!{}_{:?}", self.universe.index(), self.bound)
- }
- }
-}
-
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct AllocId;
@@ -773,6 +732,19 @@ impl<'db> inherent::AdtDef<DbInterner<'db>> for AdtDef {
fn is_manually_drop(self) -> bool {
self.inner().flags.is_manually_drop
}
+
+ fn is_packed(self) -> bool {
+ self.repr().packed()
+ }
+
+ fn field_representing_type_info(
+ self,
+ _interner: DbInterner<'db>,
+ _args: GenericArgs<'db>,
+ ) -> Option<rustc_type_ir::FieldInfo<DbInterner<'db>>> {
+ // FIXME
+ None
+ }
}
impl fmt::Debug for AdtDef {
@@ -806,11 +778,16 @@ impl<'db> inherent::Features<DbInterner<'db>> for Features {
false
}
- fn associated_const_equality(self) -> bool {
+ fn feature_bound_holds_in_crate(self, _symbol: Symbol) -> bool {
false
}
+}
+
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, GenericTypeVisitable)]
+pub struct Symbol;
- fn feature_bound_holds_in_crate(self, _symbol: ()) -> bool {
+impl<'db> inherent::Symbol<DbInterner<'db>> for Symbol {
+ fn is_kw_underscore_lifetime(self) -> bool {
false
}
}
@@ -1036,7 +1013,6 @@ impl<'db> Interner for DbInterner<'db> {
type Term = Term<'db>;
type BoundVarKinds = BoundVarKinds<'db>;
- type BoundVarKind = BoundVarKind;
type PredefinedOpaques = PredefinedOpaques<'db>;
@@ -1047,13 +1023,13 @@ impl<'db> Interner for DbInterner<'db> {
PredefinedOpaques::new_from_slice(data)
}
- type CanonicalVarKinds = CanonicalVars<'db>;
+ type CanonicalVarKinds = CanonicalVarKinds<'db>;
fn mk_canonical_var_kinds(
self,
kinds: &[rustc_type_ir::CanonicalVarKind<Self>],
) -> Self::CanonicalVarKinds {
- CanonicalVars::new_from_slice(kinds)
+ CanonicalVarKinds::new_from_slice(kinds)
}
type ExternalConstraints = ExternalConstraints<'db>;
@@ -1073,9 +1049,7 @@ impl<'db> Interner for DbInterner<'db> {
type Tys = Tys<'db>;
type FnInputTys = &'db [Ty<'db>];
type ParamTy = ParamTy;
- type BoundTy = BoundTy;
- type PlaceholderTy = PlaceholderTy;
- type Symbol = ();
+ type Symbol = Symbol;
type ErrorGuaranteed = ErrorGuaranteed;
type BoundExistentialPredicates = BoundExistentialPredicates<'db>;
@@ -1086,18 +1060,16 @@ impl<'db> Interner for DbInterner<'db> {
type Abi = FnAbi;
type Const = Const<'db>;
- type PlaceholderConst = PlaceholderConst;
type ParamConst = ParamConst;
- type BoundConst = BoundConst;
type ValueConst = ValueConst<'db>;
- type ValTree = Valtree<'db>;
+ type ValTree = ValTree<'db>;
+ type Consts = Consts<'db>;
+ type ScalarInt = ScalarInt;
type ExprConst = ExprConst;
type Region = Region<'db>;
type EarlyParamRegion = EarlyParamRegion;
- type LateParamRegion = LateParamRegion;
- type BoundRegion = BoundRegion;
- type PlaceholderRegion = PlaceholderRegion;
+ type LateParamRegion = LateParamRegion<'db>;
type RegionAssumptions = RegionAssumptions<'db>;
@@ -1231,22 +1203,6 @@ impl<'db> Interner for DbInterner<'db> {
AdtDef::new(def_id.0, self)
}
- fn alias_ty_kind(self, alias: rustc_type_ir::AliasTy<Self>) -> AliasTyKind {
- match alias.def_id {
- SolverDefId::InternedOpaqueTyId(_) => AliasTyKind::Opaque,
- SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container {
- ItemContainerId::ImplId(impl_)
- if ImplSignature::of(self.db, impl_).target_trait.is_none() =>
- {
- AliasTyKind::Inherent
- }
- ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => AliasTyKind::Projection,
- _ => AliasTyKind::Free,
- },
- _ => unimplemented!("Unexpected alias: {:?}", alias.def_id),
- }
- }
-
fn alias_term_kind(
self,
alias: rustc_type_ir::AliasTerm<Self>,
@@ -1346,7 +1302,7 @@ impl<'db> Interner for DbInterner<'db> {
50
}
- fn features(self) -> Self::Features {
+ fn features(self) -> Features {
Features
}
@@ -1476,7 +1432,9 @@ impl<'db> Interner for DbInterner<'db> {
fn is_ty_assoc_of_self(ty: Ty<'_>) -> bool {
// FIXME: Is this correct wrt. combined kind of assoc type bounds, i.e. `where Self::Assoc: Trait<Assoc2: Trait>`
// wrt. `Assoc2`, which we should exclude?
- if let TyKind::Alias(AliasTyKind::Projection, alias) = ty.kind() {
+ if let TyKind::Alias(alias @ AliasTy { kind: AliasTyKind::Projection { .. }, .. }) =
+ ty.kind()
+ {
is_ty_assoc_of_self(alias.self_ty())
} else {
is_ty_self(ty)
@@ -1540,6 +1498,8 @@ impl<'db> Interner for DbInterner<'db> {
SolverLangItem::DynMetadata => {
return lang_items.DynMetadata.expect("Lang item required but not found.").into();
}
+ SolverLangItem::FieldBase => unimplemented!(),
+ SolverLangItem::FieldType => unimplemented!(),
};
lang_item.expect("Lang item required but not found.").into()
}
@@ -1580,6 +1540,7 @@ impl<'db> Interner for DbInterner<'db> {
unimplemented!()
}
SolverTraitLangItem::TrivialClone => lang_items.TrivialClone,
+ SolverTraitLangItem::Field => unimplemented!(),
};
lang_item.expect("Lang item required but not found.").into()
}
@@ -1607,6 +1568,7 @@ impl<'db> Interner for DbInterner<'db> {
AsyncIterator,
BikeshedGuaranteedNoDrop,
FusedIterator,
+ Field,
AsyncFnOnceOutput, // This is incorrectly marked as `SolverTraitLangItem`, and is not used by the solver.
}
@@ -1652,6 +1614,8 @@ impl<'db> Interner for DbInterner<'db> {
ignore = {
AsyncFnKindUpvars,
DynMetadata,
+ FieldBase,
+ FieldType,
}
Metadata,
@@ -1676,6 +1640,8 @@ impl<'db> Interner for DbInterner<'db> {
CallRefFuture,
CallOnceFuture,
AsyncFnOnceOutput,
+ FieldBase,
+ FieldType,
}
DynMetadata,
@@ -1694,6 +1660,7 @@ impl<'db> Interner for DbInterner<'db> {
AsyncIterator,
BikeshedGuaranteedNoDrop,
FusedIterator,
+ Field,
AsyncFnOnceOutput, // This is incorrectly marked as `SolverTraitLangItem`, and is not used by the solver.
}
@@ -1871,7 +1838,7 @@ impl<'db> Interner for DbInterner<'db> {
//
// Impls which apply to an alias after normalization are handled by
// `assemble_candidates_after_normalizing_self_ty`.
- TyKind::Alias(_, _) | TyKind::Placeholder(..) | TyKind::Error(_) => (),
+ TyKind::Alias(..) | TyKind::Placeholder(..) | TyKind::Error(_) => (),
// FIXME: These should ideally not exist as a self type. It would be nice for
// the builtin auto trait impls of coroutines to instead directly recurse
@@ -1964,12 +1931,6 @@ impl<'db> Interner for DbInterner<'db> {
trait_data.flags.contains(TraitFlags::FUNDAMENTAL)
}
- fn trait_may_be_implemented_via_object(self, _trait_def_id: Self::TraitId) -> bool {
- // FIXME(next-solver): should check the `TraitFlags` for
- // the `#[rustc_do_not_implement_via_object]` flag
- true
- }
-
fn is_impl_trait_in_trait(self, _def_id: Self::DefId) -> bool {
// FIXME(next-solver)
false
@@ -2068,32 +2029,33 @@ impl<'db> Interner for DbInterner<'db> {
) -> rustc_type_ir::Binder<Self, T> {
struct Anonymize<'a, 'db> {
interner: DbInterner<'db>,
- map: &'a mut FxIndexMap<BoundVar, BoundVarKind>,
+ map: &'a mut FxIndexMap<BoundVar, BoundVariableKind<'db>>,
}
impl<'db> BoundVarReplacerDelegate<'db> for Anonymize<'_, 'db> {
- fn replace_region(&mut self, br: BoundRegion) -> Region<'db> {
+ fn replace_region(&mut self, br: BoundRegion<'db>) -> Region<'db> {
let entry = self.map.entry(br.var);
let index = entry.index();
let var = BoundVar::from_usize(index);
- let kind = (*entry.or_insert_with(|| BoundVarKind::Region(BoundRegionKind::Anon)))
- .expect_region();
+ let kind = (*entry
+ .or_insert_with(|| BoundVariableKind::Region(BoundRegionKind::Anon)))
+ .expect_region();
let br = BoundRegion { var, kind };
Region::new_bound(self.interner, DebruijnIndex::ZERO, br)
}
- fn replace_ty(&mut self, bt: BoundTy) -> Ty<'db> {
+ fn replace_ty(&mut self, bt: BoundTy<'db>) -> Ty<'db> {
let entry = self.map.entry(bt.var);
let index = entry.index();
let var = BoundVar::from_usize(index);
- let kind =
- (*entry.or_insert_with(|| BoundVarKind::Ty(BoundTyKind::Anon))).expect_ty();
+ let kind = (*entry.or_insert_with(|| BoundVariableKind::Ty(BoundTyKind::Anon)))
+ .expect_ty();
Ty::new_bound(self.interner, DebruijnIndex::ZERO, BoundTy { var, kind })
}
- fn replace_const(&mut self, bv: BoundConst) -> Const<'db> {
+ fn replace_const(&mut self, bv: BoundConst<'db>) -> Const<'db> {
let entry = self.map.entry(bv.var);
let index = entry.index();
let var = BoundVar::from_usize(index);
- let () = (*entry.or_insert_with(|| BoundVarKind::Const)).expect_const();
- Const::new_bound(self.interner, DebruijnIndex::ZERO, BoundConst { var })
+ let () = (*entry.or_insert_with(|| BoundVariableKind::Const)).expect_const();
+ Const::new_bound(self.interner, DebruijnIndex::ZERO, BoundConst::new(var))
}
}
@@ -2273,6 +2235,34 @@ impl<'db> Interner for DbInterner<'db> {
UnevaluatedConst { def: GeneralConstIdWrapper(id), args: GenericArgs::empty(self) },
))
}
+
+ fn anon_const_kind(self, _def_id: Self::DefId) -> rustc_type_ir::AnonConstKind {
+ // FIXME
+ rustc_type_ir::AnonConstKind::GCE
+ }
+
+ fn alias_ty_kind_from_def_id(self, def_id: Self::DefId) -> AliasTyKind<DbInterner<'db>> {
+ match def_id {
+ SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container {
+ ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
+ AliasTyKind::Free { def_id }
+ }
+ ItemContainerId::ImplId(_) => AliasTyKind::Inherent { def_id },
+ ItemContainerId::TraitId(_) => AliasTyKind::Projection { def_id },
+ },
+ SolverDefId::InternedOpaqueTyId(_) => AliasTyKind::Opaque { def_id },
+ _ => unreachable!(),
+ }
+ }
+
+ fn closure_is_const(self, _def_id: Self::ClosureId) -> bool {
+ // FIXME
+ false
+ }
+
+ fn item_name(self, _item_index: Self::DefId) -> Self::Symbol {
+ Symbol
+ }
}
fn is_ty_self(ty: Ty<'_>) -> bool {
@@ -2302,14 +2292,14 @@ impl<'db> DbInterner<'db> {
self.replace_escaping_bound_vars_uncached(
value,
FnMutDelegate {
- regions: &mut |r: BoundRegion| {
+ regions: &mut |r: BoundRegion<'db>| {
Region::new_bound(
self,
DebruijnIndex::ZERO,
BoundRegion { var: shift_bv(r.var), kind: r.kind },
)
},
- types: &mut |t: BoundTy| {
+ types: &mut |t: BoundTy<'db>| {
Ty::new_bound(
self,
DebruijnIndex::ZERO,
@@ -2317,7 +2307,7 @@ impl<'db> DbInterner<'db> {
)
},
consts: &mut |c| {
- Const::new_bound(self, DebruijnIndex::ZERO, BoundConst { var: shift_bv(c.var) })
+ Const::new_bound(self, DebruijnIndex::ZERO, BoundConst::new(shift_bv(c.var)))
},
},
)
@@ -2430,17 +2420,9 @@ TrivialTypeTraversalImpls! {
Span,
ParamConst,
ParamTy,
- BoundRegion,
- Placeholder<BoundRegion>,
- Placeholder<BoundTy>,
- Placeholder<BoundVar>,
- Placeholder<BoundConst>,
- BoundVarKind,
EarlyParamRegion,
- LateParamRegion,
AdtDef,
- BoundTy,
- BoundConst,
+ ScalarInt,
}
mod tls_db {
@@ -2633,13 +2615,15 @@ pub unsafe fn collect_ty_garbage() {
let mut gc = intern::GarbageCollector::default();
gc.add_storage::<super::consts::ConstInterned>();
- gc.add_storage::<super::consts::ValtreeInterned>();
+ gc.add_storage::<super::consts::ValTreeInterned>();
+ gc.add_storage::<super::allocation::AllocationInterned>();
gc.add_storage::<PatternInterned>();
gc.add_storage::<super::opaques::ExternalConstraintsInterned>();
gc.add_storage::<super::predicate::PredicateInterned>();
gc.add_storage::<super::region::RegionInterned>();
gc.add_storage::<super::ty::TyInterned>();
+ gc.add_slice_storage::<super::consts::ConstsStorage>();
gc.add_slice_storage::<super::predicate::ClausesStorage>();
gc.add_slice_storage::<super::generic_arg::GenericArgsStorage>();
gc.add_slice_storage::<BoundVarKindsStorage>();
@@ -2674,7 +2658,8 @@ macro_rules! impl_gc_visit {
impl_gc_visit!(
super::consts::ConstInterned,
- super::consts::ValtreeInterned,
+ super::consts::ValTreeInterned,
+ super::allocation::AllocationInterned,
PatternInterned,
super::opaques::ExternalConstraintsInterned,
super::predicate::PredicateInterned,
@@ -2713,4 +2698,5 @@ impl_gc_visit_slice!(
super::predicate::BoundExistentialPredicatesStorage,
super::region::RegionAssumptionsStorage,
super::ty::TysStorage,
+ super::consts::ConstsStorage,
);
diff --git a/crates/hir-ty/src/next_solver/ir_print.rs b/crates/hir-ty/src/next_solver/ir_print.rs
index e0732b3473..5dd372a367 100644
--- a/crates/hir-ty/src/next_solver/ir_print.rs
+++ b/crates/hir-ty/src/next_solver/ir_print.rs
@@ -12,7 +12,7 @@ impl<'db> IrPrint<ty::AliasTy<Self>> for DbInterner<'db> {
}
fn print_debug(t: &ty::AliasTy<Self>, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- crate::with_attached_db(|db| match t.def_id {
+ crate::with_attached_db(|db| match t.kind.def_id() {
SolverDefId::TypeAliasId(id) => fmt.write_str(&format!(
"AliasTy({:?}[{:?}])",
TypeAliasSignature::of(db, id).name.as_str(),
diff --git a/crates/hir-ty/src/next_solver/normalize.rs b/crates/hir-ty/src/next_solver/normalize.rs
index bd678b3e78..5d8f3fe519 100644
--- a/crates/hir-ty/src/next_solver/normalize.rs
+++ b/crates/hir-ty/src/next_solver/normalize.rs
@@ -229,6 +229,7 @@ impl<'db> FallibleTypeFolder<DbInterner<'db>> for NormalizationFolder<'_, 'db> {
}
// Deeply normalize a value and return it
+#[expect(dead_code, reason = "rustc has this")]
pub(crate) fn deeply_normalize_for_diagnostics<'db, T: TypeFoldable<DbInterner<'db>>>(
infcx: &InferCtxt<'db>,
param_env: ParamEnv<'db>,
diff --git a/crates/hir-ty/src/next_solver/region.rs b/crates/hir-ty/src/next_solver/region.rs
index dc2441f76e..3f0aebac2d 100644
--- a/crates/hir-ty/src/next_solver/region.rs
+++ b/crates/hir-ty/src/next_solver/region.rs
@@ -1,12 +1,12 @@
//! Things related to regions.
use hir_def::LifetimeParamId;
-use intern::{Interned, InternedRef, Symbol, impl_internable};
+use intern::{Interned, InternedRef, impl_internable};
use macros::GenericTypeVisitable;
use rustc_type_ir::{
- BoundVar, BoundVarIndexKind, DebruijnIndex, Flags, GenericTypeVisitable, INNERMOST, RegionVid,
- TypeFlags, TypeFoldable, TypeVisitable,
- inherent::{IntoKind, PlaceholderLike, SliceLike},
+ BoundVarIndexKind, DebruijnIndex, Flags, GenericTypeVisitable, INNERMOST, RegionVid, TypeFlags,
+ TypeFoldable, TypeVisitable,
+ inherent::{IntoKind, SliceLike},
relate::Relate,
};
@@ -15,10 +15,7 @@ use crate::next_solver::{
interned_slice,
};
-use super::{
- SolverDefId,
- interner::{BoundVarKind, DbInterner, Placeholder},
-};
+use super::{SolverDefId, interner::DbInterner};
pub type RegionKind<'db> = rustc_type_ir::RegionKind<DbInterner<'db>>;
@@ -57,7 +54,7 @@ impl<'db> Region<'db> {
Region::new(interner, RegionKind::ReEarlyParam(early_bound_region))
}
- pub fn new_placeholder(interner: DbInterner<'db>, placeholder: PlaceholderRegion) -> Self {
+ pub fn new_placeholder(interner: DbInterner<'db>, placeholder: PlaceholderRegion<'db>) -> Self {
Region::new(interner, RegionKind::RePlaceholder(placeholder))
}
@@ -72,7 +69,7 @@ impl<'db> Region<'db> {
pub fn new_bound(
interner: DbInterner<'db>,
index: DebruijnIndex,
- bound: BoundRegion,
+ bound: BoundRegion<'db>,
) -> Region<'db> {
Region::new(interner, RegionKind::ReBound(BoundVarIndexKind::Bound(index), bound))
}
@@ -147,7 +144,7 @@ impl<'db> Region<'db> {
}
}
-pub type PlaceholderRegion = Placeholder<BoundRegion>;
+pub type PlaceholderRegion<'db> = rustc_type_ir::PlaceholderRegion<DbInterner<'db>>;
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct EarlyParamRegion {
@@ -156,7 +153,7 @@ pub struct EarlyParamRegion {
pub index: u32,
}
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, GenericTypeVisitable)]
/// The parameter representation of late-bound function parameters, "some region
/// at least as big as the scope `fr.scope`".
///
@@ -165,50 +162,19 @@ pub struct EarlyParamRegion {
/// between others we use the `DefId` of the parameter. For this reason the `bound_region` field
/// should basically always be `BoundRegionKind::Named` as otherwise there is no way of telling
/// different parameters apart.
-pub struct LateParamRegion {
+pub struct LateParamRegion<'db> {
pub scope: SolverDefId,
- pub bound_region: BoundRegionKind,
+ pub bound_region: BoundRegionKind<'db>,
}
-impl std::fmt::Debug for LateParamRegion {
+impl std::fmt::Debug for LateParamRegion<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "ReLateParam({:?}, {:?})", self.scope, self.bound_region)
}
}
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub enum BoundRegionKind {
- /// An anonymous region parameter for a given fn (&T)
- Anon,
-
- /// Named region parameters for functions (a in &'a T)
- ///
- /// The `DefId` is needed to distinguish free regions in
- /// the event of shadowing.
- Named(SolverDefId),
-
- /// Anonymous region for the implicit env pointer parameter
- /// to a closure
- ClosureEnv,
-}
-
-impl std::fmt::Debug for BoundRegionKind {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match *self {
- BoundRegionKind::Anon => write!(f, "BrAnon"),
- BoundRegionKind::Named(did) => {
- write!(f, "BrNamed({did:?})")
- }
- BoundRegionKind::ClosureEnv => write!(f, "BrEnv"),
- }
- }
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub struct BoundRegion {
- pub var: BoundVar,
- pub kind: BoundRegionKind,
-}
+pub type BoundRegion<'db> = rustc_type_ir::BoundRegion<DbInterner<'db>>;
+pub type BoundRegionKind<'db> = rustc_type_ir::BoundRegionKind<DbInterner<'db>>;
impl rustc_type_ir::inherent::ParamLike for EarlyParamRegion {
fn index(self) -> u32 {
@@ -223,45 +189,6 @@ impl std::fmt::Debug for EarlyParamRegion {
}
}
-impl<'db> rustc_type_ir::inherent::BoundVarLike<DbInterner<'db>> for BoundRegion {
- fn var(self) -> BoundVar {
- self.var
- }
-
- fn assert_eq(self, var: BoundVarKind) {
- assert_eq!(self.kind, var.expect_region())
- }
-}
-
-impl core::fmt::Debug for BoundRegion {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match &self.kind {
- BoundRegionKind::Anon => write!(f, "{:?}", self.var),
- BoundRegionKind::ClosureEnv => write!(f, "{:?}.Env", self.var),
- BoundRegionKind::Named(def) => {
- write!(f, "{:?}.Named({:?})", self.var, def)
- }
- }
- }
-}
-
-impl BoundRegionKind {
- pub fn is_named(&self) -> bool {
- matches!(self, BoundRegionKind::Named(_))
- }
-
- pub fn get_name(&self) -> Option<Symbol> {
- None
- }
-
- pub fn get_id(&self) -> Option<SolverDefId> {
- match self {
- BoundRegionKind::Named(id) => Some(*id),
- _ => None,
- }
- }
-}
-
impl std::fmt::Debug for Region<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.kind().fmt(f)
@@ -323,15 +250,15 @@ impl<'db> Flags for Region<'db> {
impl<'db> rustc_type_ir::inherent::Region<DbInterner<'db>> for Region<'db> {
fn new_bound(
interner: DbInterner<'db>,
- debruijn: rustc_type_ir::DebruijnIndex,
- var: BoundRegion,
+ debruijn: DebruijnIndex,
+ var: BoundRegion<'db>,
) -> Self {
Region::new(interner, RegionKind::ReBound(BoundVarIndexKind::Bound(debruijn), var))
}
fn new_anon_bound(
interner: DbInterner<'db>,
- debruijn: rustc_type_ir::DebruijnIndex,
+ debruijn: DebruijnIndex,
var: rustc_type_ir::BoundVar,
) -> Self {
Region::new(
@@ -357,38 +284,11 @@ impl<'db> rustc_type_ir::inherent::Region<DbInterner<'db>> for Region<'db> {
interner.default_types().regions.statik
}
- fn new_placeholder(
- interner: DbInterner<'db>,
- var: <DbInterner<'db> as rustc_type_ir::Interner>::PlaceholderRegion,
- ) -> Self {
+ fn new_placeholder(interner: DbInterner<'db>, var: PlaceholderRegion<'db>) -> Self {
Region::new(interner, RegionKind::RePlaceholder(var))
}
}
-impl<'db> PlaceholderLike<DbInterner<'db>> for PlaceholderRegion {
- type Bound = BoundRegion;
-
- fn universe(self) -> rustc_type_ir::UniverseIndex {
- self.universe
- }
-
- fn var(self) -> rustc_type_ir::BoundVar {
- self.bound.var
- }
-
- fn with_updated_universe(self, ui: rustc_type_ir::UniverseIndex) -> Self {
- Placeholder { universe: ui, bound: self.bound }
- }
-
- fn new(ui: rustc_type_ir::UniverseIndex, bound: Self::Bound) -> Self {
- Placeholder { universe: ui, bound }
- }
-
- fn new_anon(ui: rustc_type_ir::UniverseIndex, var: rustc_type_ir::BoundVar) -> Self {
- Placeholder { universe: ui, bound: BoundRegion { var, kind: BoundRegionKind::Anon } }
- }
-}
-
impl<'db, V: super::WorldExposer> GenericTypeVisitable<V> for Region<'db> {
fn generic_visit_with(&self, visitor: &mut V) {
if visitor.on_interned(self.interned).is_continue() {
diff --git a/crates/hir-ty/src/next_solver/solver.rs b/crates/hir-ty/src/next_solver/solver.rs
index 848bb110af..d45ac6c959 100644
--- a/crates/hir-ty/src/next_solver/solver.rs
+++ b/crates/hir-ty/src/next_solver/solver.rs
@@ -14,10 +14,13 @@ use rustc_type_ir::{
};
use tracing::debug;
-use crate::next_solver::{
- AliasTy, AnyImplId, CanonicalVarKind, Clause, ClauseKind, CoercePredicate, GenericArgs,
- ParamEnv, Predicate, PredicateKind, SubtypePredicate, Ty, TyKind, fold::fold_tys,
- util::sizedness_fast_path,
+use crate::{
+ ParamEnvAndCrate,
+ next_solver::{
+ AliasTy, AnyImplId, CanonicalVarKind, Clause, ClauseKind, CoercePredicate, GenericArgs,
+ ParamEnv, Predicate, PredicateKind, SubtypePredicate, Ty, TyKind, UnevaluatedConst,
+ fold::fold_tys, util::sizedness_fast_path,
+ },
};
use super::{
@@ -155,10 +158,11 @@ impl<'db> SolverDelegate for SolverContext<'db> {
fold_tys(interner, clause, |ty| match ty.kind() {
// Replace all other mentions of the same opaque type with the hidden type,
// as the bounds must hold on the hidden type after all.
- TyKind::Alias(
- AliasTyKind::Opaque,
- AliasTy { def_id: def_id2, args: args2, .. },
- ) if def_id == def_id2 && args == args2 => hidden_ty,
+ TyKind::Alias(AliasTy {
+ kind: AliasTyKind::Opaque { def_id: def_id2 },
+ args: args2,
+ ..
+ }) if def_id == def_id2 && args == args2 => hidden_ty,
_ => ty,
})
};
@@ -247,25 +251,26 @@ impl<'db> SolverDelegate for SolverContext<'db> {
fn evaluate_const(
&self,
- _param_env: ParamEnv<'db>,
- uv: rustc_type_ir::UnevaluatedConst<Self::Interner>,
- ) -> Option<<Self::Interner as rustc_type_ir::Interner>::Const> {
- match uv.def.0 {
+ param_env: ParamEnv<'db>,
+ uv: UnevaluatedConst<'db>,
+ ) -> Option<Const<'db>> {
+ let ec = match uv.def.0 {
GeneralConstId::ConstId(c) => {
let subst = uv.args;
- let ec = self.cx().db.const_eval(c, subst, None).ok()?;
- Some(ec)
- }
- GeneralConstId::StaticId(c) => {
- let ec = self.cx().db.const_eval_static(c).ok()?;
- Some(ec)
+ self.cx().db.const_eval(c, subst, None).ok()?
}
+ GeneralConstId::StaticId(c) => self.cx().db.const_eval_static(c).ok()?,
// TODO: Wire up const_eval_anon query in Phase 5.
// For now, return an error const so normalization resolves the
// unevaluated const to Error (matching the old behavior where
// complex expressions produced ConstKind::Error directly).
- GeneralConstId::AnonConstId(_) => Some(Const::error(self.cx())),
- }
+ GeneralConstId::AnonConstId(_) => return Some(Const::error(self.cx())),
+ };
+ Some(Const::new_from_allocation(
+ self.interner,
+ &ec,
+ ParamEnvAndCrate { param_env, krate: self.interner.expect_crate() },
+ ))
}
fn compute_goal_fast_path(
diff --git a/crates/hir-ty/src/next_solver/ty.rs b/crates/hir-ty/src/next_solver/ty.rs
index dccb8c7936..3811bddb38 100644
--- a/crates/hir-ty/src/next_solver/ty.rs
+++ b/crates/hir-ty/src/next_solver/ty.rs
@@ -17,8 +17,8 @@ use rustc_type_ir::{
IntVid, Interner, TyVid, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
TypeVisitableExt, TypeVisitor, UintTy, Upcast, WithCachedTypeInfo,
inherent::{
- AdtDef as _, BoundExistentialPredicates, BoundVarLike, Const as _, GenericArgs as _,
- IntoKind, ParamLike, PlaceholderLike, Safety as _, SliceLike, Ty as _,
+ AdtDef as _, BoundExistentialPredicates, Const as _, GenericArgs as _, IntoKind, ParamLike,
+ Safety as _, SliceLike, Ty as _,
},
relate::Relate,
solve::SizedTraitKind,
@@ -40,7 +40,7 @@ use crate::{
};
use super::{
- BoundVarKind, DbInterner, GenericArgs, Placeholder, SolverDefId,
+ DbInterner, GenericArgs, SolverDefId,
util::{FloatExt, IntegerExt},
};
@@ -97,7 +97,7 @@ impl<'db> Ty<'db> {
Ty::new(interner, TyKind::Param(ParamTy { id, index }))
}
- pub fn new_placeholder(interner: DbInterner<'db>, placeholder: PlaceholderTy) -> Self {
+ pub fn new_placeholder(interner: DbInterner<'db>, placeholder: PlaceholderType<'db>) -> Self {
Ty::new(interner, TyKind::Placeholder(placeholder))
}
@@ -177,7 +177,10 @@ impl<'db> Ty<'db> {
def_id: SolverDefId,
args: GenericArgs<'db>,
) -> Self {
- Ty::new_alias(interner, AliasTyKind::Opaque, AliasTy::new_from_args(interner, def_id, args))
+ Ty::new_alias(
+ interner,
+ AliasTy::new_from_args(interner, AliasTyKind::Opaque { def_id }, args),
+ )
}
/// Returns the `Size` for primitive types (bool, uint, int, char, float).
@@ -681,12 +684,11 @@ impl<'db> Ty<'db> {
let interner = DbInterner::new_no_crate(db);
match self.kind() {
- TyKind::Alias(AliasTyKind::Opaque, opaque_ty) => Some(
- opaque_ty
- .def_id
+ TyKind::Alias(AliasTy { kind: AliasTyKind::Opaque { def_id }, args, .. }) => Some(
+ def_id
.expect_opaque_ty()
.predicates(db)
- .iter_instantiated_copied(interner, opaque_ty.args.as_slice())
+ .iter_instantiated_copied(interner, args.as_slice())
.collect(),
),
TyKind::Param(param) => {
@@ -743,9 +745,7 @@ impl<'db> Ty<'db> {
true
}
(TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2,
- (TyKind::Alias(_, alias, ..), TyKind::Alias(_, alias2)) => {
- alias.def_id == alias2.def_id
- }
+ (TyKind::Alias(alias), TyKind::Alias(alias2)) => alias.kind == alias2.kind,
(TyKind::Foreign(ty_id, ..), TyKind::Foreign(ty_id2, ..)) => ty_id == ty_id2,
(TyKind::Closure(id1, _), TyKind::Closure(id2, _)) => id1 == id2,
(TyKind::Ref(.., mutability), TyKind::Ref(.., mutability2))
@@ -858,7 +858,7 @@ impl<'db> TypeSuperVisitable<DbInterner<'db>> for Ty<'db> {
TyKind::CoroutineWitness(_did, ref args) => args.visit_with(visitor),
TyKind::Closure(_did, ref args) => args.visit_with(visitor),
TyKind::CoroutineClosure(_did, ref args) => args.visit_with(visitor),
- TyKind::Alias(_, ref data) => data.visit_with(visitor),
+ TyKind::Alias(ref data) => data.visit_with(visitor),
TyKind::Pat(ty, pat) => {
try_visit!(ty.visit_with(visitor));
@@ -925,7 +925,7 @@ impl<'db> TypeSuperFoldable<DbInterner<'db>> for Ty<'db> {
TyKind::CoroutineClosure(did, args) => {
TyKind::CoroutineClosure(did, args.try_fold_with(folder)?)
}
- TyKind::Alias(kind, data) => TyKind::Alias(kind, data.try_fold_with(folder)?),
+ TyKind::Alias(data) => TyKind::Alias(data.try_fold_with(folder)?),
TyKind::Pat(ty, pat) => {
TyKind::Pat(ty.try_fold_with(folder)?, pat.try_fold_with(folder)?)
}
@@ -974,7 +974,7 @@ impl<'db> TypeSuperFoldable<DbInterner<'db>> for Ty<'db> {
TyKind::CoroutineClosure(did, args) => {
TyKind::CoroutineClosure(did, args.fold_with(folder))
}
- TyKind::Alias(kind, data) => TyKind::Alias(kind, data.fold_with(folder)),
+ TyKind::Alias(data) => TyKind::Alias(data.fold_with(folder)),
TyKind::Pat(ty, pat) => TyKind::Pat(ty.fold_with(folder), pat.fold_with(folder)),
TyKind::Bool
@@ -1045,11 +1045,11 @@ impl<'db> rustc_type_ir::inherent::Ty<DbInterner<'db>> for Ty<'db> {
Ty::new(interner, TyKind::Param(param))
}
- fn new_placeholder(interner: DbInterner<'db>, param: PlaceholderTy) -> Self {
+ fn new_placeholder(interner: DbInterner<'db>, param: PlaceholderType<'db>) -> Self {
Ty::new(interner, TyKind::Placeholder(param))
}
- fn new_bound(interner: DbInterner<'db>, debruijn: DebruijnIndex, var: BoundTy) -> Self {
+ fn new_bound(interner: DbInterner<'db>, debruijn: DebruijnIndex, var: BoundTy<'db>) -> Self {
Ty::new(interner, TyKind::Bound(BoundVarIndexKind::Bound(debruijn), var))
}
@@ -1070,8 +1070,8 @@ impl<'db> rustc_type_ir::inherent::Ty<DbInterner<'db>> for Ty<'db> {
)
}
- fn new_alias(interner: DbInterner<'db>, kind: AliasTyKind, alias_ty: AliasTy<'db>) -> Self {
- Ty::new(interner, TyKind::Alias(kind, alias_ty))
+ fn new_alias(interner: DbInterner<'db>, alias_ty: AliasTy<'db>) -> Self {
+ Ty::new(interner, TyKind::Alias(alias_ty))
}
fn new_error(interner: DbInterner<'db>, guar: ErrorGuaranteed) -> Self {
@@ -1352,7 +1352,7 @@ impl<'db> rustc_type_ir::inherent::Tys<DbInterner<'db>> for Tys<'db> {
}
}
-pub type PlaceholderTy = Placeholder<BoundTy>;
+pub type PlaceholderType<'db> = rustc_type_ir::PlaceholderType<DbInterner<'db>>;
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct ParamTy {
@@ -1375,27 +1375,8 @@ impl std::fmt::Debug for ParamTy {
}
}
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub struct BoundTy {
- pub var: BoundVar,
- // FIXME: This is for diagnostics in rustc, do we really need it?
- pub kind: BoundTyKind,
-}
-
-impl std::fmt::Debug for BoundTy {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self.kind {
- BoundTyKind::Anon => write!(f, "{:?}", self.var),
- BoundTyKind::Param(def_id) => write!(f, "{def_id:?}"),
- }
- }
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub enum BoundTyKind {
- Anon,
- Param(SolverDefId),
-}
+pub type BoundTy<'db> = rustc_type_ir::BoundTy<DbInterner<'db>>;
+pub type BoundTyKind<'db> = rustc_type_ir::BoundTyKind<DbInterner<'db>>;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct ErrorGuaranteed;
@@ -1431,40 +1412,6 @@ impl ParamLike for ParamTy {
}
}
-impl<'db> BoundVarLike<DbInterner<'db>> for BoundTy {
- fn var(self) -> BoundVar {
- self.var
- }
-
- fn assert_eq(self, var: BoundVarKind) {
- assert_eq!(self.kind, var.expect_ty())
- }
-}
-
-impl<'db> PlaceholderLike<DbInterner<'db>> for PlaceholderTy {
- type Bound = BoundTy;
-
- fn universe(self) -> rustc_type_ir::UniverseIndex {
- self.universe
- }
-
- fn var(self) -> BoundVar {
- self.bound.var
- }
-
- fn with_updated_universe(self, ui: rustc_type_ir::UniverseIndex) -> Self {
- Placeholder { universe: ui, bound: self.bound }
- }
-
- fn new(ui: rustc_type_ir::UniverseIndex, bound: BoundTy) -> Self {
- Placeholder { universe: ui, bound }
- }
-
- fn new_anon(ui: rustc_type_ir::UniverseIndex, var: rustc_type_ir::BoundVar) -> Self {
- Placeholder { universe: ui, bound: BoundTy { var, kind: BoundTyKind::Anon } }
- }
-}
-
impl<'db> DbInterner<'db> {
/// Given a closure signature, returns an equivalent fn signature. Detuples
/// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then
diff --git a/crates/hir-ty/src/next_solver/util.rs b/crates/hir-ty/src/next_solver/util.rs
index c175062bda..858233cb2c 100644
--- a/crates/hir-ty/src/next_solver/util.rs
+++ b/crates/hir-ty/src/next_solver/util.rs
@@ -15,7 +15,7 @@ use rustc_type_ir::{
use crate::{
next_solver::{
- BoundConst, FxIndexMap, ParamEnv, Placeholder, PlaceholderConst, PlaceholderRegion,
+ BoundConst, FxIndexMap, ParamEnv, PlaceholderConst, PlaceholderRegion, PlaceholderType,
PolyTraitRef,
infer::{
InferCtxt,
@@ -446,9 +446,10 @@ pub fn apply_args_to_binder<'db, T: TypeFoldable<DbInterner<'db>>>(
args: GenericArgs<'db>,
interner: DbInterner<'db>,
) -> T {
- let types = &mut |ty: BoundTy| args.as_slice()[ty.var.index()].expect_ty();
- let regions = &mut |region: BoundRegion| args.as_slice()[region.var.index()].expect_region();
- let consts = &mut |const_: BoundConst| args.as_slice()[const_.var.index()].expect_const();
+ let types = &mut |ty: BoundTy<'db>| args.as_slice()[ty.var.index()].expect_ty();
+ let regions =
+ &mut |region: BoundRegion<'db>| args.as_slice()[region.var.index()].expect_region();
+ let consts = &mut |const_: BoundConst<'db>| args.as_slice()[const_.var.index()].expect_const();
let mut instantiate = BoundVarReplacer::new(interner, FnMutDelegate { types, regions, consts });
b.skip_binder().fold_with(&mut instantiate)
}
@@ -497,9 +498,9 @@ impl<'db> TypeVisitor<DbInterner<'db>> for ContainsTypeErrors {
/// The inverse of [`BoundVarReplacer`]: replaces placeholders with the bound vars from which they came.
pub struct PlaceholderReplacer<'a, 'db> {
infcx: &'a InferCtxt<'db>,
- mapped_regions: FxIndexMap<PlaceholderRegion, BoundRegion>,
- mapped_types: FxIndexMap<Placeholder<BoundTy>, BoundTy>,
- mapped_consts: FxIndexMap<PlaceholderConst, BoundConst>,
+ mapped_regions: FxIndexMap<PlaceholderRegion<'db>, BoundRegion<'db>>,
+ mapped_types: FxIndexMap<PlaceholderType<'db>, BoundTy<'db>>,
+ mapped_consts: FxIndexMap<PlaceholderConst<'db>, BoundConst<'db>>,
universe_indices: &'a [Option<UniverseIndex>],
current_index: DebruijnIndex,
}
@@ -507,9 +508,9 @@ pub struct PlaceholderReplacer<'a, 'db> {
impl<'a, 'db> PlaceholderReplacer<'a, 'db> {
pub fn replace_placeholders<T: TypeFoldable<DbInterner<'db>>>(
infcx: &'a InferCtxt<'db>,
- mapped_regions: FxIndexMap<PlaceholderRegion, BoundRegion>,
- mapped_types: FxIndexMap<Placeholder<BoundTy>, BoundTy>,
- mapped_consts: FxIndexMap<PlaceholderConst, BoundConst>,
+ mapped_regions: FxIndexMap<PlaceholderRegion<'db>, BoundRegion<'db>>,
+ mapped_types: FxIndexMap<PlaceholderType<'db>, BoundTy<'db>>,
+ mapped_consts: FxIndexMap<PlaceholderConst<'db>, BoundConst<'db>>,
universe_indices: &'a [Option<UniverseIndex>],
value: T,
) -> T {
diff --git a/crates/hir-ty/src/variance.rs b/crates/hir-ty/src/variance.rs
index 1945b04bb3..a88457e3c7 100644
--- a/crates/hir-ty/src/variance.rs
+++ b/crates/hir-ty/src/variance.rs
@@ -216,7 +216,7 @@ impl<'db> Context<'db> {
TyKind::Adt(def, args) => {
self.add_constraints_from_args(def.def_id().0.into(), args, variance);
}
- TyKind::Alias(_, alias) => {
+ TyKind::Alias(alias) => {
// FIXME: Probably not correct wrt. opaques.
self.add_constraints_from_invariant_args(alias.args);
}
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index c9af4aa263..27516ed80b 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -3128,7 +3128,7 @@ impl Const {
let interner = DbInterner::new_no_crate(db);
let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity();
db.const_eval(self.id, GenericArgs::empty(interner), None).map(|it| EvaluatedConst {
- const_: it,
+ allocation: it,
def: self.id.into(),
ty,
})
@@ -3143,22 +3143,19 @@ impl HasVisibility for Const {
pub struct EvaluatedConst<'db> {
def: DefWithBodyId,
- const_: hir_ty::next_solver::Const<'db>,
+ allocation: hir_ty::next_solver::Allocation<'db>,
ty: Ty<'db>,
}
impl<'db> EvaluatedConst<'db> {
pub fn render(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
- format!("{}", self.const_.display(db, display_target))
+ format!("{}", self.allocation.display(db, display_target))
}
pub fn render_debug(&self, db: &'db dyn HirDatabase) -> Result<String, MirEvalError> {
- let kind = self.const_.kind();
- if let ConstKind::Value(c) = kind
- && let ty = c.ty.kind()
- && let TyKind::Int(_) | TyKind::Uint(_) = ty
- {
- let b = &c.value.inner().memory;
+ let ty = self.allocation.ty.kind();
+ if let TyKind::Int(_) | TyKind::Uint(_) = ty {
+ let b = &self.allocation.memory;
let value = u128::from_le_bytes(mir::pad16(b, false));
let value_signed = i128::from_le_bytes(mir::pad16(b, matches!(ty, TyKind::Int(_))));
let mut result =
@@ -3170,7 +3167,7 @@ impl<'db> EvaluatedConst<'db> {
return Ok(result);
}
}
- mir::render_const_using_debug_impl(db, self.def, self.const_, self.ty)
+ mir::render_const_using_debug_impl(db, self.def, self.allocation, self.ty)
}
}
@@ -3211,7 +3208,7 @@ impl Static {
pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst<'_>, ConstEvalError> {
let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity();
db.const_eval_static(self.id).map(|it| EvaluatedConst {
- const_: it,
+ allocation: it,
def: self.id.into(),
ty,
})
@@ -5740,8 +5737,11 @@ impl<'db> Type<'db> {
// FIXME: We don't handle GATs yet.
let projection = Ty::new_alias(
interner,
- AliasTyKind::Projection,
- AliasTy::new_from_args(interner, alias.id.into(), args),
+ AliasTy::new_from_args(
+ interner,
+ AliasTyKind::Projection { def_id: alias.id.into() },
+ args,
+ ),
);
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
@@ -6357,8 +6357,12 @@ impl<'db> Type<'db> {
}
pub fn as_associated_type_parent_trait(&self, db: &'db dyn HirDatabase) -> Option<Trait> {
- let TyKind::Alias(AliasTyKind::Projection, alias) = self.ty.kind() else { return None };
- match alias.def_id.expect_type_alias().loc(db).container {
+ let TyKind::Alias(AliasTy { kind: AliasTyKind::Projection { def_id }, .. }) =
+ self.ty.kind()
+ else {
+ return None;
+ };
+ match def_id.expect_type_alias().loc(db).container {
ItemContainerId::TraitId(id) => Some(Trait { id }),
_ => None,
}
@@ -6674,8 +6678,8 @@ impl Layout {
let offset = stride.bytes() * tail;
self.0.size.bytes().checked_sub(offset)?.checked_sub(tail_field_size)
}),
- layout::FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
- let tail = memory_index.last_index()?;
+ layout::FieldsShape::Arbitrary { ref offsets, ref in_memory_order } => {
+ let tail = in_memory_order[in_memory_order.len().checked_sub(1)? as u32];
let tail_field_size = field_size(tail.0.into_raw().into_u32() as usize)?;
let offset = offsets.get(tail)?.bytes();
self.0.size.bytes().checked_sub(offset)?.checked_sub(tail_field_size)
@@ -6695,10 +6699,11 @@ impl Layout {
let size = field_size(0)?;
stride.bytes().checked_sub(size)
}
- layout::FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
- let mut reverse_index = vec![None; memory_index.len()];
- for (src, (mem, offset)) in memory_index.iter().zip(offsets.iter()).enumerate() {
- reverse_index[*mem as usize] = Some((src, offset.bytes()));
+ layout::FieldsShape::Arbitrary { ref offsets, ref in_memory_order } => {
+ let mut reverse_index = vec![None; in_memory_order.len()];
+ for (mem, src) in in_memory_order.iter().enumerate() {
+ reverse_index[mem] =
+ Some((src.0.into_raw().into_u32() as usize, offsets[*src].bytes()));
}
if reverse_index.iter().any(|it| it.is_none()) {
stdx::never!();
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 1a34fa9134..6c43f80ce8 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -37,7 +37,7 @@ use hir_ty::{
lang_items::lang_items_for_bin_op,
method_resolution::{self, CandidateId},
next_solver::{
- DbInterner, ErrorGuaranteed, GenericArgs, ParamEnv, Ty, TyKind, TypingMode,
+ AliasTy, DbInterner, ErrorGuaranteed, GenericArgs, ParamEnv, Ty, TyKind, TypingMode,
infer::DbInternerInferExt,
},
traits::structurally_normalize_ty,
@@ -1293,10 +1293,14 @@ impl<'db> SourceAnalyzer<'db> {
PathResolution::Def(ModuleDef::Adt(adt_id.into())),
)
}
- TyKind::Alias(AliasTyKind::Projection, alias) => {
- let assoc_id = alias.def_id.expect_type_alias();
+ TyKind::Alias(AliasTy {
+ kind: AliasTyKind::Projection { def_id },
+ args,
+ ..
+ }) => {
+ let assoc_id = def_id.expect_type_alias();
(
- GenericSubstitution::new(assoc_id.into(), alias.args, env),
+ GenericSubstitution::new(assoc_id.into(), args, env),
PathResolution::Def(ModuleDef::TypeAlias(assoc_id.into())),
)
}