Unnamed repository; edit this file 'description' to name the repository.
Update solver types as required by the upgrade
38 files changed, 416 insertions, 1770 deletions
diff --git a/Cargo.lock b/Cargo.lock index 4c6e0e5ed8..94e9507c02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2048,9 +2048,9 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "ra-ap-rustc_abi" -version = "0.159.0" +version = "0.160.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ada9f3d87f035c2234b48ceb43c07f04daa40348bffda88e91e5bc452fca147" +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.159.0" +version = "0.160.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "113acd7f51ff383eb86ebc8fb12df8a44d418bed0a990bcea363388f737a329a" +checksum = "021d80bea67458b8c90cc25bfdca6f911ea818a41905e370c1f310cced1dd07e" [[package]] name = "ra-ap-rustc_hashes" -version = "0.159.0" +version = "0.160.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2002d37e435be69d87d307bd4d9b494a3ac08b30d383c7e4b1b6b3f976fb2675" +checksum = "8bb89395306ecfc980d252f77a4038d8b8bb578a25c856b545cbeeb3fde8358e" dependencies = [ "rustc-stable-hash", ] [[package]] name = "ra-ap-rustc_index" -version = "0.159.0" +version = "0.160.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e8921cba582b0c93d8e4443cca24aec07f25e87b1483e4fa62113d2d9cfea1" +checksum = "84219d028a1954c4340ddde11adffe93eb83e476e942718fe926f4d99637cbbe" dependencies = [ "ra-ap-rustc_index_macros", ] [[package]] name = "ra-ap-rustc_index_macros" -version = "0.159.0" +version = "0.160.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49574ecf35748cebf67fec53db7e81968b599cc50becceba01b895d1ad40e9ea" +checksum = "3908fdfa258c663d8ee407e6b4a205b0880e323b533c0df7edceafbd54a02fb6" dependencies = [ "proc-macro2", "quote", @@ -2095,9 +2095,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_lexer" -version = "0.159.0" +version = "0.160.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33aabb4e87bc6c0dbb721728ad71126fb17fb9262cb9cd215314a10d64c92985" +checksum = "34b50f19d5856b8e2b36150e89b53a6102ab096e8044e1f55fd6fef977b10d85" dependencies = [ "memchr", "unicode-ident", @@ -2106,9 +2106,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_next_trait_solver" -version = "0.159.0" +version = "0.160.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7559a4b05b358ec59838d8d2a9a6b6e3c4f7aaf3805c0878b82456d63ad4d05" +checksum = "76f83dcc451bcee8a99e284a583d5b3d82db5a200107a256a40ef132c4988f1b" dependencies = [ "derive-where", "ra-ap-rustc_index", @@ -2119,9 +2119,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_parse_format" -version = "0.159.0" +version = "0.160.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ec9bf15c3fed1ba4e0f9a0ceba36f8fa740e2f606609a68fc42034e0e6b28d" +checksum = "f31236bdc6cbcae8af42d0b2db2fa8d812a8715b90a2ba5afb1132b37a4d0bbc" dependencies = [ "ra-ap-rustc_lexer", "rustc-literal-escaper 0.0.7", @@ -2129,9 +2129,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_pattern_analysis" -version = "0.159.0" +version = "0.160.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9088a430b80729958eda4c428acf731644d3b78caa4285ed659ff586b772743" +checksum = "3fc4edac740e896fba4b3b4d9c423083e3eac49947732561ddfb2377e1f57829" dependencies = [ "ra-ap-rustc_index", "rustc-hash 2.1.1", @@ -2142,9 +2142,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_type_ir" -version = "0.159.0" +version = "0.160.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0f59b0708ec44c375dad7dc3818a3bd8eb3497a54d5968f5c945ac11c029854" +checksum = "8efa119afc1bcadd821b27aa94332abf79c48ac0a972cb78932f63004ba4cdd9" dependencies = [ "arrayvec", "bitflags 2.9.4", @@ -2163,9 +2163,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_type_ir_macros" -version = "0.159.0" +version = "0.160.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4b09efb7749eb0a3fb8fac1ce26618eef8ee5ca0aa36fe01228b853d28113a2" +checksum = "e6b1dc03abfabc7179393c282892c73a3f0e4bbd5f0b6c87ff42c2b142e68f57" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 40fcb9aed6..4372afa0f5 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.159", default-features = false } -ra-ap-rustc_parse_format = { version = "0.159", default-features = false } -ra-ap-rustc_index = { version = "0.159", default-features = false } -ra-ap-rustc_abi = { version = "0.159", default-features = false } -ra-ap-rustc_pattern_analysis = { version = "0.159", default-features = false } -ra-ap-rustc_ast_ir = { version = "0.159", default-features = false } -ra-ap-rustc_type_ir = { version = "0.159", default-features = false } -ra-ap-rustc_next_trait_solver = { version = "0.159", 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. 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/display.rs b/crates/hir-ty/src/display.rs index 7f1b1ecbd2..1e4c2985cf 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -646,7 +646,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 +657,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 +673,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()) )?; @@ -1005,7 +1005,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>"), @@ -1280,7 +1280,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 +1289,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 +1585,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 71a7db6559..5a6e14a1e5 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/eval.rs b/crates/hir-ty/src/mir/eval.rs index 79b1c5cb7c..17af4ad961 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -46,7 +46,7 @@ use crate::{ layout::{Layout, LayoutError, RustcEnumVariantIdx}, method_resolution::{is_dyn_method, lookup_impl_const}, next_solver::{ - Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArgs, Region, + AliasTy, Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArgs, Region, StoredConst, StoredTy, Ty, TyKind, TypingMode, UnevaluatedConst, ValueConst, infer::{DbInternerInferExt, InferCtxt, traits::ObligationCause}, obligation_ctxt::ObligationCtxt, @@ -2340,7 +2340,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 +2483,7 @@ impl<'db> Evaluator<'db> { | TyKind::Error(_) | TyKind::Placeholder(_) | TyKind::Dynamic(_, _) - | TyKind::Alias(_, _) + | TyKind::Alias(..) | TyKind::Bound(_, _) | TyKind::Infer(_) | TyKind::Pat(_, _) diff --git a/crates/hir-ty/src/next_solver.rs b/crates/hir-ty/src/next_solver.rs index 605e31404c..354ad16ffe 100644 --- a/crates/hir-ty/src/next_solver.rs +++ b/crates/hir-ty/src/next_solver.rs @@ -101,7 +101,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 +109,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 +168,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,6 +221,12 @@ 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); @@ -270,11 +277,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/consts.rs b/crates/hir-ty/src/next_solver/consts.rs index 9643f1ba4c..8ed515b452 100644 --- a/crates/hir-ty/src/next_solver/consts.rs +++ b/crates/hir-ty/src/next_solver/consts.rs @@ -10,16 +10,19 @@ use rustc_type_ir::{ BoundVar, BoundVarIndexKind, ConstVid, DebruijnIndex, FlagComputation, Flags, GenericTypeVisitable, InferConst, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, WithCachedTypeInfo, - inherent::{IntoKind, ParamEnv as _, PlaceholderLike, SliceLike}, + inherent::{IntoKind, ParamEnv as _, SliceLike}, relate::Relate, }; use crate::{ MemoryMap, - next_solver::{ClauseKind, ParamEnv, impl_stored_interned}, + next_solver::{ + ClauseKind, ParamEnv, 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 type ConstKind<'db> = rustc_type_ir::ConstKind<DbInterner<'db>>; pub type UnevaluatedConst<'db> = rustc_type_ir::UnevaluatedConst<DbInterner<'db>>; @@ -71,11 +74,15 @@ 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)) } @@ -120,7 +127,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 { @@ -169,6 +176,8 @@ impl ParamConst { } } +pub type ValTreeKind<'db> = rustc_type_ir::ValTreeKind<DbInterner<'db>>; + /// A type-level constant value. /// /// Represents a typed, fully evaluated constant. @@ -235,6 +244,14 @@ const _: () = { is_copy::<Valtree<'static>>(); }; +impl<'db> IntoKind for Valtree<'db> { + type Kind = ValTreeKind<'db>; + + fn kind(self) -> Self::Kind { + todo!() + } +} + impl<'db> Valtree<'db> { #[inline] pub fn new(bytes: ConstBytes<'db>) -> Self { @@ -388,25 +405,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 +440,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 +461,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/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..9a94d1a865 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,9 @@ 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, SimplifiedType, + SolverContext, SolverDefIds, TraitIdWrapper, TypeAliasIdWrapper, UnevaluatedConst, util::{explicit_item_bounds, explicit_item_self_bounds}, }, }; @@ -53,14 +53,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, }; @@ -390,43 +387,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 +407,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 +726,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 +772,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 +1007,6 @@ impl<'db> Interner for DbInterner<'db> { type Term = Term<'db>; type BoundVarKinds = BoundVarKinds<'db>; - type BoundVarKind = BoundVarKind; type PredefinedOpaques = PredefinedOpaques<'db>; @@ -1047,13 +1017,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 +1043,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 +1054,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 Consts = Consts<'db>; + type 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 +1197,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 +1296,7 @@ impl<'db> Interner for DbInterner<'db> { 50 } - fn features(self) -> Self::Features { + fn features(self) -> Features { Features } @@ -1476,7 +1426,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 +1492,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 +1534,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 +1562,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 +1608,8 @@ impl<'db> Interner for DbInterner<'db> { ignore = { AsyncFnKindUpvars, DynMetadata, + FieldBase, + FieldType, } Metadata, @@ -1676,6 +1634,8 @@ impl<'db> Interner for DbInterner<'db> { CallRefFuture, CallOnceFuture, AsyncFnOnceOutput, + FieldBase, + FieldType, } DynMetadata, @@ -1694,6 +1654,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 +1832,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 +1925,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 +2023,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 +2229,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 +2286,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 +2301,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 +2414,8 @@ TrivialTypeTraversalImpls! { Span, ParamConst, ParamTy, - BoundRegion, - Placeholder<BoundRegion>, - Placeholder<BoundTy>, - Placeholder<BoundVar>, - Placeholder<BoundConst>, - BoundVarKind, EarlyParamRegion, - LateParamRegion, AdtDef, - BoundTy, - BoundConst, } mod tls_db { 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..a9e7de1613 100644 --- a/crates/hir-ty/src/next_solver/solver.rs +++ b/crates/hir-ty/src/next_solver/solver.rs @@ -155,10 +155,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, }) }; 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 53240259e0..e102572148 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -5736,8 +5736,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); @@ -6353,8 +6356,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, } @@ -6670,8 +6677,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) @@ -6691,10 +6698,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())), ) } |