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 | 141 |
1 files changed, 107 insertions, 34 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 737cfb16f6..61329f6c88 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -39,7 +39,7 @@ use la_arena::{Arena, ArenaMap, Idx}; use path::{PathDiagnosticCallback, PathLoweringContext}; use rustc_abi::ExternAbi; use rustc_ast_ir::Mutability; -use rustc_hash::FxHashSet; +use rustc_hash::{FxHashMap, FxHashSet}; use rustc_type_ir::{ AliasTyKind, BoundVarIndexKind, DebruijnIndex, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, Interner, OutlivesPredicate, TermKind, TyKind, TypeFoldable, @@ -52,16 +52,17 @@ use thin_vec::ThinVec; use tracing::debug; use crate::{ - ImplTraitId, TyLoweringDiagnostic, TyLoweringDiagnosticKind, + ImplTraitId, Span, TyLoweringDiagnostic, TyLoweringDiagnosticKind, consteval::{create_anon_const, path_to_const}, db::{AnonConstId, GeneralConstId, HirDatabase, InternedOpaqueTyId}, generics::{Generics, SingleGenerics, generics}, + infer::unify::InferenceTable, next_solver::{ AliasTy, Binder, BoundExistentialPredicates, Clause, ClauseKind, Clauses, Const, ConstKind, - DbInterner, EarlyBinder, EarlyParamRegion, ErrorGuaranteed, FnSigKind, FxIndexMap, - GenericArg, GenericArgs, ParamConst, ParamEnv, PolyFnSig, Predicate, Region, StoredClauses, - StoredEarlyBinder, StoredGenericArg, StoredGenericArgs, StoredPolyFnSig, StoredTraitRef, - StoredTy, TraitPredicate, TraitRef, Ty, Tys, Unnormalized, abi::Safety, + DbInterner, DefaultAny, EarlyBinder, EarlyParamRegion, ErrorGuaranteed, FnSigKind, + FxIndexMap, GenericArg, GenericArgs, ParamConst, ParamEnv, PolyFnSig, Predicate, Region, + StoredClauses, StoredEarlyBinder, StoredGenericArg, StoredGenericArgs, StoredPolyFnSig, + StoredTraitRef, StoredTy, TraitPredicate, TraitRef, Ty, Tys, Unnormalized, abi::Safety, util::BottomUpFolder, }, }; @@ -184,7 +185,12 @@ pub(crate) enum ForbidParamsAfterReason { ConstParamTy, } -#[derive(Debug)] +pub(crate) struct TyLoweringInferVarsCtx<'a, 'db> { + // Technically we can just put an `&InferCtxt` here, but borrowck constraints requires us to put this: + pub(crate) table: &'a mut InferenceTable<'db>, + pub(crate) type_of_placeholder: &'a mut FxHashMap<TypeRefId, StoredTy>, +} + pub struct TyLoweringContext<'db, 'a> { pub db: &'db dyn HirDatabase, interner: DbInterner<'db>, @@ -204,6 +210,7 @@ pub struct TyLoweringContext<'db, 'a> { forbid_params_after: Option<u32>, forbid_params_after_reason: ForbidParamsAfterReason, pub(crate) defined_anon_consts: ThinVec<AnonConstId>, + infer_vars: Option<TyLoweringInferVarsCtx<'a, 'db>>, } impl<'db, 'a> TyLoweringContext<'db, 'a> { @@ -238,6 +245,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { forbid_params_after: None, forbid_params_after_reason: ForbidParamsAfterReason::AnonConst, defined_anon_consts: ThinVec::new(), + infer_vars: None, } } @@ -278,9 +286,66 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { self.forbid_params_after_reason = reason; } + pub(crate) fn with_infer_vars_behavior( + mut self, + behavior: Option<TyLoweringInferVarsCtx<'a, 'db>>, + ) -> Self { + self.infer_vars = behavior; + self + } + pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) { self.diagnostics.push(TyLoweringDiagnostic { source: type_ref, kind }); } + + #[track_caller] + pub(crate) fn expect_table(&mut self) -> &mut InferenceTable<'db> { + self.infer_vars.as_mut().unwrap().table + } + + fn next_ty_var(&mut self, type_ref: TypeRefId) -> Ty<'db> { + match &mut self.infer_vars { + Some(infer_vars) => { + let var = infer_vars.table.next_ty_var(type_ref.into()); + infer_vars.type_of_placeholder.insert(type_ref, var.store()); + var + } + None => { + // FIXME: Emit an error: no infer vars allowed here. + self.types.types.error + } + } + } + + fn next_ty_var_no_placeholder(&mut self, span: Span) -> Ty<'db> { + match &mut self.infer_vars { + Some(infer_vars) => infer_vars.table.next_ty_var(span), + None => { + // FIXME: Emit an error: no infer vars allowed here. + self.types.types.error + } + } + } + + fn next_const_var(&mut self, span: Span) -> Const<'db> { + match &mut self.infer_vars { + Some(infer_vars) => infer_vars.table.next_const_var(span), + None => { + // FIXME: Emit an error: no infer vars allowed here. + self.types.consts.error + } + } + } + + fn next_region_var(&mut self, span: Span) -> Region<'db> { + match &mut self.infer_vars { + Some(infer_vars) => infer_vars.table.next_region_var(span), + None => { + // FIXME: Emit an error: no infer vars allowed here. + self.types.regions.error + } + } + } } #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] @@ -309,7 +374,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { self.resolver, const_type, &|| self.generics(), - None, + self.infer_vars.as_ref().map(|vars_ctx| &vars_ctx.table.infer_ctxt), self.forbid_params_after, ); @@ -345,7 +410,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { fn type_param(&mut self, id: TypeParamId, index: u32) -> Ty<'db> { if self.param_index_is_disallowed(index) { // FIXME: Report an error. - Ty::new_error(self.interner, ErrorGuaranteed) + self.types.types.error } else { Ty::new_param(self.interner, id, index) } @@ -354,7 +419,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { fn region_param(&mut self, id: LifetimeParamId, index: u32) -> Region<'db> { if self.param_index_is_disallowed(index) { // FIXME: Report an error. - Region::error(self.interner) + self.types.regions.error } else { Region::new_early_param(self.interner, EarlyParamRegion { id, index }) } @@ -391,7 +456,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { } TypeRef::Array(array) => { let inner_ty = self.lower_ty(array.ty); - let const_len = self.lower_const(array.len, Ty::new_usize(interner)); + let const_len = self.lower_const(array.len, self.types.types.usize); Ty::new_array_with_const_len(interner, inner_ty, const_len) } &TypeRef::Slice(inner) => { @@ -401,12 +466,11 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { TypeRef::Reference(ref_) => { let inner_ty = self.lower_ty(ref_.ty); // FIXME: It should infer the eldided lifetimes instead of stubbing with error - let lifetime = ref_ - .lifetime - .map_or_else(|| Region::error(interner), |lr| self.lower_lifetime(lr)); + let lifetime = + ref_.lifetime.map_or(self.types.regions.error, |lr| self.lower_lifetime(lr)); Ty::new_ref(interner, lifetime, inner_ty, lower_mutability(ref_.mutability)) } - TypeRef::Placeholder => Ty::new_error(interner, ErrorGuaranteed), + TypeRef::Placeholder => self.next_ty_var(type_ref_id), TypeRef::Fn(fn_) => self.lower_fn_ptr(fn_), TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds), TypeRef::ImplTrait(bounds) => { @@ -462,11 +526,11 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { } ImplTraitLoweringMode::Disallowed => { // FIXME: report error - Ty::new_error(self.interner, ErrorGuaranteed) + self.types.types.error } } } - TypeRef::Error => Ty::new_error(self.interner, ErrorGuaranteed), + TypeRef::Error => self.types.types.error, }; (ty, res) } @@ -548,13 +612,13 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { if let Some(type_ref) = path.type_anchor() { let (ty, res) = self.lower_ty_ext(type_ref); let mut ctx = self.at_path(path_id); - return ctx.lower_ty_relative_path(ty, res, false); + return ctx.lower_ty_relative_path(ty, res, false, path_id.type_ref().into()); } let mut ctx = self.at_path(path_id); let (resolution, remaining_index) = match ctx.resolve_path_in_type_ns() { Some(it) => it, - None => return (Ty::new_error(self.interner, ErrorGuaranteed), None), + None => return (self.types.types.error, None), }; if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() { @@ -564,7 +628,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { return (ty, None); } - ctx.lower_partly_resolved_path(resolution, false) + ctx.lower_partly_resolved_path(resolution, false, path_id.type_ref().into()) } fn lower_trait_ref_from_path( @@ -578,7 +642,15 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { TypeNs::TraitId(tr) => tr, _ => return None, }; - Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty, false), ctx)) + Some(( + ctx.lower_trait_ref_from_resolved_path( + resolved, + explicit_self_ty, + false, + path_id.type_ref().into(), + ), + ctx, + )) } fn lower_trait_ref( @@ -640,7 +712,10 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { ctx.ty_ctx().unsized_types.insert(self_ty); } else { if !ignore_bindings { - assoc_bounds = ctx.assoc_type_bindings_from_type_bound(trait_ref); + assoc_bounds = ctx.assoc_type_bindings_from_type_bound( + trait_ref, + path.type_ref().into(), + ); } clause = Some(Clause(Predicate::new( interner, @@ -687,7 +762,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty<'db> { let interner = self.interner; - let dummy_self_ty = dyn_trait_dummy_self(interner); + let dummy_self_ty = self.types.types.dyn_trait_dummy_self; 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 @@ -885,7 +960,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { .map(|arg| { if arg.walk().any(|arg| arg == dummy_self_ty.into()) { // FIXME: Report an error. - Ty::new_error(interner, ErrorGuaranteed).into() + self.types.types.error.into() } else { arg } @@ -911,8 +986,11 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { false }); if references_self { - proj.projection_term = - replace_dummy_self_with_error(interner, proj.projection_term); + proj.projection_term = replace_dummy_self_with_error( + interner, + self.types, + proj.projection_term, + ); } ExistentialPredicate::Projection(ExistentialProjection::erase_self_ty( @@ -950,7 +1028,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { } else { // FIXME: report error // (additional non-auto traits, associated type rebound, or no resolved trait) - Ty::new_error(self.interner, ErrorGuaranteed) + self.types.types.error } } @@ -1084,20 +1162,15 @@ impl<T> TyLoweringResult<T> { } } -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>, + types: &DefaultAny<'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 } + if ty == types.types.dyn_trait_dummy_self { types.types.error } else { ty } }, lt_op: |lt| lt, ct_op: |ct| ct, |