Implement return position impl trait / opaque type support

This is working, but I'm not that happy with how the lowering works. We might
need an additional representation between `TypeRef` and `Ty` where names are
resolved and `impl Trait` bounds are separated out, but things like inference
variables don't exist and `impl Trait` is always represented the same
way.

Also note that this doesn't implement correct handling of RPIT *inside* the
function (which involves turning the `impl Trait`s into variables and creating
obligations for them). That intermediate representation might help there as
well.
This commit is contained in:
Florian Diebold 2020-03-04 23:00:44 +01:00 committed by Florian Diebold
parent 9c52f527a1
commit 02962b374e
10 changed files with 403 additions and 85 deletions

View file

@ -359,6 +359,21 @@ impl HirDisplay for ApplicationTy {
write!(f, ">")?;
}
}
TypeCtor::OpaqueType(opaque_ty_id) => {
let bounds = match opaque_ty_id {
crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
let datas =
f.db.return_type_impl_traits(func).expect("impl trait id without data");
let data = (*datas)
.as_ref()
.map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
data.clone().subst(&self.parameters)
}
};
write!(f, "impl ")?;
write_bounds_like_dyn_trait(&bounds.value, f)?;
// FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
}
TypeCtor::Closure { .. } => {
let sig = self.parameters[0].callable_sig(f.db);
if let Some(sig) = sig {
@ -427,14 +442,24 @@ impl HirDisplay for Ty {
}
}
Ty::Bound(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
match self {
Ty::Dyn(_) => write!(f, "dyn ")?,
Ty::Opaque(_) => write!(f, "impl ")?,
_ => unreachable!(),
};
Ty::Dyn(predicates) => {
write!(f, "dyn ")?;
write_bounds_like_dyn_trait(predicates, f)?;
}
Ty::Opaque(opaque_ty) => {
let bounds = match opaque_ty.opaque_ty_id {
crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
let datas =
f.db.return_type_impl_traits(func).expect("impl trait id without data");
let data = (*datas)
.as_ref()
.map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
data.clone().subst(&opaque_ty.parameters)
}
};
write!(f, "impl ")?;
write_bounds_like_dyn_trait(&bounds.value, f)?;
}
Ty::Unknown => write!(f, "{{unknown}}")?,
Ty::Infer(..) => write!(f, "_")?,
}