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.rs69
1 files changed, 49 insertions, 20 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 3e6d81f6ca..0bc739e696 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -61,9 +61,9 @@ use crate::{
InTypeConstIdMetadata,
},
AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
- FnAbi, FnPointer, FnSig, FnSubst, ImplTraitId, Interner, ParamKind, PolyFnSig, ProjectionTy,
- QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits,
- Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
+ FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, ParamKind,
+ PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, Substitution,
+ TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
};
#[derive(Debug)]
@@ -76,7 +76,7 @@ enum ImplTraitLoweringState {
/// we're grouping the mutable data (the counter and this field) together
/// with the immutable context (the references to the DB and resolver).
/// Splitting this up would be a possible fix.
- Opaque(RefCell<Arena<ReturnTypeImplTrait>>),
+ Opaque(RefCell<Arena<ImplTrait>>),
Param(Cell<u16>),
Variable(Cell<u16>),
Disallowed,
@@ -301,15 +301,18 @@ impl<'a> TyLoweringContext<'a> {
TypeRef::ImplTrait(bounds) => {
match &self.impl_trait_mode {
ImplTraitLoweringState::Opaque(opaque_type_data) => {
- let func = match self.resolver.generic_def() {
- Some(GenericDefId::FunctionId(f)) => f,
- _ => panic!("opaque impl trait lowering in non-function"),
+ let origin = match self.resolver.generic_def() {
+ Some(GenericDefId::FunctionId(it)) => Either::Left(it),
+ Some(GenericDefId::TypeAliasId(it)) => Either::Right(it),
+ _ => panic!(
+ "opaque impl trait lowering must be in function or type alias"
+ ),
};
// this dance is to make sure the data is in the right
// place even if we encounter more opaque types while
// lowering the bounds
- let idx = opaque_type_data.borrow_mut().alloc(ReturnTypeImplTrait {
+ let idx = opaque_type_data.borrow_mut().alloc(ImplTrait {
bounds: crate::make_single_type_binders(Vec::new()),
});
// We don't want to lower the bounds inside the binders
@@ -323,13 +326,17 @@ impl<'a> TyLoweringContext<'a> {
// away instead of two.
let actual_opaque_type_data = self
.with_debruijn(DebruijnIndex::INNERMOST, |ctx| {
- ctx.lower_impl_trait(bounds, func)
+ ctx.lower_impl_trait(bounds, self.resolver.krate())
});
opaque_type_data.borrow_mut()[idx] = actual_opaque_type_data;
- let impl_trait_id = ImplTraitId::ReturnTypeImplTrait(func, idx);
+ let impl_trait_id = origin.either(
+ |f| ImplTraitId::ReturnTypeImplTrait(f, idx),
+ |a| ImplTraitId::AssociatedTypeImplTrait(a, idx),
+ );
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
- let generics = generics(self.db.upcast(), func.into());
+ let generics =
+ generics(self.db.upcast(), origin.either(|f| f.into(), |a| a.into()));
let parameters = generics.bound_vars_subst(self.db, self.in_binders);
TyKind::OpaqueType(opaque_ty_id, parameters).intern(Interner)
}
@@ -1274,11 +1281,7 @@ impl<'a> TyLoweringContext<'a> {
}
}
- fn lower_impl_trait(
- &self,
- bounds: &[Interned<TypeBound>],
- func: FunctionId,
- ) -> ReturnTypeImplTrait {
+ fn lower_impl_trait(&self, bounds: &[Interned<TypeBound>], krate: CrateId) -> ImplTrait {
cov_mark::hit!(lower_rpit);
let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
@@ -1288,7 +1291,6 @@ impl<'a> TyLoweringContext<'a> {
.collect();
if !ctx.unsized_types.borrow().contains(&self_ty) {
- let krate = func.krate(ctx.db.upcast());
let sized_trait = ctx
.db
.lang_item(krate, LangItem::Sized)
@@ -1305,7 +1307,7 @@ impl<'a> TyLoweringContext<'a> {
}
predicates
});
- ReturnTypeImplTrait { bounds: crate::make_single_type_binders(predicates) }
+ ImplTrait { bounds: crate::make_single_type_binders(predicates) }
}
}
@@ -1873,6 +1875,7 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
let generics = generics(db.upcast(), t.into());
let resolver = t.resolver(db.upcast());
let ctx = TyLoweringContext::new(db, &resolver, t.into())
+ .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
.with_type_param_mode(ParamLoweringMode::Variable);
let type_alias_data = db.type_alias_data(t);
if type_alias_data.is_extern {
@@ -2033,7 +2036,7 @@ pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<
pub(crate) fn return_type_impl_traits(
db: &dyn HirDatabase,
def: hir_def::FunctionId,
-) -> Option<Arc<Binders<ReturnTypeImplTraits>>> {
+) -> Option<Arc<Binders<ImplTraits>>> {
// FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe
let data = db.function_data(def);
let resolver = def.resolver(db.upcast());
@@ -2042,7 +2045,7 @@ pub(crate) fn return_type_impl_traits(
.with_type_param_mode(ParamLoweringMode::Variable);
let _ret = ctx_ret.lower_ty(&data.ret_type);
let generics = generics(db.upcast(), def.into());
- let return_type_impl_traits = ReturnTypeImplTraits {
+ let return_type_impl_traits = ImplTraits {
impl_traits: match ctx_ret.impl_trait_mode {
ImplTraitLoweringState::Opaque(x) => x.into_inner(),
_ => unreachable!(),
@@ -2055,6 +2058,32 @@ pub(crate) fn return_type_impl_traits(
}
}
+pub(crate) fn type_alias_impl_traits(
+ db: &dyn HirDatabase,
+ def: hir_def::TypeAliasId,
+) -> Option<Arc<Binders<ImplTraits>>> {
+ let data = db.type_alias_data(def);
+ let resolver = def.resolver(db.upcast());
+ let ctx = TyLoweringContext::new(db, &resolver, def.into())
+ .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
+ .with_type_param_mode(ParamLoweringMode::Variable);
+ if let Some(type_ref) = &data.type_ref {
+ let _ty = ctx.lower_ty(type_ref);
+ }
+ let generics = generics(db.upcast(), def.into());
+ let type_alias_impl_traits = ImplTraits {
+ impl_traits: match ctx.impl_trait_mode {
+ ImplTraitLoweringState::Opaque(x) => x.into_inner(),
+ _ => unreachable!(),
+ },
+ };
+ if type_alias_impl_traits.impl_traits.is_empty() {
+ None
+ } else {
+ Some(Arc::new(make_binders(db, &generics, type_alias_impl_traits)))
+ }
+}
+
pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mutability {
match m {
hir_def::type_ref::Mutability::Shared => Mutability::Not,