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.rs235
1 files changed, 191 insertions, 44 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 4f6943f695..656d39e5ad 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -44,7 +44,8 @@ use rustc_abi::ExternAbi;
use rustc_ast_ir::Mutability;
use rustc_hash::FxHashSet;
use rustc_type_ir::{
- AliasTyKind, BoundVarIndexKind, DebruijnIndex, ExistentialPredicate, ExistentialProjection,
+ AliasTyKind, BoundRegion, BoundRegionKind, BoundTyKind, BoundVar, BoundVarIndexKind,
+ BoundVariableKind, 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 _},
@@ -61,12 +62,13 @@ use crate::{
generics::{Generics, SingleGenerics, generics},
infer::unify::InferenceTable,
next_solver::{
- 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, StoredConst, StoredEarlyBinder, StoredGenericArg,
- StoredGenericArgs, StoredPolyFnSig, StoredTraitRef, StoredTy, TraitPredicate, TraitRef, Ty,
- Tys, Unnormalized, abi::Safety, util::BottomUpFolder,
+ AliasTy, Binder, BoundExistentialPredicates, BoundVarKinds, Clause, ClauseKind, Clauses,
+ Const, ConstKind, DbInterner, DefaultAny, EarlyBinder, EarlyParamRegion, ErrorGuaranteed,
+ FnSigKind, FxIndexMap, GenericArg, GenericArgs, ParamConst, ParamEnv, PatList, Pattern,
+ PolyFnSig, Predicate, Region, StoredClauses, StoredConst, StoredEarlyBinder,
+ StoredGenericArg, StoredGenericArgs, StoredPolyFnSig, StoredTraitRef, StoredTy,
+ TraitPredicate, TraitRef, Ty, Tys, Unnormalized, abi::Safety, mk_param,
+ util::BottomUpFolder,
},
};
@@ -247,6 +249,9 @@ pub struct TyLoweringContext<'db, 'a> {
forbid_params_after_reason: ForbidParamsAfterReason,
pub(crate) defined_anon_consts: ThinVec<AnonConstId>,
infer_vars: Option<&'a mut dyn TyLoweringInferVarsCtx<'db>>,
+ is_lowering_impl_trait_bounds: bool,
+ bound_vars: Vec<BoundVarKinds<'db>>, // FIXME: HRTB and other for lifetime doesn't change it now
+ lifetime_lowering_mode: LifetimeLoweringMode,
}
impl<'db, 'a> TyLoweringContext<'db, 'a> {
@@ -258,10 +263,12 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
generic_def: GenericDefId,
generics: &'a OnceCell<Generics<'db>>,
lifetime_elision: LifetimeElisionKind<'db>,
+ lifetime_lowering_mode: LifetimeLoweringMode,
) -> Self {
let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed);
let in_binders = DebruijnIndex::ZERO;
let interner = DbInterner::new_with(db, resolver.krate());
+ let bound_vars = vec![BoundVarKinds::empty(interner)];
Self {
db,
// Can provide no block since we don't use it for trait solving.
@@ -283,6 +290,9 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
forbid_params_after_reason: ForbidParamsAfterReason::AnonConst,
defined_anon_consts: ThinVec::new(),
infer_vars: None,
+ is_lowering_impl_trait_bounds: false,
+ bound_vars,
+ lifetime_lowering_mode,
}
}
@@ -385,6 +395,32 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
}
}
+
+ fn peek_bound_vars(&self) -> BoundVarKinds<'db> {
+ *self.bound_vars.last().unwrap()
+ }
+
+ fn bound_vars(
+ db: &'db dyn HirDatabase,
+ interner: DbInterner<'db>,
+ def: GenericDefId,
+ generic: &'a OnceCell<Generics<'db>>,
+ ) -> BoundVarKinds<'db> {
+ let def_id = def.into();
+
+ let generics = generic.get_or_init(|| generics(db, def));
+ let args = generics.iter_self_late_bound().map(|(_, data)| match data {
+ GenericParamDataRef::TypeParamData(..) => {
+ BoundVariableKind::Ty(BoundTyKind::Param(def_id))
+ }
+ GenericParamDataRef::ConstParamData(..) => BoundVariableKind::Const,
+ GenericParamDataRef::LifetimeParamData(..) => {
+ BoundVariableKind::Region(BoundRegionKind::Named(def_id))
+ }
+ });
+
+ BoundVarKinds::new_from_iter(interner, args)
+ }
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
@@ -399,6 +435,16 @@ pub(crate) enum ImplTraitLoweringMode {
Disallowed,
}
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum LifetimeLoweringMode {
+ /// Lowers the late bound lifetimes to `ReBound`, used in cases when lowering
+ /// from outside of function.
+ Bound,
+ /// Lowers the late bound lifetimes to `ReLateParam`, used in cases when lowering
+ /// inside the function itself
+ LateParam,
+}
+
impl<'db, 'a> TyLoweringContext<'db, 'a> {
pub fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> {
self.lower_ty_ext(type_ref).0
@@ -471,12 +517,40 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
}
- fn region_param(&mut self, id: LifetimeParamId, index: u32) -> Region<'db> {
+ fn region_param(
+ &mut self,
+ id: LifetimeParamId,
+ index: u32,
+ is_late_bound: bool,
+ ) -> Region<'db> {
if self.param_index_is_disallowed(index) {
// FIXME: Report an error.
self.types.regions.error
} else {
- Region::new_early_param(self.interner, EarlyParamRegion { id, index })
+ if is_late_bound {
+ if self.lifetime_lowering_mode == LifetimeLoweringMode::Bound {
+ Region::new_bound(
+ self.interner,
+ self.in_binders,
+ BoundRegion {
+ var: BoundVar::from_u32(index),
+ kind: BoundRegionKind::Named(id.parent.into()),
+ },
+ )
+ } else {
+ let solver_def_id = id.parent.into();
+ Region::new_late_param(
+ self.interner,
+ solver_def_id,
+ BoundRegion {
+ var: BoundVar::from_u32(index),
+ kind: BoundRegionKind::Named(solver_def_id),
+ },
+ )
+ }
+ } else {
+ Region::new_early_param(self.interner, EarlyParamRegion { id, index })
+ }
}
}
@@ -568,8 +642,45 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
});
self.impl_trait_mode.opaque_type_data[idx] = actual_opaque_type_data;
- let args =
- GenericArgs::identity_for_item(self.interner, opaque_ty_id.into());
+ let mut late_bound_index = 0;
+ let args = GenericArgs::for_item(
+ self.interner,
+ opaque_ty_id.into(),
+ |index, param_id, lt_param, _| {
+ if let Some(lt) = lt_param
+ && lt.is_late_bound()
+ && !self.is_lowering_impl_trait_bounds
+ {
+ let GenericParamId::LifetimeParamId(id) = param_id else {
+ unreachable!()
+ };
+ let bound_region_kind =
+ BoundRegionKind::Named(id.parent.into());
+ let region = match self.lifetime_lowering_mode {
+ LifetimeLoweringMode::Bound => Region::new_bound(
+ interner,
+ self.in_binders,
+ BoundRegion {
+ var: BoundVar::from_u32(late_bound_index),
+ kind: bound_region_kind,
+ },
+ ),
+ LifetimeLoweringMode::LateParam => Region::new_late_param(
+ interner,
+ self.generic_def.into(),
+ BoundRegion {
+ var: BoundVar::from_u32(late_bound_index),
+ kind: bound_region_kind,
+ },
+ ),
+ };
+ late_bound_index += 1;
+ return region.into();
+ }
+
+ mk_param(interner, index - late_bound_index, param_id)
+ },
+ );
Ty::new_alias(
self.interner,
AliasTy::new_from_args(
@@ -635,17 +746,23 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
args.push(ctx.lower_ty(ret_ty));
});
self.lifetime_elision = old_lifetime_elision;
+
+ // FIXME: When we don't drop HRTB lifetimes, use those here.
+ let binder = BoundVarKinds::empty(interner);
Ty::new_fn_ptr(
interner,
- Binder::dummy(FnSig {
- fn_sig_kind: FnSigKind::new(
- fn_.abi,
- if fn_.is_unsafe { Safety::Unsafe } else { Safety::Safe },
- fn_.is_varargs,
- // FIXME(splat): handle splatted arguments
- ),
- inputs_and_output: Tys::new_from_slice(&args),
- }),
+ Binder::bind_with_vars(
+ FnSig {
+ fn_sig_kind: FnSigKind::new(
+ fn_.abi,
+ if fn_.is_unsafe { Safety::Unsafe } else { Safety::Safe },
+ fn_.is_varargs,
+ // FIXME(splat): handle splatted arguments
+ ),
+ inputs_and_output: Tys::new_from_slice(&args),
+ },
+ binder,
+ ),
)
}
@@ -792,6 +909,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
let mut clause = None;
match bound {
&TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => {
+ let binder = self.peek_bound_vars();
// FIXME Don't silently drop the hrtb lifetimes here
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
@@ -810,12 +928,15 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
clause = Some(Clause(Predicate::new(
interner,
- Binder::dummy(rustc_type_ir::PredicateKind::Clause(
- rustc_type_ir::ClauseKind::Trait(TraitPredicate {
- trait_ref,
- polarity: rustc_type_ir::PredicatePolarity::Positive,
- }),
- )),
+ Binder::bind_with_vars(
+ rustc_type_ir::PredicateKind::Clause(
+ rustc_type_ir::ClauseKind::Trait(TraitPredicate {
+ trait_ref,
+ polarity: rustc_type_ir::PredicatePolarity::Positive,
+ }),
+ ),
+ binder,
+ ),
)));
}
}
@@ -834,13 +955,17 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
&TypeBound::Lifetime(l) => {
let lifetime = self.lower_lifetime(l);
+ let binder = self.peek_bound_vars();
clause = Some(Clause(Predicate::new(
self.interner,
- Binder::dummy(rustc_type_ir::PredicateKind::Clause(
- rustc_type_ir::ClauseKind::TypeOutlives(OutlivesPredicate(
- self_ty, lifetime,
- )),
- )),
+ Binder::bind_with_vars(
+ rustc_type_ir::PredicateKind::Clause(
+ rustc_type_ir::ClauseKind::TypeOutlives(OutlivesPredicate(
+ self_ty, lifetime,
+ )),
+ ),
+ binder,
+ ),
)));
}
TypeBound::Use(_) | TypeBound::Error => {}
@@ -1107,7 +1232,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
rustc_type_ir::RegionKind::ReBound(BoundVarIndexKind::Bound(db), var) => {
Region::new_bound(
self.interner,
- db.shifted_out_to_binder(DebruijnIndex::from_u32(2)),
+ db.shifted_out_to_binder(DebruijnIndex::from_u32(1)),
var,
)
}
@@ -1131,6 +1256,8 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
self.interner,
AliasTy::new_from_args(interner, rustc_type_ir::Opaque { def_id: def_id.into() }, args),
);
+ let prev_is_lowering_impl_trait_bounds =
+ mem::replace(&mut self.is_lowering_impl_trait_bounds, true);
let (predicates, assoc_ty_bounds_start) =
self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| {
let mut predicates = Vec::new();
@@ -1170,6 +1297,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
(predicates, assoc_ty_bounds_start)
});
+ self.is_lowering_impl_trait_bounds = prev_is_lowering_impl_trait_bounds;
ImplTrait {
predicates: Clauses::new_from_slice(&predicates).store(),
assoc_ty_bounds_start,
@@ -1181,8 +1309,9 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
Some(resolution) => match resolution {
LifetimeNs::Static => Region::new_static(self.interner),
LifetimeNs::LifetimeParam(id) => {
- let idx = self.generics().lifetime_param_idx(id);
- self.region_param(id, idx)
+ let (idx, is_late_bound) =
+ self.generics().lifetime_param_idx(id, self.is_lowering_impl_trait_bounds);
+ self.region_param(id, idx, is_late_bound)
}
},
None => Region::error(self.interner),
@@ -1300,6 +1429,7 @@ pub(crate) fn impl_trait_with_diagnostics(
impl_id.into(),
&generics,
LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
+ LifetimeLoweringMode::Bound,
);
let self_ty = db.impl_self_ty(impl_id).skip_binder();
let target_trait = impl_data.target_trait.as_ref()?;
@@ -1384,6 +1514,7 @@ impl ImplTraits {
def.into(),
&generics,
LifetimeElisionKind::Infer,
+ LifetimeLoweringMode::Bound,
)
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
if let Some(ret_type) = data.ret_type {
@@ -1415,6 +1546,7 @@ impl ImplTraits {
def.into(),
&generics,
LifetimeElisionKind::AnonymousReportError,
+ LifetimeLoweringMode::Bound,
)
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
if let Some(type_ref) = data.ty {
@@ -1516,6 +1648,7 @@ pub(crate) fn type_for_const_with_diagnostics(
def.into(),
&generics,
LifetimeElisionKind::AnonymousReportError,
+ LifetimeLoweringMode::Bound,
);
ctx.set_lifetime_elision(LifetimeElisionKind::for_const(ctx.interner, parent));
let result = StoredEarlyBinder::bind(ctx.lower_ty(data.type_ref).store());
@@ -1546,6 +1679,7 @@ pub(crate) fn type_for_static_with_diagnostics(
def.into(),
&generics,
LifetimeElisionKind::AnonymousReportError,
+ LifetimeLoweringMode::Bound,
);
ctx.set_lifetime_elision(LifetimeElisionKind::Elided(Region::new_static(ctx.interner)));
let result = StoredEarlyBinder::bind(ctx.lower_ty(data.type_ref).store());
@@ -1628,6 +1762,7 @@ pub(crate) fn type_for_type_alias_with_diagnostics(
t.into(),
&generics,
LifetimeElisionKind::AnonymousReportError,
+ LifetimeLoweringMode::Bound,
)
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
let res = StoredEarlyBinder::bind(
@@ -1674,6 +1809,7 @@ pub(crate) fn impl_self_ty_with_diagnostics(
impl_id.into(),
&generics,
LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
+ LifetimeLoweringMode::Bound,
);
let ty = ctx.lower_ty(impl_data.self_ty);
assert!(!ty.has_escaping_bound_vars());
@@ -1722,6 +1858,7 @@ pub(crate) fn const_param_types_with_diagnostics(
def,
&generics,
LifetimeElisionKind::AnonymousReportError,
+ LifetimeLoweringMode::Bound,
);
ctx.forbid_params_after(0, ForbidParamsAfterReason::ConstParamTy);
for (local_id, param_data) in data.iter_type_or_consts() {
@@ -1793,6 +1930,7 @@ pub(crate) fn field_types_with_diagnostics(
generic_def,
&generics,
LifetimeElisionKind::AnonymousReportError,
+ LifetimeLoweringMode::Bound,
);
for (field_id, field_data) in var_data.fields().iter() {
let ty = ctx.lower_ty(field_data.type_ref);
@@ -1933,6 +2071,7 @@ fn resolve_type_param_assoc_type_shorthand(
def,
generics,
LifetimeElisionKind::AnonymousReportError,
+ LifetimeLoweringMode::Bound,
);
let interner = ctx.interner;
let generics = generics.get().unwrap();
@@ -2113,6 +2252,7 @@ pub(crate) fn type_alias_bounds_with_diagnostics(
type_alias.into(),
&generics,
LifetimeElisionKind::AnonymousReportError,
+ LifetimeLoweringMode::Bound,
);
let interner = ctx.interner;
@@ -2351,6 +2491,7 @@ fn generic_predicates(
def,
generics,
LifetimeElisionKind::AnonymousReportError,
+ LifetimeLoweringMode::Bound,
);
let generics = generics.get().unwrap();
let sized_trait = ctx.lang_items.Sized;
@@ -2568,6 +2709,7 @@ pub(crate) fn generic_defaults_with_diagnostics(
def,
generics,
LifetimeElisionKind::AnonymousReportError,
+ LifetimeLoweringMode::Bound,
)
.with_impl_trait_mode(ImplTraitLoweringMode::Disallowed);
let generics = generics.get().unwrap();
@@ -2657,6 +2799,7 @@ fn fn_sig_for_fn(
def.into(),
&generics,
LifetimeElisionKind::for_fn_params(data),
+ LifetimeLoweringMode::Bound,
);
let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr));
@@ -2668,6 +2811,7 @@ fn fn_sig_for_fn(
def.into(),
&generics,
LifetimeElisionKind::for_fn_ret(interner),
+ LifetimeLoweringMode::Bound,
)
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
let ret = match data.ret_type {
@@ -2676,19 +2820,21 @@ fn fn_sig_for_fn(
};
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`
- let result = StoredEarlyBinder::bind(StoredPolyFnSig::new(Binder::dummy(FnSig {
- inputs_and_output,
- fn_sig_kind: FnSigKind::new(
- data.abi,
- if data.is_unsafe() { Safety::Unsafe } else { Safety::Safe },
- data.is_varargs(),
- ),
- })));
+ let binder = TyLoweringContext::bound_vars(db, interner, def.into(), &generics);
+ let result = StoredEarlyBinder::bind(StoredPolyFnSig::new(Binder::bind_with_vars(
+ FnSig {
+ inputs_and_output,
+ fn_sig_kind: FnSigKind::new(
+ data.abi,
+ if data.is_unsafe() { Safety::Unsafe } else { Safety::Safe },
+ data.is_varargs(),
+ ),
+ },
+ binder,
+ )));
TyLoweringResult::from_ctx(result, ctx_params)
}
@@ -2749,6 +2895,7 @@ pub(crate) fn associated_ty_item_bounds<'db>(
type_alias.into(),
&generics,
LifetimeElisionKind::AnonymousReportError,
+ LifetimeLoweringMode::Bound,
);
// 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