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 | 100 |
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(); |