Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/lower.rs')
| -rw-r--r-- | crates/hir-ty/src/lower.rs | 479 |
1 files changed, 301 insertions, 178 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 3f187d205d..301e89556d 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -11,7 +11,6 @@ pub(crate) mod path; use std::{cell::OnceCell, iter, mem}; use arrayvec::ArrayVec; -use base_db::Crate; use either::Either; use hir_def::{ AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, @@ -24,7 +23,7 @@ use hir_def::{ GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate, }, item_tree::FieldsShape, - lang_item::LangItem, + lang_item::LangItems, resolver::{HasResolver, LifetimeNs, Resolver, TypeNs, ValueNs}, signatures::{FunctionSignature, TraitFlags, TypeAliasFlags}, type_ref::{ @@ -40,26 +39,29 @@ use rustc_hash::FxHashSet; use rustc_pattern_analysis::Captures; use rustc_type_ir::{ AliasTyKind, BoundVarIndexKind, ConstKind, DebruijnIndex, ExistentialPredicate, - ExistentialProjection, ExistentialTraitRef, FnSig, OutlivesPredicate, + ExistentialProjection, ExistentialTraitRef, FnSig, Interner, OutlivesPredicate, TermKind, TyKind::{self}, - TypeVisitableExt, Upcast, - inherent::{GenericArg as _, GenericArgs as _, IntoKind as _, Region as _, SliceLike, Ty as _}, + TypeFoldable, TypeVisitableExt, Upcast, UpcastFrom, elaborate, + inherent::{ + Clause as _, GenericArg as _, GenericArgs as _, IntoKind as _, Region as _, SliceLike, + Ty as _, + }, }; -use salsa::plumbing::AsId; use smallvec::{SmallVec, smallvec}; use stdx::{impl_from, never}; +use tracing::debug; use triomphe::{Arc, ThinArc}; use crate::{ - FnAbi, ImplTraitId, TraitEnvironment, TyLoweringDiagnostic, TyLoweringDiagnosticKind, + FnAbi, ImplTraitId, TyLoweringDiagnostic, TyLoweringDiagnosticKind, consteval::intern_const_ref, db::{HirDatabase, InternedOpaqueTyId}, generics::{Generics, generics, trait_self_param_idx}, next_solver::{ AliasTy, Binder, BoundExistentialPredicates, Clause, ClauseKind, Clauses, Const, - DbInterner, EarlyBinder, EarlyParamRegion, ErrorGuaranteed, GenericArg, GenericArgs, - ParamConst, ParamEnv, PolyFnSig, Predicate, Region, SolverDefId, TraitPredicate, TraitRef, - Ty, Tys, UnevaluatedConst, abi::Safety, + DbInterner, EarlyBinder, EarlyParamRegion, ErrorGuaranteed, FxIndexMap, GenericArg, + GenericArgs, ParamConst, ParamEnv, PolyFnSig, Predicate, Region, SolverDefId, + TraitPredicate, TraitRef, Ty, Tys, UnevaluatedConst, abi::Safety, util::BottomUpFolder, }, }; @@ -166,6 +168,7 @@ impl<'db> LifetimeElisionKind<'db> { pub struct TyLoweringContext<'db, 'a> { pub db: &'db dyn HirDatabase, interner: DbInterner<'db>, + lang_items: &'db LangItems, resolver: &'a Resolver<'db>, store: &'a ExpressionStore, def: GenericDefId, @@ -191,9 +194,12 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { ) -> Self { let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed); let in_binders = DebruijnIndex::ZERO; + let interner = DbInterner::new_with(db, resolver.krate()); Self { db, - interner: DbInterner::new_with(db, Some(resolver.krate()), None), + // Can provide no block since we don't use it for trait solving. + interner, + lang_items: interner.lang_items(), resolver, def, generics: Default::default(), @@ -490,7 +496,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { // away instead of two. let actual_opaque_type_data = self .with_debruijn(DebruijnIndex::ZERO, |ctx| { - ctx.lower_impl_trait(opaque_ty_id, bounds, self.resolver.krate()) + ctx.lower_impl_trait(opaque_ty_id, bounds) }); self.impl_trait_mode.opaque_type_data[idx] = actual_opaque_type_data; @@ -658,6 +664,8 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { ignore_bindings: bool, ) -> impl Iterator<Item = Clause<'db>> + use<'b, 'a, 'db> { let interner = self.interner; + let meta_sized = self.lang_items.MetaSized; + let pointee_sized = self.lang_items.PointeeSized; let mut assoc_bounds = None; let mut clause = None; match bound { @@ -666,10 +674,6 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { if let Some((trait_ref, mut ctx)) = self.lower_trait_ref_from_path(path, self_ty) { // FIXME(sized-hierarchy): Remove this bound modifications once we have implemented // sized-hierarchy correctly. - let meta_sized = LangItem::MetaSized - .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate()); - let pointee_sized = LangItem::PointeeSized - .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate()); if meta_sized.is_some_and(|it| it == trait_ref.def_id.0) { // Ignore this bound } else if pointee_sized.is_some_and(|it| it == trait_ref.def_id.0) { @@ -692,7 +696,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { } } &TypeBound::Path(path, TraitBoundModifier::Maybe) => { - let sized_trait = LangItem::Sized.resolve_trait(self.db, self.resolver.krate()); + let sized_trait = self.lang_items.Sized; // Don't lower associated type bindings as the only possible relaxed trait bound // `?Sized` has no of them. // If we got another trait here ignore the bound completely. @@ -721,138 +725,250 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty<'db> { let interner = self.interner; - // FIXME: we should never create non-existential predicates in the first place - // For now, use an error type so we don't run into dummy binder issues - let self_ty = Ty::new_error(interner, ErrorGuaranteed); + let dummy_self_ty = dyn_trait_dummy_self(interner); + let mut region = None; // INVARIANT: The principal trait bound, if present, must come first. Others may be in any // order but should be in the same order for the same set but possibly different order of // bounds in the input. // INVARIANT: If this function returns `DynTy`, there should be at least one trait bound. // These invariants are utilized by `TyExt::dyn_trait()` and chalk. - let mut lifetime = None; let bounds = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| { - let mut lowered_bounds: Vec< - rustc_type_ir::Binder<DbInterner<'db>, ExistentialPredicate<DbInterner<'db>>>, - > = Vec::new(); + let mut principal = None; + let mut auto_traits = SmallVec::<[_; 3]>::new(); + let mut projections = Vec::new(); + let mut had_error = false; + for b in bounds { let db = ctx.db; - ctx.lower_type_bound(b, self_ty, false).for_each(|b| { - if let Some(bound) = b - .kind() - .map_bound(|c| match c { - rustc_type_ir::ClauseKind::Trait(t) => { - let id = t.def_id(); - let is_auto = - db.trait_signature(id.0).flags.contains(TraitFlags::AUTO); - if is_auto { - Some(ExistentialPredicate::AutoTrait(t.def_id())) - } else { - Some(ExistentialPredicate::Trait( - ExistentialTraitRef::new_from_args( - interner, - t.def_id(), - GenericArgs::new_from_iter( - interner, - t.trait_ref.args.iter().skip(1), - ), - ), - )) + ctx.lower_type_bound(b, dummy_self_ty, false).for_each(|b| { + match b.kind().skip_binder() { + rustc_type_ir::ClauseKind::Trait(t) => { + let id = t.def_id(); + let is_auto = db.trait_signature(id.0).flags.contains(TraitFlags::AUTO); + if is_auto { + auto_traits.push(t.def_id().0); + } else { + if principal.is_some() { + // FIXME: Report an error. + had_error = true; } + principal = Some(b.kind().rebind(t.trait_ref)); } - rustc_type_ir::ClauseKind::Projection(p) => { - Some(ExistentialPredicate::Projection( - ExistentialProjection::new_from_args( - interner, - p.def_id(), - GenericArgs::new_from_iter( - interner, - p.projection_term.args.iter().skip(1), - ), - p.term, - ), - )) - } - rustc_type_ir::ClauseKind::TypeOutlives(outlives_predicate) => { - lifetime = Some(outlives_predicate.1); - None + } + rustc_type_ir::ClauseKind::Projection(p) => { + projections.push(b.kind().rebind(p)); + } + rustc_type_ir::ClauseKind::TypeOutlives(outlives_predicate) => { + if region.is_some() { + // FIXME: Report an error. + had_error = true; } - rustc_type_ir::ClauseKind::RegionOutlives(_) - | rustc_type_ir::ClauseKind::ConstArgHasType(_, _) - | rustc_type_ir::ClauseKind::WellFormed(_) - | rustc_type_ir::ClauseKind::ConstEvaluatable(_) - | rustc_type_ir::ClauseKind::HostEffect(_) - | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(), - }) - .transpose() - { - lowered_bounds.push(bound); + region = Some(outlives_predicate.1); + } + rustc_type_ir::ClauseKind::RegionOutlives(_) + | rustc_type_ir::ClauseKind::ConstArgHasType(_, _) + | rustc_type_ir::ClauseKind::WellFormed(_) + | rustc_type_ir::ClauseKind::ConstEvaluatable(_) + | rustc_type_ir::ClauseKind::HostEffect(_) + | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(), } }) } - let mut multiple_regular_traits = false; - let mut multiple_same_projection = false; - lowered_bounds.sort_unstable_by(|lhs, rhs| { - use std::cmp::Ordering; - match ((*lhs).skip_binder(), (*rhs).skip_binder()) { - (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => { - multiple_regular_traits = true; - // Order doesn't matter - we error - Ordering::Equal - } - ( - ExistentialPredicate::AutoTrait(lhs_id), - ExistentialPredicate::AutoTrait(rhs_id), - ) => lhs_id.0.cmp(&rhs_id.0), - (ExistentialPredicate::Trait(_), _) => Ordering::Less, - (_, ExistentialPredicate::Trait(_)) => Ordering::Greater, - (ExistentialPredicate::AutoTrait(_), _) => Ordering::Less, - (_, ExistentialPredicate::AutoTrait(_)) => Ordering::Greater, - ( - ExistentialPredicate::Projection(lhs), - ExistentialPredicate::Projection(rhs), - ) => { - let lhs_id = match lhs.def_id { - SolverDefId::TypeAliasId(id) => id, - _ => unreachable!(), - }; - let rhs_id = match rhs.def_id { - SolverDefId::TypeAliasId(id) => id, - _ => unreachable!(), - }; - // We only compare the `associated_ty_id`s. We shouldn't have - // multiple bounds for an associated type in the correct Rust code, - // and if we do, we error out. - if lhs_id == rhs_id { - multiple_same_projection = true; - } - lhs_id.as_id().index().cmp(&rhs_id.as_id().index()) - } - } - }); + if had_error { + return None; + } - if multiple_regular_traits || multiple_same_projection { + if principal.is_none() && auto_traits.is_empty() { + // No traits is not allowed. return None; } - if !lowered_bounds.first().map_or(false, |b| { - matches!( - b.as_ref().skip_binder(), - ExistentialPredicate::Trait(_) | ExistentialPredicate::AutoTrait(_) + // `Send + Sync` is the same as `Sync + Send`. + auto_traits.sort_unstable(); + // Duplicate auto traits are permitted. + auto_traits.dedup(); + + // Map the projection bounds onto a key that makes it easy to remove redundant + // bounds that are constrained by supertraits of the principal def id. + // + // Also make sure we detect conflicting bounds from expanding a trait alias and + // also specifying it manually, like: + // ``` + // type Alias = Trait<Assoc = i32>; + // let _: &dyn Alias<Assoc = u32> = /* ... */; + // ``` + let mut projection_bounds = FxIndexMap::default(); + for proj in projections { + let key = ( + proj.skip_binder().def_id().expect_type_alias(), + interner.anonymize_bound_vars( + proj.map_bound(|proj| proj.projection_term.trait_ref(interner)), + ), + ); + if let Some(old_proj) = projection_bounds.insert(key, proj) + && interner.anonymize_bound_vars(proj) + != interner.anonymize_bound_vars(old_proj) + { + // FIXME: Report "conflicting associated type" error. + } + } + + // A stable ordering of associated types from the principal trait and all its + // supertraits. We use this to ensure that different substitutions of a trait + // don't result in `dyn Trait` types with different projections lists, which + // can be unsound: <https://github.com/rust-lang/rust/pull/136458>. + // We achieve a stable ordering by walking over the unsubstituted principal + // trait ref. + let mut ordered_associated_types = vec![]; + + if let Some(principal_trait) = principal { + for clause in elaborate::elaborate( + interner, + [Clause::upcast_from( + TraitRef::identity(interner, principal_trait.def_id()), + interner, + )], ) - }) { - return None; + .filter_only_self() + { + let clause = clause.instantiate_supertrait(interner, principal_trait); + debug!("observing object predicate `{clause:?}`"); + + let bound_predicate = clause.kind(); + match bound_predicate.skip_binder() { + ClauseKind::Trait(pred) => { + // FIXME(negative_bounds): Handle this correctly... + let trait_ref = interner + .anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref)); + ordered_associated_types.extend( + pred.trait_ref + .def_id + .0 + .trait_items(self.db) + .associated_types() + .map(|item| (item, trait_ref)), + ); + } + ClauseKind::Projection(pred) => { + let pred = bound_predicate.rebind(pred); + // A `Self` within the original bound will be instantiated with a + // `trait_object_dummy_self`, so check for that. + let references_self = match pred.skip_binder().term.kind() { + TermKind::Ty(ty) => { + ty.walk().any(|arg| arg == dummy_self_ty.into()) + } + // FIXME(associated_const_equality): We should walk the const instead of not doing anything + TermKind::Const(_) => false, + }; + + // If the projection output contains `Self`, force the user to + // elaborate it explicitly to avoid a lot of complexity. + // + // The "classically useful" case is the following: + // ``` + // trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput { + // type MyOutput; + // } + // ``` + // + // Here, the user could theoretically write `dyn MyTrait<MyOutput = X>`, + // but actually supporting that would "expand" to an infinitely-long type + // `fix $ τ → dyn MyTrait<MyOutput = X, Output = <τ as MyTrait>::MyOutput`. + // + // Instead, we force the user to write + // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See + // the discussion in #56288 for alternatives. + if !references_self { + let key = ( + pred.skip_binder().projection_term.def_id.expect_type_alias(), + interner.anonymize_bound_vars(pred.map_bound(|proj| { + proj.projection_term.trait_ref(interner) + })), + ); + if !projection_bounds.contains_key(&key) { + projection_bounds.insert(key, pred); + } + } + } + _ => (), + } + } } - // As multiple occurrences of the same auto traits *are* permitted, we deduplicate the - // bounds. We shouldn't have repeated elements besides auto traits at this point. - lowered_bounds.dedup(); + // We compute the list of projection bounds taking the ordered associated types, + // and check if there was an entry in the collected `projection_bounds`. Those + // are computed by first taking the user-written associated types, then elaborating + // the principal trait ref, and only using those if there was no user-written. + // See note below about how we handle missing associated types with `Self: Sized`, + // which are not required to be provided, but are still used if they are provided. + let mut projection_bounds: Vec<_> = ordered_associated_types + .into_iter() + .filter_map(|key| projection_bounds.get(&key).copied()) + .collect(); + + projection_bounds.sort_unstable_by_key(|proj| proj.skip_binder().def_id()); + + let principal = principal.map(|principal| { + principal.map_bound(|principal| { + // Verify that `dummy_self` did not leak inside default type parameters. + let args: Vec<_> = principal + .args + .iter() + // Skip `Self` + .skip(1) + .map(|arg| { + if arg.walk().any(|arg| arg == dummy_self_ty.into()) { + // FIXME: Report an error. + Ty::new_error(interner, ErrorGuaranteed).into() + } else { + arg + } + }) + .collect(); + + ExistentialPredicate::Trait(ExistentialTraitRef::new( + interner, + principal.def_id, + args, + )) + }) + }); + + let projections = projection_bounds.into_iter().map(|proj| { + proj.map_bound(|mut proj| { + // Like for trait refs, verify that `dummy_self` did not leak inside default type + // parameters. + let references_self = proj.projection_term.args.iter().skip(1).any(|arg| { + if arg.walk().any(|arg| arg == dummy_self_ty.into()) { + return true; + } + false + }); + if references_self { + proj.projection_term = + replace_dummy_self_with_error(interner, proj.projection_term); + } + + ExistentialPredicate::Projection(ExistentialProjection::erase_self_ty( + interner, proj, + )) + }) + }); + + let auto_traits = auto_traits.into_iter().map(|auto_trait| { + Binder::dummy(ExistentialPredicate::AutoTrait(auto_trait.into())) + }); - Some(BoundExistentialPredicates::new_from_iter(interner, lowered_bounds)) + // N.b. principal, projections, auto traits + Some(BoundExistentialPredicates::new_from_iter( + interner, + principal.into_iter().chain(projections).chain(auto_traits), + )) }); if let Some(bounds) = bounds { - let region = match lifetime { + let region = match region { Some(it) => match it.kind() { rustc_type_ir::RegionKind::ReBound(BoundVarIndexKind::Bound(db), var) => { Region::new_bound( @@ -873,12 +989,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { } } - fn lower_impl_trait( - &mut self, - def_id: SolverDefId, - bounds: &[TypeBound], - krate: Crate, - ) -> ImplTrait<'db> { + fn lower_impl_trait(&mut self, def_id: SolverDefId, bounds: &[TypeBound]) -> ImplTrait<'db> { let interner = self.interner; cov_mark::hit!(lower_rpit); let args = GenericArgs::identity_for_item(interner, def_id); @@ -894,7 +1005,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { } if !ctx.unsized_types.contains(&self_ty) { - let sized_trait = LangItem::Sized.resolve_trait(self.db, krate); + let sized_trait = self.lang_items.Sized; let sized_clause = sized_trait.map(|trait_id| { let trait_ref = TraitRef::new_from_args( interner, @@ -935,6 +1046,26 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { } } +fn dyn_trait_dummy_self(interner: DbInterner<'_>) -> Ty<'_> { + // This type must not appear anywhere except here. + Ty::new_fresh(interner, 0) +} + +fn replace_dummy_self_with_error<'db, T: TypeFoldable<DbInterner<'db>>>( + interner: DbInterner<'db>, + t: T, +) -> T { + let dyn_trait_dummy_self = dyn_trait_dummy_self(interner); + t.fold_with(&mut BottomUpFolder { + interner, + ty_op: |ty| { + if ty == dyn_trait_dummy_self { Ty::new_error(interner, ErrorGuaranteed) } else { ty } + }, + lt_op: |lt| lt, + ct_op: |ct| ct, + }) +} + pub(crate) fn lower_mutability(m: hir_def::type_ref::Mutability) -> Mutability { match m { hir_def::type_ref::Mutability::Shared => Mutability::Not, @@ -1101,7 +1232,7 @@ impl ValueTyDefId { /// the constructor function `(usize) -> Foo` which lives in the values /// namespace. pub(crate) fn ty_query<'db>(db: &'db dyn HirDatabase, def: TyDefId) -> EarlyBinder<'db, Ty<'db>> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); match def { TyDefId::BuiltinType(it) => EarlyBinder::bind(Ty::from_builtin_type(interner, it)), TyDefId::AdtId(it) => EarlyBinder::bind(Ty::new_adt( @@ -1116,7 +1247,7 @@ pub(crate) fn ty_query<'db>(db: &'db dyn HirDatabase, def: TyDefId) -> EarlyBind /// Build the declared type of a function. This should not need to look at the /// function body. fn type_for_fn<'db>(db: &'db dyn HirDatabase, def: FunctionId) -> EarlyBinder<'db, Ty<'db>> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); EarlyBinder::bind(Ty::new_fn_def( interner, CallableDefId::FunctionId(def).into(), @@ -1165,7 +1296,7 @@ fn type_for_struct_constructor<'db>( FieldsShape::Record => None, FieldsShape::Unit => Some(type_for_adt(db, def.into())), FieldsShape::Tuple => { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); Some(EarlyBinder::bind(Ty::new_fn_def( interner, CallableDefId::StructId(def).into(), @@ -1185,7 +1316,7 @@ fn type_for_enum_variant_constructor<'db>( FieldsShape::Record => None, FieldsShape::Unit => Some(type_for_adt(db, def.loc(db).parent.into())), FieldsShape::Tuple => { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); Some(EarlyBinder::bind(Ty::new_fn_def( interner, CallableDefId::EnumVariantId(def).into(), @@ -1216,7 +1347,7 @@ pub(crate) fn type_for_type_alias_with_diagnostics_query<'db>( let type_alias_data = db.type_alias_signature(t); let mut diags = None; let resolver = t.resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let interner = DbInterner::new_no_crate(db); let inner = if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) { EarlyBinder::bind(Ty::new_foreign(interner, t.into())) } else { @@ -1244,7 +1375,7 @@ pub(crate) fn type_for_type_alias_with_diagnostics_cycle_result<'db>( db: &'db dyn HirDatabase, _adt: TypeAliasId, ) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) { - (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None) + (EarlyBinder::bind(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed)), None) } pub(crate) fn impl_self_ty_query<'db>( @@ -1277,7 +1408,7 @@ pub(crate) fn impl_self_ty_with_diagnostics_cycle_result( db: &dyn HirDatabase, _impl_id: ImplId, ) -> (EarlyBinder<'_, Ty<'_>>, Diagnostics) { - (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None) + (EarlyBinder::bind(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed)), None) } pub(crate) fn const_param_ty_query<'db>(db: &'db dyn HirDatabase, def: ConstParamId) -> Ty<'db> { @@ -1292,7 +1423,7 @@ pub(crate) fn const_param_ty_with_diagnostics_query<'db>( let (parent_data, store) = db.generic_params_and_store(def.parent()); let data = &parent_data[def.local_id()]; let resolver = def.parent().resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let interner = DbInterner::new_no_crate(db); let mut ctx = TyLoweringContext::new( db, &resolver, @@ -1313,10 +1444,9 @@ pub(crate) fn const_param_ty_with_diagnostics_query<'db>( pub(crate) fn const_param_ty_with_diagnostics_cycle_result<'db>( db: &'db dyn HirDatabase, _: crate::db::HirDatabaseData, - def: ConstParamId, + _def: ConstParamId, ) -> (Ty<'db>, Diagnostics) { - let resolver = def.parent().resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let interner = DbInterner::new_no_crate(db); (Ty::new_error(interner, ErrorGuaranteed), None) } @@ -1374,7 +1504,7 @@ pub(crate) fn generic_predicates_for_param<'db>( assoc_name: Option<Name>, ) -> EarlyBinder<'db, Box<[Clause<'db>]>> { let generics = generics(db, def); - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let resolver = def.resolver(db); let mut ctx = TyLoweringContext::new( db, @@ -1401,9 +1531,7 @@ pub(crate) fn generic_predicates_for_param<'db>( let TypeRef::Path(path) = &ctx.store[path.type_ref()] else { return false; }; - let Some(pointee_sized) = - LangItem::PointeeSized.resolve_trait(ctx.db, ctx.resolver.krate()) - else { + let Some(pointee_sized) = ctx.lang_items.PointeeSized else { return false; }; // Lower the path directly with `Resolver` instead of PathLoweringContext` @@ -1466,9 +1594,13 @@ pub(crate) fn generic_predicates_for_param<'db>( let args = GenericArgs::identity_for_item(interner, def.into()); if !args.is_empty() { let explicitly_unsized_tys = ctx.unsized_types; - if let Some(implicitly_sized_predicates) = - implicitly_sized_clauses(db, param_id.parent, &explicitly_unsized_tys, &args, &resolver) - { + if let Some(implicitly_sized_predicates) = implicitly_sized_clauses( + db, + ctx.lang_items, + param_id.parent, + &explicitly_unsized_tys, + &args, + ) { predicates.extend(implicitly_sized_predicates); }; } @@ -1520,8 +1652,7 @@ pub fn type_alias_bounds_with_diagnostics<'db>( } if !ctx.unsized_types.contains(&interner_ty) { - let sized_trait = LangItem::Sized - .resolve_trait(ctx.db, interner.krate.expect("Must have interner.krate")); + let sized_trait = ctx.lang_items.Sized; if let Some(sized_trait) = sized_trait { let trait_ref = TraitRef::new_from_args( interner, @@ -1612,10 +1743,9 @@ impl<'db> GenericPredicates<'db> { pub(crate) fn trait_environment_for_body_query( db: &dyn HirDatabase, def: DefWithBodyId, -) -> Arc<TraitEnvironment<'_>> { +) -> ParamEnv<'_> { let Some(def) = def.as_generic_def_id(db) else { - let krate = def.module(db).krate(); - return TraitEnvironment::empty(krate); + return ParamEnv::empty(); }; db.trait_environment(def) } @@ -1623,24 +1753,16 @@ pub(crate) fn trait_environment_for_body_query( pub(crate) fn trait_environment_query<'db>( db: &'db dyn HirDatabase, def: GenericDefId, -) -> Arc<TraitEnvironment<'db>> { +) -> ParamEnv<'db> { let module = def.module(db); - let interner = DbInterner::new_with(db, Some(module.krate()), module.containing_block()); + let interner = DbInterner::new_with(db, module.krate()); let predicates = GenericPredicates::query_all(db, def); - let traits_in_scope = predicates - .iter_identity_copied() - .filter_map(|pred| match pred.kind().skip_binder() { - ClauseKind::Trait(tr) => Some((tr.self_ty(), tr.def_id().0)), - _ => None, - }) - .collect(); let clauses = rustc_type_ir::elaborate::elaborate(interner, predicates.iter_identity_copied()); let clauses = Clauses::new_from_iter(interner, clauses); - let env = ParamEnv { clauses }; // FIXME: We should normalize projections here, like rustc does. - TraitEnvironment::new(module.krate(), module.containing_block(), traits_in_scope, env) + ParamEnv { clauses } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -1663,7 +1785,7 @@ where { let generics = generics(db, def); let resolver = def.resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let interner = DbInterner::new_no_crate(db); let mut ctx = TyLoweringContext::new( db, &resolver, @@ -1671,7 +1793,7 @@ where def, LifetimeElisionKind::AnonymousReportError, ); - let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()); + let sized_trait = ctx.lang_items.Sized; let mut predicates = Vec::new(); let all_generics = @@ -1811,7 +1933,7 @@ fn push_const_arg_has_type_predicates<'db>( predicates: &mut Vec<Clause<'db>>, generics: &Generics, ) { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let const_params_offset = generics.len_parent() + generics.len_lifetimes_self(); for (param_index, (param_idx, param_data)) in generics.iter_self_type_or_consts().enumerate() { if !matches!(param_data, TypeOrConstParamData::ConstParamData(_)) { @@ -1839,13 +1961,13 @@ fn push_const_arg_has_type_predicates<'db>( /// Exception is Self of a trait def. fn implicitly_sized_clauses<'a, 'subst, 'db>( db: &'db dyn HirDatabase, + lang_items: &LangItems, def: GenericDefId, explicitly_unsized_tys: &'a FxHashSet<Ty<'db>>, args: &'subst GenericArgs<'db>, - resolver: &Resolver<'db>, ) -> Option<impl Iterator<Item = Clause<'db>> + Captures<'a> + Captures<'subst>> { - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); - let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate())?; + let interner = DbInterner::new_no_crate(db); + let sized_trait = lang_items.Sized?; let trait_self_idx = trait_self_param_idx(db, def); @@ -1992,7 +2114,7 @@ fn fn_sig_for_fn<'db>( ) -> EarlyBinder<'db, PolyFnSig<'db>> { let data = db.function_signature(def); let resolver = def.resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let interner = DbInterner::new_no_crate(db); let mut ctx_params = TyLoweringContext::new( db, &resolver, @@ -2028,7 +2150,7 @@ fn fn_sig_for_fn<'db>( } fn type_for_adt<'db>(db: &'db dyn HirDatabase, adt: AdtId) -> EarlyBinder<'db, Ty<'db>> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let args = GenericArgs::identity_for_item(interner, adt.into()); let ty = Ty::new_adt(interner, adt, args); EarlyBinder::bind(ty) @@ -2043,7 +2165,7 @@ fn fn_sig_for_struct_constructor<'db>( let ret = type_for_adt(db, def.into()).skip_binder(); let inputs_and_output = - Tys::new_from_iter(DbInterner::new_with(db, None, None), params.chain(Some(ret))); + Tys::new_from_iter(DbInterner::new_no_crate(db), params.chain(Some(ret))); EarlyBinder::bind(Binder::dummy(FnSig { abi: FnAbi::RustCall, c_variadic: false, @@ -2062,7 +2184,7 @@ fn fn_sig_for_enum_variant_constructor<'db>( let ret = type_for_adt(db, parent.into()).skip_binder(); let inputs_and_output = - Tys::new_from_iter(DbInterner::new_with(db, None, None), params.chain(Some(ret))); + Tys::new_from_iter(DbInterner::new_no_crate(db), params.chain(Some(ret))); EarlyBinder::bind(Binder::dummy(FnSig { abi: FnAbi::RustCall, c_variadic: false, @@ -2078,7 +2200,7 @@ pub(crate) fn associated_ty_item_bounds<'db>( ) -> EarlyBinder<'db, BoundExistentialPredicates<'db>> { let type_alias_data = db.type_alias_signature(type_alias); let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let interner = DbInterner::new_no_crate(db); let mut ctx = TyLoweringContext::new( db, &resolver, @@ -2139,7 +2261,7 @@ pub(crate) fn associated_ty_item_bounds<'db>( } if !ctx.unsized_types.contains(&self_ty) - && let Some(sized_trait) = LangItem::Sized.resolve_trait(db, resolver.krate()) + && let Some(sized_trait) = ctx.lang_items.Sized { let sized_clause = Binder::dummy(ExistentialPredicate::Trait(ExistentialTraitRef::new( interner, @@ -2157,7 +2279,8 @@ pub(crate) fn associated_type_by_name_including_super_traits<'db>( trait_ref: TraitRef<'db>, name: &Name, ) -> Option<(TraitRef<'db>, TypeAliasId)> { - let interner = DbInterner::new_with(db, None, None); + let module = trait_ref.def_id.0.module(db); + let interner = DbInterner::new_with(db, module.krate()); rustc_type_ir::elaborate::supertraits(interner, Binder::dummy(trait_ref)).find_map(|t| { let trait_id = t.as_ref().skip_binder().def_id.0; let assoc_type = trait_id.trait_items(db).associated_type_by_name(name)?; @@ -2171,7 +2294,7 @@ pub fn associated_type_shorthand_candidates( res: TypeNs, mut cb: impl FnMut(&Name, TypeAliasId) -> bool, ) -> Option<TypeAliasId> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); named_associated_type_shorthand_candidates(interner, def, res, None, |name, _, id| { cb(name, id).then_some(id) }) |