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.rs460
1 files changed, 296 insertions, 164 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 3f187d205d..cfd2a06b2a 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,14 +39,17 @@ 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::{
@@ -57,9 +59,9 @@ use crate::{
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);
+ }
- Some(BoundExistentialPredicates::new_from_iter(interner, lowered_bounds))
+ 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()))
+ });
+
+ // 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,
@@ -1625,7 +1756,7 @@ pub(crate) fn trait_environment_query<'db>(
def: GenericDefId,
) -> Arc<TraitEnvironment<'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()
@@ -1663,7 +1794,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 +1802,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 +1942,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 +1970,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 +2123,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 +2159,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 +2174,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 +2193,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 +2209,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 +2270,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 +2288,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 +2303,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)
})