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.rs1028
1 files changed, 497 insertions, 531 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index d3db2a9057..dbbe31971e 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -8,23 +8,23 @@
pub(crate) mod diagnostics;
pub(crate) mod path;
-use std::{cell::OnceCell, iter, mem};
+use std::{cell::OnceCell, iter, mem, sync::OnceLock};
use either::Either;
use hir_def::{
AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, EnumId, EnumVariantId,
- ExpressionStoreOwnerId, FunctionId, GeneralConstId, GenericDefId, GenericParamId, HasModule,
- ImplId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, StaticId, StructId, TraitId,
+ ExpressionStoreOwnerId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId,
+ ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, StaticId, StructId, TraitId,
TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, VariantId,
builtin_type::BuiltinType,
- expr_store::{ExpressionStore, HygieneId, path::Path},
+ expr_store::{ExpressionStore, path::Path},
hir::generics::{
- GenericParamDataRef, GenericParams, TypeOrConstParamData, TypeParamProvenance,
- WherePredicate,
+ GenericParamDataRef, GenericParams, LocalTypeOrConstParamId, TypeOrConstParamData,
+ TypeParamProvenance, WherePredicate,
},
item_tree::FieldsShape,
lang_item::LangItems,
- resolver::{HasResolver, LifetimeNs, Resolver, TypeNs, ValueNs},
+ resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
signatures::{
ConstSignature, FunctionSignature, ImplSignature, StaticSignature, StructSignature,
TraitFlags, TraitSignature, TypeAliasFlags, TypeAliasSignature,
@@ -40,27 +40,27 @@ use path::{PathDiagnosticCallback, PathLoweringContext};
use rustc_ast_ir::Mutability;
use rustc_hash::FxHashSet;
use rustc_type_ir::{
- AliasTyKind, BoundVarIndexKind, ConstKind, DebruijnIndex, ExistentialPredicate,
- ExistentialProjection, ExistentialTraitRef, FnSig, Interner, OutlivesPredicate, TermKind,
- TyKind, TypeFoldable, TypeVisitableExt, Upcast, UpcastFrom, elaborate,
+ AliasTyKind, BoundVarIndexKind, DebruijnIndex, ExistentialPredicate, ExistentialProjection,
+ ExistentialTraitRef, FnSig, Interner, OutlivesPredicate, TermKind, TyKind, TypeFoldable,
+ TypeVisitableExt, Upcast, UpcastFrom, elaborate,
inherent::{Clause as _, GenericArgs as _, IntoKind as _, Region as _, Ty as _},
};
use smallvec::SmallVec;
use stdx::{impl_from, never};
+use thin_vec::ThinVec;
use tracing::debug;
-use triomphe::{Arc, ThinArc};
use crate::{
FnAbi, ImplTraitId, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
- consteval::intern_const_ref,
- db::{HirDatabase, InternedOpaqueTyId},
+ consteval::{create_anon_const, path_to_const},
+ db::{AnonConstId, GeneralConstId, HirDatabase, InternedOpaqueTyId},
generics::{Generics, SingleGenerics, generics},
next_solver::{
- AliasTy, Binder, BoundExistentialPredicates, Clause, ClauseKind, Clauses, Const,
+ AliasTy, Binder, BoundExistentialPredicates, Clause, ClauseKind, Clauses, Const, ConstKind,
DbInterner, EarlyBinder, EarlyParamRegion, ErrorGuaranteed, FxIndexMap, GenericArg,
GenericArgs, ParamConst, ParamEnv, PolyFnSig, Predicate, Region, SolverDefId,
StoredClauses, StoredEarlyBinder, StoredGenericArg, StoredGenericArgs, StoredPolyFnSig,
- StoredTy, TraitPredicate, TraitRef, Ty, Tys, UnevaluatedConst, abi::Safety,
+ StoredTraitRef, StoredTy, TraitPredicate, TraitRef, Ty, Tys, abi::Safety,
util::BottomUpFolder,
},
};
@@ -171,6 +171,18 @@ pub(crate) enum GenericPredicateSource {
AssocTyBound,
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub(crate) enum ForbidParamsAfterReason {
+ /// When lowering generic param defaults, you cannot refer to any param after
+ /// the currently lowered param, including the current param.
+ LoweringParamDefault,
+ /// Most anon const (except array repeat expressions) cannot refer to any generic
+ /// param.
+ AnonConst,
+ /// The type of a const param cannot refer to a type param.
+ ConstParamTy,
+}
+
#[derive(Debug)]
pub struct TyLoweringContext<'db, 'a> {
pub db: &'db dyn HirDatabase,
@@ -179,17 +191,18 @@ pub struct TyLoweringContext<'db, 'a> {
lang_items: &'db LangItems,
resolver: &'a Resolver<'db>,
store: &'a ExpressionStore,
- def: GenericDefId,
+ def: ExpressionStoreOwnerId,
+ generic_def: GenericDefId,
generics: OnceCell<Generics<'db>>,
in_binders: DebruijnIndex,
impl_trait_mode: ImplTraitLoweringState,
/// Tracks types with explicit `?Sized` bounds.
pub(crate) unsized_types: FxHashSet<Ty<'db>>,
- pub(crate) diagnostics: Vec<TyLoweringDiagnostic>,
+ pub(crate) diagnostics: ThinVec<TyLoweringDiagnostic>,
lifetime_elision: LifetimeElisionKind<'db>,
- /// When lowering the defaults for generic params, this contains the index of the currently lowered param.
- /// We disallow referring to later params, or to ADT's `Self`.
- lowering_param_default: Option<u32>,
+ forbid_params_after: Option<u32>,
+ forbid_params_after_reason: ForbidParamsAfterReason,
+ pub(crate) defined_anon_consts: ThinVec<AnonConstId>,
}
impl<'db, 'a> TyLoweringContext<'db, 'a> {
@@ -197,7 +210,8 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
db: &'db dyn HirDatabase,
resolver: &'a Resolver<'db>,
store: &'a ExpressionStore,
- def: GenericDefId,
+ def: ExpressionStoreOwnerId,
+ generic_def: GenericDefId,
lifetime_elision: LifetimeElisionKind<'db>,
) -> Self {
let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed);
@@ -211,14 +225,17 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
lang_items: interner.lang_items(),
resolver,
def,
+ generic_def,
generics: Default::default(),
store,
in_binders,
impl_trait_mode,
unsized_types: FxHashSet::default(),
- diagnostics: Vec::new(),
+ diagnostics: ThinVec::new(),
lifetime_elision,
- lowering_param_default: None,
+ forbid_params_after: None,
+ forbid_params_after_reason: ForbidParamsAfterReason::AnonConst,
+ defined_anon_consts: ThinVec::new(),
}
}
@@ -254,8 +271,9 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
self
}
- pub(crate) fn lowering_param_default(&mut self, index: u32) {
- self.lowering_param_default = Some(index);
+ pub(crate) fn forbid_params_after(&mut self, index: u32, reason: ForbidParamsAfterReason) {
+ self.forbid_params_after = Some(index);
+ self.forbid_params_after_reason = reason;
}
pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) {
@@ -281,128 +299,45 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
pub(crate) fn lower_const(&mut self, const_ref: ConstRef, const_type: Ty<'db>) -> Const<'db> {
- let expr_id = const_ref.expr;
- let expr = &self.store[expr_id];
- match expr {
- hir_def::hir::Expr::Path(path) => self
- .path_to_const(path)
- .unwrap_or_else(|| Const::new(self.interner, ConstKind::Error(ErrorGuaranteed))),
- hir_def::hir::Expr::Literal(literal) => {
- intern_const_ref(self.db, literal, const_type, self.resolver.krate())
- }
- hir_def::hir::Expr::UnaryOp { expr: inner_expr, op: hir_def::hir::UnaryOp::Neg } => {
- if let hir_def::hir::Expr::Literal(literal) = &self.store[*inner_expr] {
- // Only handle negation for signed integers and floats
- match literal {
- hir_def::hir::Literal::Int(_, _) | hir_def::hir::Literal::Float(_, _) => {
- if let Some(negated_literal) = literal.clone().negate() {
- intern_const_ref(
- self.db,
- &negated_literal,
- const_type,
- self.resolver.krate(),
- )
- } else {
- Const::new(self.interner, ConstKind::Error(ErrorGuaranteed))
- }
- }
- // For unsigned integers, chars, bools, etc., negation is not meaningful
- _ => Const::new(self.interner, ConstKind::Error(ErrorGuaranteed)),
- }
- } else {
- // Complex negation expression (e.g. `-N` where N is a const param)
- self.lower_const_as_unevaluated(expr_id, const_type)
- }
- }
- hir_def::hir::Expr::Underscore => {
- Const::new(self.interner, ConstKind::Error(ErrorGuaranteed))
- }
- // Any other complex expression becomes an unevaluated anonymous const.
- _ => self.lower_const_as_unevaluated(expr_id, const_type),
- }
- }
+ let konst = create_anon_const(
+ self.interner,
+ self.def,
+ self.store,
+ const_ref.expr,
+ self.resolver,
+ const_type,
+ &|| self.generics(),
+ None,
+ self.forbid_params_after,
+ );
- /// Lower a complex const expression to an `UnevaluatedConst` backed by an `AnonConstId`.
- ///
- /// The `expected_ty_ref` is `None` for array lengths (implicitly `usize`) or
- /// `Some(type_ref_id)` for const generic arguments where the expected type comes
- /// from the const parameter declaration.
- fn lower_const_as_unevaluated(
- &mut self,
- _expr: hir_def::hir::ExprId,
- _expected_ty: Ty<'db>,
- ) -> Const<'db> {
- // /// Build the identity generic args for the current generic context.
- // ///
- // /// This maps each generic parameter to itself (as a `ParamTy`, `ParamConst`,
- // /// or `EarlyParamRegion`), which is the correct substitution when creating
- // /// an `UnevaluatedConst` during type lowering — the anon const inherits the
- // /// parent's generics and they haven't been substituted yet.
- // fn current_generic_args(&self) -> GenericArgs<'db> {
- // let generics = self.generics();
- // let interner = self.interner;
- // GenericArgs::new_from_iter(
- // interner,
- // generics.iter_id().enumerate().map(|(index, id)| match id {
- // GenericParamId::TypeParamId(id) => {
- // GenericArg::from(Ty::new_param(interner, id, index as u32))
- // }
- // GenericParamId::ConstParamId(id) => GenericArg::from(Const::new_param(
- // interner,
- // ParamConst { id, index: index as u32 },
- // )),
- // GenericParamId::LifetimeParamId(id) => GenericArg::from(Region::new_early_param(
- // interner,
- // EarlyParamRegion { id, index: index as u32 },
- // )),
- // }),
- // )
- // }
- // let loc = AnonConstLoc { owner: self.def, expr };
- // let id = loc.intern(self.db);
- // let args = self.current_generic_args();
- // Const::new(
- // self.interner,
- // ConstKind::Unevaluated(UnevaluatedConst::new(
- // GeneralConstId::AnonConstId(id).into(),
- // args,
- // )),
- // )
- Const::new(self.interner, ConstKind::Error(ErrorGuaranteed))
- }
-
- pub(crate) fn path_to_const(&mut self, path: &Path) -> Option<Const<'db>> {
- match self.resolver.resolve_path_in_value_ns_fully(self.db, path, HygieneId::ROOT) {
- Some(ValueNs::GenericParam(p)) => {
- let args = self.generics();
- let idx = args.type_or_const_param_idx(p.into());
- Some(self.const_param(p, idx))
- }
- Some(ValueNs::ConstId(c)) => {
- let args = GenericArgs::empty(self.interner);
- Some(Const::new(
- self.interner,
- rustc_type_ir::ConstKind::Unevaluated(UnevaluatedConst::new(
- GeneralConstId::ConstId(c).into(),
- args,
- )),
- ))
- }
- _ => None,
+ if let Ok(konst) = konst
+ && let ConstKind::Unevaluated(konst) = konst.kind()
+ && let GeneralConstId::AnonConstId(konst) = konst.def.0
+ {
+ self.defined_anon_consts.push(konst);
}
+
+ konst.unwrap_or({
+ // FIXME: Report an error.
+ self.types.consts.error
+ })
}
- pub(crate) fn lower_path_as_const(&mut self, path: &Path, const_type: Ty<'db>) -> Const<'db> {
- self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type))
+ pub(crate) fn lower_path_as_const(&mut self, path: &Path, _const_type: Ty<'db>) -> Const<'db> {
+ path_to_const(self.db, self.resolver, &|| self.generics(), self.forbid_params_after, path)
+ .unwrap_or({
+ // FIXME: Report an error.
+ self.types.consts.error
+ })
}
fn generics(&self) -> &Generics<'db> {
- self.generics.get_or_init(|| generics(self.db, self.def))
+ self.generics.get_or_init(|| generics(self.db, self.generic_def))
}
fn param_index_is_disallowed(&self, index: u32) -> bool {
- self.lowering_param_default
- .is_some_and(|disallow_params_after| index >= disallow_params_after)
+ self.forbid_params_after.is_some_and(|disallow_params_after| index >= disallow_params_after)
}
fn type_param(&mut self, id: TypeParamId, index: u32) -> Ty<'db> {
@@ -414,15 +349,6 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
}
- fn const_param(&mut self, id: ConstParamId, index: u32) -> Const<'db> {
- if self.param_index_is_disallowed(index) {
- // FIXME: Report an error.
- Const::error(self.interner)
- } else {
- Const::new_param(self.interner, ParamConst { id, index })
- }
- }
-
fn region_param(&mut self, id: LifetimeParamId, index: u32) -> Region<'db> {
if self.param_index_is_disallowed(index) {
// FIXME: Report an error.
@@ -1091,6 +1017,69 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
}
+#[derive(Clone, PartialEq, Eq)]
+pub struct TyLoweringResult<T> {
+ pub value: T,
+ info: Option<Box<(ThinVec<TyLoweringDiagnostic>, ThinVec<AnonConstId>)>>,
+}
+
+impl<T: std::fmt::Debug> std::fmt::Debug for TyLoweringResult<T> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let mut debug = f.debug_struct("TyLoweringResult");
+ debug.field("value", &self.value);
+ let diagnostics = self.diagnostics();
+ if !diagnostics.is_empty() {
+ debug.field("diagnostics", &diagnostics);
+ }
+ let defined_anon_consts = self.defined_anon_consts();
+ if !defined_anon_consts.is_empty() {
+ debug.field("defined_anon_consts", &defined_anon_consts);
+ }
+ debug.finish()
+ }
+}
+
+impl<T> TyLoweringResult<T> {
+ fn new(
+ value: T,
+ mut diagnostics: ThinVec<TyLoweringDiagnostic>,
+ mut defined_anon_consts: ThinVec<AnonConstId>,
+ ) -> Self {
+ let info = if diagnostics.is_empty() && defined_anon_consts.is_empty() {
+ None
+ } else {
+ diagnostics.shrink_to_fit();
+ defined_anon_consts.shrink_to_fit();
+ Some(Box::new((diagnostics, defined_anon_consts)))
+ };
+ Self { value, info }
+ }
+
+ fn from_ctx(value: T, ctx: TyLoweringContext<'_, '_>) -> Self {
+ Self::new(value, ctx.diagnostics, ctx.defined_anon_consts)
+ }
+
+ fn empty(value: T) -> Self {
+ Self { value, info: None }
+ }
+
+ #[inline]
+ pub fn diagnostics(&self) -> &[TyLoweringDiagnostic] {
+ match &self.info {
+ Some(info) => &info.0,
+ None => &[],
+ }
+ }
+
+ #[inline]
+ pub fn defined_anon_consts(&self) -> &[AnonConstId] {
+ match &self.info {
+ Some(info) => &info.1,
+ None => &[],
+ }
+ }
+}
+
fn dyn_trait_dummy_self(interner: DbInterner<'_>) -> Ty<'_> {
// This type must not appear anywhere except here.
Ty::new_fresh(interner, 0)
@@ -1118,62 +1107,34 @@ pub(crate) fn lower_mutability(m: hir_def::type_ref::Mutability) -> Mutability {
}
}
-fn unknown_const(_ty: Ty<'_>) -> Const<'_> {
- Const::new(DbInterner::conjure(), ConstKind::Error(ErrorGuaranteed))
-}
-
-pub(crate) type Diagnostics = Option<ThinArc<(), TyLoweringDiagnostic>>;
-
-pub(crate) fn create_diagnostics(diagnostics: Vec<TyLoweringDiagnostic>) -> Diagnostics {
- (!diagnostics.is_empty()).then(|| ThinArc::from_header_and_iter((), diagnostics.into_iter()))
-}
-
pub(crate) fn impl_trait_query<'db>(
db: &'db dyn HirDatabase,
impl_id: ImplId,
) -> Option<EarlyBinder<'db, TraitRef<'db>>> {
- db.impl_trait_with_diagnostics(impl_id).map(|it| it.0)
+ impl_trait_with_diagnostics(db, impl_id)
+ .as_ref()
+ .map(|it| it.value.get(DbInterner::new_no_crate(db)))
}
-pub(crate) fn impl_trait_with_diagnostics<'db>(
- db: &'db dyn HirDatabase,
+#[salsa::tracked(returns(ref))]
+pub(crate) fn impl_trait_with_diagnostics(
+ db: &dyn HirDatabase,
impl_id: ImplId,
-) -> Option<(EarlyBinder<'db, TraitRef<'db>>, Diagnostics)> {
- return impl_trait_with_diagnostics_query(db, impl_id).as_ref().map(|(binder, diags)| {
- (
- binder.get_with(|(trait_id, args)| {
- TraitRef::new_from_args(
- DbInterner::new_no_crate(db),
- (*trait_id).into(),
- args.as_ref(),
- )
- }),
- diags.clone(),
- )
- });
-
- #[salsa::tracked(returns(ref))]
- pub(crate) fn impl_trait_with_diagnostics_query(
- db: &dyn HirDatabase,
- impl_id: ImplId,
- ) -> Option<(StoredEarlyBinder<(TraitId, StoredGenericArgs)>, Diagnostics)> {
- let impl_data = ImplSignature::of(db, impl_id);
- let resolver = impl_id.resolver(db);
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- &impl_data.store,
- impl_id.into(),
- LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
- );
- let self_ty = db.impl_self_ty(impl_id).skip_binder();
- let target_trait = impl_data.target_trait.as_ref()?;
- let trait_ref = ctx.lower_trait_ref(target_trait, self_ty)?;
- Some((
- StoredEarlyBinder::bind((trait_ref.def_id.0, trait_ref.args.store())),
- create_diagnostics(ctx.diagnostics),
- ))
- }
+) -> Option<TyLoweringResult<StoredEarlyBinder<StoredTraitRef>>> {
+ let impl_data = ImplSignature::of(db, impl_id);
+ let resolver = impl_id.resolver(db);
+ let mut ctx = TyLoweringContext::new(
+ db,
+ &resolver,
+ &impl_data.store,
+ ExpressionStoreOwnerId::Signature(impl_id.into()),
+ impl_id.into(),
+ LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
+ );
+ let self_ty = db.impl_self_ty(impl_id).skip_binder();
+ let target_trait = impl_data.target_trait.as_ref()?;
+ let trait_ref = ctx.lower_trait_ref(target_trait, self_ty)?;
+ Some(TyLoweringResult::from_ctx(StoredEarlyBinder::bind(StoredTraitRef::new(trait_ref)), ctx))
}
impl ImplTraitId {
@@ -1248,6 +1209,7 @@ impl ImplTraits {
db,
&resolver,
&data.store,
+ ExpressionStoreOwnerId::Signature(def.into()),
def.into(),
LifetimeElisionKind::Infer,
)
@@ -1276,6 +1238,7 @@ impl ImplTraits {
db,
&resolver,
&data.store,
+ ExpressionStoreOwnerId::Signature(def.into()),
def.into(),
LifetimeElisionKind::AnonymousReportError,
)
@@ -1339,26 +1302,34 @@ pub(crate) fn ty_query<'db>(db: &'db dyn HirDatabase, def: TyDefId) -> EarlyBind
it,
GenericArgs::identity_for_item(interner, it.into()),
)),
- TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).0,
+ TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).value.get(),
}
}
/// Build the declared type of a function. This should not need to look at the
/// function body.
-fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> StoredEarlyBinder<StoredTy> {
+fn type_for_fn<'db>(db: &'db dyn HirDatabase, def: FunctionId) -> EarlyBinder<'db, Ty<'db>> {
let interner = DbInterner::new_no_crate(db);
- StoredEarlyBinder::bind(
- Ty::new_fn_def(
- interner,
- CallableDefId::FunctionId(def).into(),
- GenericArgs::identity_for_item(interner, def.into()),
- )
- .store(),
- )
+ EarlyBinder::bind(Ty::new_fn_def(
+ interner,
+ CallableDefId::FunctionId(def).into(),
+ GenericArgs::identity_for_item(interner, def.into()),
+ ))
+}
+
+pub(crate) fn type_for_const<'db>(
+ db: &'db dyn HirDatabase,
+ def: ConstId,
+) -> EarlyBinder<'db, Ty<'db>> {
+ type_for_const_with_diagnostics(db, def).value.get()
}
/// Build the declared type of a const.
-fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> StoredEarlyBinder<StoredTy> {
+#[salsa_macros::tracked(returns(ref))]
+pub(crate) fn type_for_const_with_diagnostics(
+ db: &dyn HirDatabase,
+ def: ConstId,
+) -> TyLoweringResult<StoredEarlyBinder<StoredTy>> {
let resolver = def.resolver(db);
let data = ConstSignature::of(db, def);
let parent = def.loc(db).container;
@@ -1366,70 +1337,79 @@ fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> StoredEarlyBinder<Store
db,
&resolver,
&data.store,
+ ExpressionStoreOwnerId::Signature(def.into()),
def.into(),
LifetimeElisionKind::AnonymousReportError,
);
ctx.set_lifetime_elision(LifetimeElisionKind::for_const(ctx.interner, parent));
- StoredEarlyBinder::bind(ctx.lower_ty(data.type_ref).store())
+ let result = StoredEarlyBinder::bind(ctx.lower_ty(data.type_ref).store());
+ TyLoweringResult::from_ctx(result, ctx)
+}
+
+pub(crate) fn type_for_static<'db>(
+ db: &'db dyn HirDatabase,
+ def: StaticId,
+) -> EarlyBinder<'db, Ty<'db>> {
+ type_for_static_with_diagnostics(db, def).value.get()
}
/// Build the declared type of a static.
-fn type_for_static(db: &dyn HirDatabase, def: StaticId) -> StoredEarlyBinder<StoredTy> {
+#[salsa_macros::tracked(returns(ref))]
+pub(crate) fn type_for_static_with_diagnostics(
+ db: &dyn HirDatabase,
+ def: StaticId,
+) -> TyLoweringResult<StoredEarlyBinder<StoredTy>> {
let resolver = def.resolver(db);
let data = StaticSignature::of(db, def);
let mut ctx = TyLoweringContext::new(
db,
&resolver,
&data.store,
+ ExpressionStoreOwnerId::Signature(def.into()),
def.into(),
LifetimeElisionKind::AnonymousReportError,
);
ctx.set_lifetime_elision(LifetimeElisionKind::Elided(Region::new_static(ctx.interner)));
- StoredEarlyBinder::bind(ctx.lower_ty(data.type_ref).store())
+ let result = StoredEarlyBinder::bind(ctx.lower_ty(data.type_ref).store());
+ TyLoweringResult::from_ctx(result, ctx)
}
/// Build the type of a tuple struct constructor.
-fn type_for_struct_constructor(
- db: &dyn HirDatabase,
+fn type_for_struct_constructor<'db>(
+ db: &'db dyn HirDatabase,
def: StructId,
-) -> Option<StoredEarlyBinder<StoredTy>> {
+) -> Option<EarlyBinder<'db, Ty<'db>>> {
let struct_data = StructSignature::of(db, def);
match struct_data.shape {
FieldsShape::Record => None,
FieldsShape::Unit => Some(type_for_adt(db, def.into())),
FieldsShape::Tuple => {
let interner = DbInterner::new_no_crate(db);
- Some(StoredEarlyBinder::bind(
- Ty::new_fn_def(
- interner,
- CallableDefId::StructId(def).into(),
- GenericArgs::identity_for_item(interner, def.into()),
- )
- .store(),
- ))
+ Some(EarlyBinder::bind(Ty::new_fn_def(
+ interner,
+ CallableDefId::StructId(def).into(),
+ GenericArgs::identity_for_item(interner, def.into()),
+ )))
}
}
}
/// Build the type of a tuple enum variant constructor.
-fn type_for_enum_variant_constructor(
- db: &dyn HirDatabase,
+fn type_for_enum_variant_constructor<'db>(
+ db: &'db dyn HirDatabase,
def: EnumVariantId,
-) -> Option<StoredEarlyBinder<StoredTy>> {
+) -> Option<EarlyBinder<'db, Ty<'db>>> {
let struct_data = def.fields(db);
match struct_data.shape {
FieldsShape::Record => None,
FieldsShape::Unit => Some(type_for_adt(db, def.loc(db).parent.into())),
FieldsShape::Tuple => {
let interner = DbInterner::new_no_crate(db);
- Some(StoredEarlyBinder::bind(
- Ty::new_fn_def(
- interner,
- CallableDefId::EnumVariantId(def).into(),
- GenericArgs::identity_for_item(interner, def.loc(db).parent.into()),
- )
- .store(),
- ))
+ Some(EarlyBinder::bind(Ty::new_fn_def(
+ interner,
+ CallableDefId::EnumVariantId(def).into(),
+ GenericArgs::identity_for_item(interner, def.loc(db).parent.into()),
+ )))
}
}
}
@@ -1438,197 +1418,166 @@ pub(crate) fn value_ty<'db>(
db: &'db dyn HirDatabase,
def: ValueTyDefId,
) -> Option<EarlyBinder<'db, Ty<'db>>> {
- return value_ty_query(db, def).as_ref().map(|it| it.get());
-
- #[salsa::tracked(returns(ref))]
- pub(crate) fn value_ty_query(
- db: &dyn HirDatabase,
- def: ValueTyDefId,
- ) -> Option<StoredEarlyBinder<StoredTy>> {
- match def {
- ValueTyDefId::FunctionId(it) => Some(type_for_fn(db, it)),
- ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it),
- ValueTyDefId::UnionId(it) => Some(type_for_adt(db, it.into())),
- ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it),
- ValueTyDefId::ConstId(it) => Some(type_for_const(db, it)),
- ValueTyDefId::StaticId(it) => Some(type_for_static(db, it)),
- }
+ match def {
+ ValueTyDefId::FunctionId(it) => Some(type_for_fn(db, it)),
+ ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it),
+ ValueTyDefId::UnionId(it) => Some(type_for_adt(db, it.into())),
+ ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it),
+ ValueTyDefId::ConstId(it) => Some(type_for_const(db, it)),
+ ValueTyDefId::StaticId(it) => Some(type_for_static(db, it)),
}
}
-pub(crate) fn type_for_type_alias_with_diagnostics<'db>(
- db: &'db dyn HirDatabase,
+#[salsa::tracked(returns(ref), cycle_result = type_for_type_alias_with_diagnostics_cycle_result)]
+pub(crate) fn type_for_type_alias_with_diagnostics(
+ db: &dyn HirDatabase,
t: TypeAliasId,
-) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) {
- let (ty, diags) = type_for_type_alias_with_diagnostics_query(db, t);
- return (ty.get(), diags.clone());
-
- #[salsa::tracked(returns(ref), cycle_result = type_for_type_alias_with_diagnostics_cycle_result)]
- pub(crate) fn type_for_type_alias_with_diagnostics_query(
- db: &dyn HirDatabase,
- t: TypeAliasId,
- ) -> (StoredEarlyBinder<StoredTy>, Diagnostics) {
- let type_alias_data = TypeAliasSignature::of(db, t);
- let mut diags = None;
- let resolver = t.resolver(db);
- let interner = DbInterner::new_no_crate(db);
- let inner = if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) {
- StoredEarlyBinder::bind(Ty::new_foreign(interner, t.into()).store())
- } else {
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- &type_alias_data.store,
- t.into(),
- LifetimeElisionKind::AnonymousReportError,
- )
- .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
- let res = StoredEarlyBinder::bind(
- type_alias_data
- .ty
- .map(|type_ref| ctx.lower_ty(type_ref))
- .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed))
- .store(),
- );
- diags = create_diagnostics(ctx.diagnostics);
- res
- };
- (inner, diags)
- }
-
- pub(crate) fn type_for_type_alias_with_diagnostics_cycle_result(
- db: &dyn HirDatabase,
- _: salsa::Id,
- _adt: TypeAliasId,
- ) -> (StoredEarlyBinder<StoredTy>, Diagnostics) {
- (
- StoredEarlyBinder::bind(
- Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed).store(),
- ),
- None,
+) -> TyLoweringResult<StoredEarlyBinder<StoredTy>> {
+ let type_alias_data = TypeAliasSignature::of(db, t);
+ let resolver = t.resolver(db);
+ let interner = DbInterner::new_no_crate(db);
+ if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) {
+ TyLoweringResult::empty(StoredEarlyBinder::bind(
+ Ty::new_foreign(interner, t.into()).store(),
+ ))
+ } else {
+ let mut ctx = TyLoweringContext::new(
+ db,
+ &resolver,
+ &type_alias_data.store,
+ ExpressionStoreOwnerId::Signature(t.into()),
+ t.into(),
+ LifetimeElisionKind::AnonymousReportError,
)
+ .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
+ let res = StoredEarlyBinder::bind(
+ type_alias_data
+ .ty
+ .map(|type_ref| ctx.lower_ty(type_ref))
+ .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed))
+ .store(),
+ );
+ TyLoweringResult::from_ctx(res, ctx)
}
}
+pub(crate) fn type_for_type_alias_with_diagnostics_cycle_result(
+ db: &dyn HirDatabase,
+ _: salsa::Id,
+ _adt: TypeAliasId,
+) -> TyLoweringResult<StoredEarlyBinder<StoredTy>> {
+ TyLoweringResult::empty(StoredEarlyBinder::bind(
+ Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed).store(),
+ ))
+}
+
pub(crate) fn impl_self_ty_query<'db>(
db: &'db dyn HirDatabase,
impl_id: ImplId,
) -> EarlyBinder<'db, Ty<'db>> {
- db.impl_self_ty_with_diagnostics(impl_id).0
+ impl_self_ty_with_diagnostics(db, impl_id).value.get()
}
-pub(crate) fn impl_self_ty_with_diagnostics<'db>(
- db: &'db dyn HirDatabase,
+#[salsa::tracked(returns(ref), cycle_result = impl_self_ty_with_diagnostics_cycle_result)]
+pub(crate) fn impl_self_ty_with_diagnostics(
+ db: &dyn HirDatabase,
impl_id: ImplId,
-) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) {
- let (ty, diags) = impl_self_ty_with_diagnostics_query(db, impl_id);
- return (ty.get(), diags.clone());
+) -> TyLoweringResult<StoredEarlyBinder<StoredTy>> {
+ let resolver = impl_id.resolver(db);
- #[salsa::tracked(returns(ref), cycle_result = impl_self_ty_with_diagnostics_cycle_result)]
- pub(crate) fn impl_self_ty_with_diagnostics_query(
- db: &dyn HirDatabase,
- impl_id: ImplId,
- ) -> (StoredEarlyBinder<StoredTy>, Diagnostics) {
- let resolver = impl_id.resolver(db);
+ let impl_data = ImplSignature::of(db, impl_id);
+ let mut ctx = TyLoweringContext::new(
+ db,
+ &resolver,
+ &impl_data.store,
+ ExpressionStoreOwnerId::Signature(impl_id.into()),
+ impl_id.into(),
+ LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
+ );
+ let ty = ctx.lower_ty(impl_data.self_ty);
+ assert!(!ty.has_escaping_bound_vars());
+ TyLoweringResult::from_ctx(StoredEarlyBinder::bind(ty.store()), ctx)
+}
- let impl_data = ImplSignature::of(db, impl_id);
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- &impl_data.store,
- impl_id.into(),
- LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
- );
- let ty = ctx.lower_ty(impl_data.self_ty);
- assert!(!ty.has_escaping_bound_vars());
- (StoredEarlyBinder::bind(ty.store()), create_diagnostics(ctx.diagnostics))
- }
+pub(crate) fn impl_self_ty_with_diagnostics_cycle_result(
+ db: &dyn HirDatabase,
+ _: salsa::Id,
+ _impl_id: ImplId,
+) -> TyLoweringResult<StoredEarlyBinder<StoredTy>> {
+ TyLoweringResult::empty(StoredEarlyBinder::bind(
+ Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed).store(),
+ ))
+}
- pub(crate) fn impl_self_ty_with_diagnostics_cycle_result(
- db: &dyn HirDatabase,
- _: salsa::Id,
- _impl_id: ImplId,
- ) -> (StoredEarlyBinder<StoredTy>, Diagnostics) {
- (
- StoredEarlyBinder::bind(
- Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed).store(),
- ),
- None,
- )
+pub(crate) fn const_param_ty<'db>(db: &'db dyn HirDatabase, def: ConstParamId) -> Ty<'db> {
+ let param_types = const_param_types(db, def.parent());
+ match param_types.get(def.local_id()) {
+ Some(ty) => ty.as_ref(),
+ None => Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed),
}
}
-pub(crate) fn const_param_ty_query<'db>(db: &'db dyn HirDatabase, def: ConstParamId) -> Ty<'db> {
- db.const_param_ty_with_diagnostics(def).0
+pub(crate) fn const_param_types(
+ db: &dyn HirDatabase,
+ def: GenericDefId,
+) -> &ArenaMap<LocalTypeOrConstParamId, StoredTy> {
+ &const_param_types_with_diagnostics(db, def).value
}
-// returns None if def is a type arg
-pub(crate) fn const_param_ty_with_diagnostics<'db>(
- db: &'db dyn HirDatabase,
- def: ConstParamId,
-) -> (Ty<'db>, Diagnostics) {
- let (ty, diags) = const_param_ty_with_diagnostics_query(db, (), def);
- return (ty.as_ref(), diags.clone());
-
- // FIXME: Make this query non-interned.
- #[salsa::tracked(returns(ref), cycle_result = const_param_ty_with_diagnostics_cycle_result)]
- pub(crate) fn const_param_ty_with_diagnostics_query(
- db: &dyn HirDatabase,
- _: (),
- def: ConstParamId,
- ) -> (StoredTy, Diagnostics) {
- let (parent_data, store) = GenericParams::with_store(db, def.parent());
- let data = &parent_data[def.local_id()];
- let resolver = def.parent().resolver(db);
- let interner = DbInterner::new_no_crate(db);
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- store,
- def.parent(),
- LifetimeElisionKind::AnonymousReportError,
- );
- let ty = match data {
- TypeOrConstParamData::TypeParamData(_) => {
- never!();
- Ty::new_error(interner, ErrorGuaranteed)
- }
- TypeOrConstParamData::ConstParamData(d) => ctx.lower_ty(d.ty),
- };
- (ty.store(), create_diagnostics(ctx.diagnostics))
+#[salsa::tracked(returns(ref), cycle_result = const_param_types_with_diagnostics_cycle_result)]
+pub(crate) fn const_param_types_with_diagnostics(
+ db: &dyn HirDatabase,
+ def: GenericDefId,
+) -> TyLoweringResult<ArenaMap<LocalTypeOrConstParamId, StoredTy>> {
+ let mut result = ArenaMap::new();
+ let (data, store) = GenericParams::with_store(db, def);
+ let resolver = def.resolver(db);
+ let mut ctx = TyLoweringContext::new(
+ db,
+ &resolver,
+ store,
+ ExpressionStoreOwnerId::Signature(def),
+ def,
+ LifetimeElisionKind::AnonymousReportError,
+ );
+ ctx.forbid_params_after(0, ForbidParamsAfterReason::ConstParamTy);
+ for (local_id, param_data) in data.iter_type_or_consts() {
+ if let TypeOrConstParamData::ConstParamData(param_data) = param_data {
+ result.insert(local_id, ctx.lower_ty(param_data.ty).store());
+ }
}
+ result.shrink_to_fit();
+ TyLoweringResult::from_ctx(result, ctx)
+}
- pub(crate) fn const_param_ty_with_diagnostics_cycle_result(
- db: &dyn HirDatabase,
- _: salsa::Id,
- _: (),
- _def: ConstParamId,
- ) -> (StoredTy, Diagnostics) {
- let interner = DbInterner::new_no_crate(db);
- (Ty::new_error(interner, ErrorGuaranteed).store(), None)
- }
+fn const_param_types_with_diagnostics_cycle_result(
+ _db: &dyn HirDatabase,
+ _: salsa::Id,
+ _def: GenericDefId,
+) -> TyLoweringResult<ArenaMap<LocalTypeOrConstParamId, StoredTy>> {
+ TyLoweringResult::empty(ArenaMap::default())
}
pub(crate) fn field_types_query(
db: &dyn HirDatabase,
variant_id: VariantId,
) -> &ArenaMap<LocalFieldId, StoredEarlyBinder<StoredTy>> {
- &db.field_types_with_diagnostics(variant_id).0
+ &field_types_with_diagnostics(db, variant_id).value
}
/// Build the type of all specific fields of a struct or enum variant.
#[salsa::tracked(returns(ref))]
-pub(crate) fn field_types_with_diagnostics_query(
+pub(crate) fn field_types_with_diagnostics(
db: &dyn HirDatabase,
variant_id: VariantId,
-) -> (ArenaMap<LocalFieldId, StoredEarlyBinder<StoredTy>>, Diagnostics) {
+) -> TyLoweringResult<ArenaMap<LocalFieldId, StoredEarlyBinder<StoredTy>>> {
let var_data = variant_id.fields(db);
let fields = var_data.fields();
if fields.is_empty() {
- return (ArenaMap::default(), None);
+ return TyLoweringResult::empty(ArenaMap::default());
}
- let (resolver, def): (_, GenericDefId) = match variant_id {
+ let (resolver, generic_def): (_, GenericDefId) = match variant_id {
VariantId::StructId(it) => (it.resolver(db), it.into()),
VariantId::UnionId(it) => (it.resolver(db), it.into()),
VariantId::EnumVariantId(it) => (it.resolver(db), it.lookup(db).parent.into()),
@@ -1638,13 +1587,14 @@ pub(crate) fn field_types_with_diagnostics_query(
db,
&resolver,
&var_data.store,
- def,
+ ExpressionStoreOwnerId::VariantFields(variant_id),
+ generic_def,
LifetimeElisionKind::AnonymousReportError,
);
for (field_id, field_data) in var_data.fields().iter() {
res.insert(field_id, StoredEarlyBinder::bind(ctx.lower_ty(field_data.type_ref).store()));
}
- (res, create_diagnostics(ctx.diagnostics))
+ TyLoweringResult::from_ctx(res, ctx)
}
#[derive(Debug, PartialEq, Eq, Default)]
@@ -1766,6 +1716,7 @@ fn resolve_type_param_assoc_type_shorthand(
db,
&resolver,
generics.store(),
+ ExpressionStoreOwnerId::Signature(def),
def,
LifetimeElisionKind::AnonymousReportError,
);
@@ -1906,7 +1857,11 @@ pub(crate) fn type_alias_bounds<'db>(
db: &'db dyn HirDatabase,
type_alias: TypeAliasId,
) -> EarlyBinder<'db, &'db [Clause<'db>]> {
- type_alias_bounds_with_diagnostics(db, type_alias).0.predicates.map_bound(|it| it.as_slice())
+ type_alias_bounds_with_diagnostics(db, type_alias)
+ .value
+ .predicates
+ .get()
+ .map_bound(|it| it.as_slice())
}
#[inline]
@@ -1914,89 +1869,73 @@ pub(crate) fn type_alias_self_bounds<'db>(
db: &'db dyn HirDatabase,
type_alias: TypeAliasId,
) -> EarlyBinder<'db, &'db [Clause<'db>]> {
- let (TypeAliasBounds { predicates, assoc_ty_bounds_start }, _) =
- type_alias_bounds_with_diagnostics(db, type_alias);
- predicates.map_bound(|it| &it.as_slice()[..assoc_ty_bounds_start as usize])
+ let TypeAliasBounds { predicates, assoc_ty_bounds_start } =
+ &type_alias_bounds_with_diagnostics(db, type_alias).value;
+ predicates.get().map_bound(|it| &it.as_slice()[..*assoc_ty_bounds_start as usize])
}
#[derive(PartialEq, Eq, Debug, Hash)]
-struct TypeAliasBounds<T> {
+pub struct TypeAliasBounds<T> {
predicates: T,
assoc_ty_bounds_start: u32,
}
-fn type_alias_bounds_with_diagnostics<'db>(
- db: &'db dyn HirDatabase,
+#[salsa::tracked(returns(ref))]
+pub(crate) fn type_alias_bounds_with_diagnostics(
+ db: &dyn HirDatabase,
type_alias: TypeAliasId,
-) -> (TypeAliasBounds<EarlyBinder<'db, Clauses<'db>>>, Diagnostics) {
- let (TypeAliasBounds { predicates, assoc_ty_bounds_start }, diags) =
- type_alias_bounds_with_diagnostics_query(db, type_alias);
- return (
- TypeAliasBounds {
- predicates: predicates.get(),
- assoc_ty_bounds_start: *assoc_ty_bounds_start,
- },
- diags.clone(),
+) -> TyLoweringResult<TypeAliasBounds<StoredEarlyBinder<StoredClauses>>> {
+ let type_alias_data = TypeAliasSignature::of(db, type_alias);
+ let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db);
+ let mut ctx = TyLoweringContext::new(
+ db,
+ &resolver,
+ &type_alias_data.store,
+ ExpressionStoreOwnerId::Signature(type_alias.into()),
+ type_alias.into(),
+ LifetimeElisionKind::AnonymousReportError,
);
+ let interner = ctx.interner;
+ let def_id = type_alias.into();
- #[salsa::tracked(returns(ref))]
- pub fn type_alias_bounds_with_diagnostics_query(
- db: &dyn HirDatabase,
- type_alias: TypeAliasId,
- ) -> (TypeAliasBounds<StoredEarlyBinder<StoredClauses>>, Diagnostics) {
- let type_alias_data = TypeAliasSignature::of(db, type_alias);
- let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db);
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- &type_alias_data.store,
- type_alias.into(),
- LifetimeElisionKind::AnonymousReportError,
- );
- let interner = ctx.interner;
- let def_id = type_alias.into();
+ let item_args = GenericArgs::identity_for_item(interner, def_id);
+ let interner_ty = Ty::new_projection_from_args(interner, def_id, item_args);
- let item_args = GenericArgs::identity_for_item(interner, def_id);
- let interner_ty = Ty::new_projection_from_args(interner, def_id, item_args);
+ let mut bounds = Vec::new();
+ let mut assoc_ty_bounds = Vec::new();
+ for bound in &type_alias_data.bounds {
+ ctx.lower_type_bound(bound, interner_ty, false).for_each(|(pred, source)| match source {
+ GenericPredicateSource::SelfOnly => {
+ bounds.push(pred);
+ }
+ GenericPredicateSource::AssocTyBound => {
+ assoc_ty_bounds.push(pred);
+ }
+ });
+ }
- let mut bounds = Vec::new();
- let mut assoc_ty_bounds = Vec::new();
- for bound in &type_alias_data.bounds {
- ctx.lower_type_bound(bound, interner_ty, false).for_each(
- |(pred, source)| match source {
- GenericPredicateSource::SelfOnly => {
- bounds.push(pred);
- }
- GenericPredicateSource::AssocTyBound => {
- assoc_ty_bounds.push(pred);
- }
- },
+ if !ctx.unsized_types.contains(&interner_ty) {
+ let sized_trait = ctx.lang_items.Sized;
+ if let Some(sized_trait) = sized_trait {
+ let trait_ref = TraitRef::new_from_args(
+ interner,
+ sized_trait.into(),
+ GenericArgs::new_from_slice(&[interner_ty.into()]),
);
- }
-
- if !ctx.unsized_types.contains(&interner_ty) {
- let sized_trait = ctx.lang_items.Sized;
- if let Some(sized_trait) = sized_trait {
- let trait_ref = TraitRef::new_from_args(
- interner,
- sized_trait.into(),
- GenericArgs::new_from_slice(&[interner_ty.into()]),
- );
- bounds.push(trait_ref.upcast(interner));
- };
- }
+ bounds.push(trait_ref.upcast(interner));
+ };
+ }
- let assoc_ty_bounds_start = bounds.len() as u32;
- bounds.extend(assoc_ty_bounds);
+ let assoc_ty_bounds_start = bounds.len() as u32;
+ bounds.extend(assoc_ty_bounds);
- (
- TypeAliasBounds {
- predicates: StoredEarlyBinder::bind(Clauses::new_from_slice(&bounds).store()),
- assoc_ty_bounds_start,
- },
- create_diagnostics(ctx.diagnostics),
- )
- }
+ TyLoweringResult::from_ctx(
+ TypeAliasBounds {
+ predicates: StoredEarlyBinder::bind(Clauses::new_from_slice(&bounds).store()),
+ assoc_ty_bounds_start,
+ },
+ ctx,
+ )
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -2027,7 +1966,7 @@ impl<'db> GenericPredicates {
pub fn query_with_diagnostics(
db: &'db dyn HirDatabase,
def: GenericDefId,
- ) -> (GenericPredicates, Diagnostics) {
+ ) -> TyLoweringResult<GenericPredicates> {
generic_predicates(db, def)
}
}
@@ -2037,17 +1976,26 @@ fn generic_predicates_cycle_result(
_db: &dyn HirDatabase,
_: salsa::Id,
_def: GenericDefId,
-) -> (GenericPredicates, Diagnostics) {
- (
- GenericPredicates::from_explicit_own_predicates(StoredEarlyBinder::bind(
- Clauses::default().store(),
- )),
- None,
- )
+) -> TyLoweringResult<GenericPredicates> {
+ TyLoweringResult::empty(GenericPredicates::from_explicit_own_predicates(
+ StoredEarlyBinder::bind(Clauses::default().store()),
+ ))
}
impl GenericPredicates {
#[inline]
+ pub fn empty() -> &'static GenericPredicates {
+ static EMPTY: OnceLock<GenericPredicates> = OnceLock::new();
+ EMPTY.get_or_init(|| GenericPredicates {
+ predicates: StoredEarlyBinder::bind(Clauses::default().store()),
+ has_trait_implied_predicate: false,
+ parent_explicit_self_predicates_start: 0,
+ own_predicates_start: 0,
+ own_assoc_ty_bounds_start: 0,
+ })
+ }
+
+ #[inline]
pub(crate) fn from_explicit_own_predicates(
predicates: StoredEarlyBinder<StoredClauses>,
) -> Self {
@@ -2063,7 +2011,7 @@ impl GenericPredicates {
#[inline]
pub fn query(db: &dyn HirDatabase, def: GenericDefId) -> &GenericPredicates {
- &Self::query_with_diagnostics(db, def).0
+ &Self::query_with_diagnostics(db, def).value
}
#[inline]
@@ -2171,7 +2119,10 @@ pub(crate) fn trait_environment<'db>(
/// Resolve the where clause(s) of an item with generics,
/// with a given filter
#[tracing::instrument(skip(db), ret)]
-fn generic_predicates(db: &dyn HirDatabase, def: GenericDefId) -> (GenericPredicates, Diagnostics) {
+fn generic_predicates(
+ db: &dyn HirDatabase,
+ def: GenericDefId,
+) -> TyLoweringResult<GenericPredicates> {
let generics = generics(db, def);
let resolver = def.resolver(db);
let interner = DbInterner::new_no_crate(db);
@@ -2179,6 +2130,7 @@ fn generic_predicates(db: &dyn HirDatabase, def: GenericDefId) -> (GenericPredic
db,
&resolver,
generics.store(),
+ ExpressionStoreOwnerId::Signature(def),
def,
LifetimeElisionKind::AnonymousReportError,
);
@@ -2278,7 +2230,8 @@ fn generic_predicates(db: &dyn HirDatabase, def: GenericDefId) -> (GenericPredic
// But we do have to lower the parent first.
}
- let diagnostics = create_diagnostics(ctx.diagnostics);
+ let diagnostics = mem::take(&mut ctx.diagnostics);
+ let defined_anon_consts = mem::take(&mut ctx.defined_anon_consts);
let predicates = parent_implicit_trait_predicate
.iter()
@@ -2304,7 +2257,7 @@ fn generic_predicates(db: &dyn HirDatabase, def: GenericDefId) -> (GenericPredic
own_assoc_ty_bounds_start,
predicates: StoredEarlyBinder::bind(Clauses::new_from_slice(&predicates).store()),
};
- return (predicates, diagnostics);
+ return TyLoweringResult::new(predicates, diagnostics, defined_anon_consts);
fn implicit_trait_predicate<'db>(
interner: DbInterner<'db>,
@@ -2349,29 +2302,40 @@ fn push_const_arg_has_type_predicates<'db>(
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct GenericDefaults(Option<Arc<[Option<StoredEarlyBinder<StoredGenericArg>>]>>);
+pub struct GenericDefaults(ThinVec<Option<StoredEarlyBinder<StoredGenericArg>>>);
impl GenericDefaults {
#[inline]
- pub fn get<'db>(&self, idx: usize) -> Option<EarlyBinder<'db, GenericArg<'db>>> {
- Some(self.0.as_ref()?[idx].as_ref()?.get_with(|it| it.as_ref()))
+ pub fn as_ref(&self) -> GenericDefaultsRef<'_> {
+ GenericDefaultsRef(&self.0)
+ }
+}
+
+#[derive(Debug, Clone, Copy)]
+pub struct GenericDefaultsRef<'db>(&'db [Option<StoredEarlyBinder<StoredGenericArg>>]);
+
+impl<'db> GenericDefaultsRef<'db> {
+ #[inline]
+ pub fn get(self, idx: usize) -> Option<EarlyBinder<'db, GenericArg<'db>>> {
+ Some(self.0.get(idx)?.as_ref()?.get())
}
}
-pub(crate) fn generic_defaults_query(db: &dyn HirDatabase, def: GenericDefId) -> GenericDefaults {
- db.generic_defaults_with_diagnostics(def).0
+pub(crate) fn generic_defaults(db: &dyn HirDatabase, def: GenericDefId) -> GenericDefaultsRef<'_> {
+ generic_defaults_with_diagnostics(db, def).value.as_ref()
}
/// Resolve the default type params from generics.
///
/// Diagnostics are only returned for this `GenericDefId` (returned defaults include parents).
-pub(crate) fn generic_defaults_with_diagnostics_query(
+#[salsa_macros::tracked(returns(ref), cycle_result = generic_defaults_with_diagnostics_cycle_result)]
+pub(crate) fn generic_defaults_with_diagnostics(
db: &dyn HirDatabase,
def: GenericDefId,
-) -> (GenericDefaults, Diagnostics) {
+) -> TyLoweringResult<GenericDefaults> {
let generic_params = generics(db, def);
if generic_params.has_no_params() {
- return (GenericDefaults(None), None);
+ return TyLoweringResult::empty(GenericDefaults(ThinVec::new()));
}
let resolver = def.resolver(db);
@@ -2380,48 +2344,39 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
db,
&resolver,
store_for_self,
+ ExpressionStoreOwnerId::Signature(def),
def,
LifetimeElisionKind::AnonymousReportError,
)
.with_impl_trait_mode(ImplTraitLoweringMode::Disallowed);
- let mut has_any_default = false;
- let mut defaults = Vec::new();
+ let mut defaults = ThinVec::new();
if let Some(parent) = generic_params.parent() {
ctx.store = parent.store();
- defaults.extend(parent.iter_with_idx().map(|(idx, _id, p)| {
- let (result, has_default) = handle_generic_param(&mut ctx, idx, p);
- has_any_default |= has_default;
- result
- }));
+ defaults.extend(
+ parent.iter_with_idx().map(|(idx, _id, p)| handle_generic_param(&mut ctx, idx, p)),
+ );
}
ctx.diagnostics.clear(); // Don't include diagnostics from the parent.
+ ctx.defined_anon_consts.clear();
ctx.store = store_for_self;
- defaults.extend(generic_params.iter_self_with_idx().map(|(idx, _id, p)| {
- let (result, has_default) = handle_generic_param(&mut ctx, idx, p);
- has_any_default |= has_default;
- result
- }));
- let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics));
- let defaults = if has_any_default {
- GenericDefaults(Some(Arc::from_iter(defaults)))
- } else {
- GenericDefaults(None)
- };
- return (defaults, diagnostics);
+ defaults.extend(
+ generic_params
+ .iter_self_with_idx()
+ .map(|(idx, _id, p)| handle_generic_param(&mut ctx, idx, p)),
+ );
+ defaults.shrink_to_fit();
+ return TyLoweringResult::from_ctx(GenericDefaults(defaults), ctx);
fn handle_generic_param<'db>(
ctx: &mut TyLoweringContext<'db, '_>,
idx: u32,
p: GenericParamDataRef<'_>,
- ) -> (Option<StoredEarlyBinder<StoredGenericArg>>, bool) {
- ctx.lowering_param_default(idx);
+ ) -> Option<StoredEarlyBinder<StoredGenericArg>> {
+ ctx.forbid_params_after(idx, ForbidParamsAfterReason::LoweringParamDefault);
match p {
GenericParamDataRef::TypeParamData(p) => {
let ty = p.default.map(|ty| ctx.lower_ty(ty));
- (
- ty.map(|ty| StoredEarlyBinder::bind(GenericArg::from(ty).store())),
- p.default.is_some(),
- )
+ ty.map(|ty| StoredEarlyBinder::bind(GenericArg::from(ty).store()))
}
GenericParamDataRef::ConstParamData(p) => {
let val = p.default.map(|c| {
@@ -2429,19 +2384,19 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
let c = ctx.lower_const(c, param_ty);
GenericArg::from(c).store()
});
- (val.map(StoredEarlyBinder::bind), p.default.is_some())
+ val.map(StoredEarlyBinder::bind)
}
- GenericParamDataRef::LifetimeParamData(_) => (None, false),
+ GenericParamDataRef::LifetimeParamData(_) => None,
}
}
}
-pub(crate) fn generic_defaults_with_diagnostics_cycle_result(
+fn generic_defaults_with_diagnostics_cycle_result(
_db: &dyn HirDatabase,
_: salsa::Id,
_def: GenericDefId,
-) -> (GenericDefaults, Diagnostics) {
- (GenericDefaults(None), None)
+) -> TyLoweringResult<GenericDefaults> {
+ TyLoweringResult::empty(GenericDefaults(ThinVec::new()))
}
/// Build the signature of a callable item (function, struct or enum variant).
@@ -2449,22 +2404,27 @@ pub(crate) fn callable_item_signature<'db>(
db: &'db dyn HirDatabase,
def: CallableDefId,
) -> EarlyBinder<'db, PolyFnSig<'db>> {
- return callable_item_signature_query(db, def).get_with(|sig| sig.get());
+ callable_item_signature_with_diagnostics(db, def).value.get()
+}
- #[salsa::tracked(returns(ref))]
- pub(crate) fn callable_item_signature_query(
- db: &dyn HirDatabase,
- def: CallableDefId,
- ) -> StoredEarlyBinder<StoredPolyFnSig> {
- match def {
- CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f),
- CallableDefId::StructId(s) => fn_sig_for_struct_constructor(db, s),
- CallableDefId::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e),
+#[salsa::tracked(returns(ref))]
+pub(crate) fn callable_item_signature_with_diagnostics(
+ db: &dyn HirDatabase,
+ def: CallableDefId,
+) -> TyLoweringResult<StoredEarlyBinder<StoredPolyFnSig>> {
+ match def {
+ CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f),
+ CallableDefId::StructId(s) => TyLoweringResult::empty(fn_sig_for_struct_constructor(db, s)),
+ CallableDefId::EnumVariantId(e) => {
+ TyLoweringResult::empty(fn_sig_for_enum_variant_constructor(db, e))
}
}
}
-fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> StoredEarlyBinder<StoredPolyFnSig> {
+fn fn_sig_for_fn(
+ db: &dyn HirDatabase,
+ def: FunctionId,
+) -> TyLoweringResult<StoredEarlyBinder<StoredPolyFnSig>> {
let data = FunctionSignature::of(db, def);
let resolver = def.resolver(db);
let interner = DbInterner::new_no_crate(db);
@@ -2472,41 +2432,46 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> StoredEarlyBinder<Sto
db,
&resolver,
&data.store,
+ ExpressionStoreOwnerId::Signature(def.into()),
def.into(),
LifetimeElisionKind::for_fn_params(data),
);
let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr));
+ let mut ctx_ret = TyLoweringContext::new(
+ db,
+ &resolver,
+ &data.store,
+ ExpressionStoreOwnerId::Signature(def.into()),
+ def.into(),
+ LifetimeElisionKind::for_fn_ret(interner),
+ )
+ .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
let ret = match data.ret_type {
- Some(ret_type) => {
- let mut ctx_ret = TyLoweringContext::new(
- db,
- &resolver,
- &data.store,
- def.into(),
- LifetimeElisionKind::for_fn_ret(interner),
- )
- .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
- ctx_ret.lower_ty(ret_type)
- }
- None => Ty::new_tup(interner, &[]),
+ Some(ret_type) => ctx_ret.lower_ty(ret_type),
+ None => Ty::new_unit(interner),
};
let inputs_and_output = Tys::new_from_iter(interner, params.chain(Some(ret)));
+
+ ctx_params.diagnostics.extend(ctx_ret.diagnostics);
+ ctx_params.defined_anon_consts.extend(ctx_ret.defined_anon_consts);
+
// If/when we track late bound vars, we need to switch this to not be `dummy`
- StoredEarlyBinder::bind(StoredPolyFnSig::new(Binder::dummy(FnSig {
+ let result = StoredEarlyBinder::bind(StoredPolyFnSig::new(Binder::dummy(FnSig {
abi: data.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
c_variadic: data.is_varargs(),
safety: if data.is_unsafe() { Safety::Unsafe } else { Safety::Safe },
inputs_and_output,
- })))
+ })));
+ TyLoweringResult::from_ctx(result, ctx_params)
}
-fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> StoredEarlyBinder<StoredTy> {
+fn type_for_adt<'db>(db: &'db dyn HirDatabase, adt: AdtId) -> EarlyBinder<'db, Ty<'db>> {
let interner = DbInterner::new_no_crate(db);
let args = GenericArgs::identity_for_item(interner, adt.into());
let ty = Ty::new_adt(interner, adt, args);
- StoredEarlyBinder::bind(ty.store())
+ EarlyBinder::bind(ty)
}
fn fn_sig_for_struct_constructor(
@@ -2518,7 +2483,7 @@ fn fn_sig_for_struct_constructor(
let ret = type_for_adt(db, def.into()).skip_binder();
let inputs_and_output =
- Tys::new_from_iter(DbInterner::new_no_crate(db), params.chain(Some(ret.as_ref())));
+ Tys::new_from_iter(DbInterner::new_no_crate(db), params.chain(Some(ret)));
StoredEarlyBinder::bind(StoredPolyFnSig::new(Binder::dummy(FnSig {
abi: FnAbi::Rust,
c_variadic: false,
@@ -2537,7 +2502,7 @@ fn fn_sig_for_enum_variant_constructor(
let ret = type_for_adt(db, parent.into()).skip_binder();
let inputs_and_output =
- Tys::new_from_iter(DbInterner::new_no_crate(db), params.chain(Some(ret.as_ref())));
+ Tys::new_from_iter(DbInterner::new_no_crate(db), params.chain(Some(ret)));
StoredEarlyBinder::bind(StoredPolyFnSig::new(Binder::dummy(FnSig {
abi: FnAbi::Rust,
c_variadic: false,
@@ -2546,7 +2511,7 @@ fn fn_sig_for_enum_variant_constructor(
})))
}
-// FIXME(next-solver): should merge this with `explicit_item_bounds` in some way
+// FIXME: Remove this.
pub(crate) fn associated_ty_item_bounds<'db>(
db: &'db dyn HirDatabase,
type_alias: TypeAliasId,
@@ -2558,6 +2523,7 @@ pub(crate) fn associated_ty_item_bounds<'db>(
db,
&resolver,
&type_alias_data.store,
+ ExpressionStoreOwnerId::Signature(type_alias.into()),
type_alias.into(),
LifetimeElisionKind::AnonymousReportError,
);