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.rs100
1 files changed, 85 insertions, 15 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index df83b2abb8..fae63ddc2d 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -55,7 +55,7 @@ use thin_vec::ThinVec;
use tracing::debug;
use crate::{
- ImplTraitId, Span, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
+ ImplTraitId, Span, TyLoweringDiagnostic,
consteval::{create_anon_const, path_to_const},
db::{AnonConstId, GeneralConstId, HirDatabase, InternedOpaqueTyId},
generics::{Generics, SingleGenerics, generics},
@@ -64,9 +64,9 @@ use crate::{
AliasTy, Binder, BoundExistentialPredicates, Clause, ClauseKind, Clauses, Const, ConstKind,
DbInterner, DefaultAny, EarlyBinder, EarlyParamRegion, ErrorGuaranteed, FnSigKind,
FxIndexMap, GenericArg, GenericArgs, ParamConst, ParamEnv, PatList, Pattern, PolyFnSig,
- Predicate, Region, StoredClauses, StoredEarlyBinder, StoredGenericArg, StoredGenericArgs,
- StoredPolyFnSig, StoredTraitRef, StoredTy, TraitPredicate, TraitRef, Ty, Tys, Unnormalized,
- abi::Safety, util::BottomUpFolder,
+ Predicate, Region, StoredClauses, StoredConst, StoredEarlyBinder, StoredGenericArg,
+ StoredGenericArgs, StoredPolyFnSig, StoredTraitRef, StoredTy, TraitPredicate, TraitRef, Ty,
+ Tys, Unnormalized, abi::Safety, util::BottomUpFolder,
},
};
@@ -199,6 +199,33 @@ pub trait TyLoweringInferVarsCtx<'db> {
}
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum LoweringMode {
+ Analysis,
+ Ide,
+}
+
+pub(crate) use self::tracked_struct_token::TrackedStructToken;
+mod tracked_struct_token {
+ use super::LoweringMode;
+
+ /// A token that is required to construct tracked structs.
+ /// This exists to prevent one from accidentally creating a tracked struct outside of a query which may happen for some codepaths.
+ pub(crate) struct TrackedStructToken {
+ // #[non_exhaustive] doesn't work for us here, we want it module focused.
+ _private: (),
+ }
+
+ impl LoweringMode {
+ pub(crate) fn allow_tracked_structs(self) -> Option<TrackedStructToken> {
+ match self {
+ LoweringMode::Analysis => Some(TrackedStructToken { _private: () }),
+ LoweringMode::Ide => None,
+ }
+ }
+ }
+}
+
pub struct TyLoweringContext<'db, 'a> {
pub db: &'db dyn HirDatabase,
pub(crate) interner: DbInterner<'db>,
@@ -211,6 +238,7 @@ pub struct TyLoweringContext<'db, 'a> {
generics: &'a OnceCell<Generics<'db>>,
in_binders: DebruijnIndex,
impl_trait_mode: ImplTraitLoweringState,
+ interning_mode: LoweringMode,
/// Tracks types with explicit `?Sized` bounds.
pub(crate) unsized_types: FxHashSet<Ty<'db>>,
pub(crate) diagnostics: ThinVec<TyLoweringDiagnostic>,
@@ -247,6 +275,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
store,
in_binders,
impl_trait_mode,
+ interning_mode: LoweringMode::Analysis,
unsized_types: FxHashSet::default(),
diagnostics: ThinVec::new(),
lifetime_elision,
@@ -261,6 +290,11 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
self.lifetime_elision = lifetime_elision;
}
+ pub(crate) fn with_interning_mode(mut self, interning_mode: LoweringMode) -> Self {
+ self.interning_mode = interning_mode;
+ self
+ }
+
pub(crate) fn with_debruijn<T>(
&mut self,
debruijn: DebruijnIndex,
@@ -302,8 +336,14 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
self
}
- pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) {
- self.diagnostics.push(TyLoweringDiagnostic { source: type_ref, kind });
+ pub(crate) fn push_diagnostic(&mut self, diagnostic: TyLoweringDiagnostic) {
+ self.diagnostics.push(diagnostic);
+ }
+
+ fn push_infer_vars_not_allowed(&mut self, span: Span) {
+ if !span.is_dummy() {
+ self.push_diagnostic(TyLoweringDiagnostic::InferVarsNotAllowed { source: span });
+ }
}
#[track_caller]
@@ -315,7 +355,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
match &mut self.infer_vars {
Some(infer_vars) => infer_vars.next_ty_var(span),
None => {
- // FIXME: Emit an error: no infer vars allowed here.
+ self.push_infer_vars_not_allowed(span);
self.types.types.error
}
}
@@ -325,7 +365,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
match &mut self.infer_vars {
Some(infer_vars) => infer_vars.next_const_var(span),
None => {
- // FIXME: Emit an error: no infer vars allowed here.
+ self.push_infer_vars_not_allowed(span);
self.types.consts.error
}
}
@@ -335,7 +375,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
match &mut self.infer_vars {
Some(infer_vars) => infer_vars.next_region_var(span),
None => {
- // FIXME: Emit an error: no infer vars allowed here.
+ self.push_infer_vars_not_allowed(span);
self.types.regions.error
}
}
@@ -384,6 +424,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
const_type,
&|| self.generics.get_or_init(|| generics(self.db, self.generic_def)),
create_var,
+ self.interning_mode,
self.forbid_params_after,
);
@@ -634,7 +675,10 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
data: Either::Left(PathDiagnosticCallbackData(type_ref)),
callback: |data, this, diag| {
let type_ref = data.as_ref().left().unwrap().0;
- this.push_diagnostic(type_ref, TyLoweringDiagnosticKind::PathDiagnostic(diag))
+ this.push_diagnostic(TyLoweringDiagnostic::PathDiagnostic {
+ source: type_ref,
+ diag,
+ })
},
}
}
@@ -1694,16 +1738,34 @@ fn const_param_types_with_diagnostics_cycle_result(
pub(crate) fn field_types_query(
db: &dyn HirDatabase,
variant_id: VariantId,
-) -> &ArenaMap<LocalFieldId, StoredEarlyBinder<StoredTy>> {
+) -> &ArenaMap<LocalFieldId, FieldType> {
&field_types_with_diagnostics(db, variant_id).value
}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct FieldType {
+ ty: StoredEarlyBinder<StoredTy>,
+ default: Option<StoredEarlyBinder<StoredConst>>,
+}
+
+impl FieldType {
+ #[inline]
+ pub fn ty<'db>(&self) -> EarlyBinder<'db, Ty<'db>> {
+ self.ty.get()
+ }
+
+ #[inline]
+ pub fn default<'db>(&self) -> Option<EarlyBinder<'db, Const<'db>>> {
+ self.default.as_ref().map(|default| default.get_with(|it| it.as_ref()))
+ }
+}
+
/// Build the type of all specific fields of a struct or enum variant.
#[salsa::tracked(returns(ref))]
pub(crate) fn field_types_with_diagnostics(
db: &dyn HirDatabase,
variant_id: VariantId,
-) -> TyLoweringResult<ArenaMap<LocalFieldId, StoredEarlyBinder<StoredTy>>> {
+) -> TyLoweringResult<ArenaMap<LocalFieldId, FieldType>> {
let var_data = variant_id.fields(db);
let fields = var_data.fields();
if fields.is_empty() {
@@ -1727,7 +1789,15 @@ pub(crate) fn field_types_with_diagnostics(
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()));
+ let ty = ctx.lower_ty(field_data.type_ref);
+ let default = field_data.default_value.map(|default| ctx.lower_const(default, ty));
+ res.insert(
+ field_id,
+ FieldType {
+ ty: StoredEarlyBinder::bind(ty.store()),
+ default: default.map(|default| StoredEarlyBinder::bind(default.store())),
+ },
+ );
}
TyLoweringResult::from_ctx(res, ctx)
}
@@ -2628,7 +2698,7 @@ fn fn_sig_for_struct_constructor(
def: StructId,
) -> StoredEarlyBinder<StoredPolyFnSig> {
let field_tys = db.field_types(def.into());
- let params = field_tys.iter().map(|(_, ty)| ty.get().skip_binder());
+ let params = field_tys.iter().map(|(_, field)| field.ty().skip_binder());
let ret = type_for_adt(db, def.into()).skip_binder();
let inputs_and_output =
@@ -2644,7 +2714,7 @@ fn fn_sig_for_enum_variant_constructor(
def: EnumVariantId,
) -> StoredEarlyBinder<StoredPolyFnSig> {
let field_tys = db.field_types(def.into());
- let params = field_tys.iter().map(|(_, ty)| ty.get().skip_binder());
+ let params = field_tys.iter().map(|(_, field)| field.ty().skip_binder());
let parent = def.lookup(db).parent;
let ret = type_for_adt(db, parent.into()).skip_binder();