Fix APIT some more

This commit is contained in:
Florian Diebold 2020-02-02 13:04:22 +01:00 committed by Florian Diebold
parent c6654fd4a7
commit 3397ca679f
4 changed files with 115 additions and 101 deletions

View File

@ -479,8 +479,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
fn collect_fn(&mut self, data: &FunctionData) {
let body = Arc::clone(&self.body); // avoid borrow checker problem
for (type_ref, pat) in data.params.iter().zip(body.params.iter()) {
let ty = self.make_ty_with_mode(type_ref, ImplTraitLoweringMode::Param);
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver).with_impl_trait_mode(ImplTraitLoweringMode::Param);
let param_tys = data.params.iter().map(|type_ref| Ty::from_hir(&ctx, type_ref)).collect::<Vec<_>>();
for (ty, pat) in param_tys.into_iter().zip(body.params.iter()) {
let ty = self.insert_type_vars(ty);
let ty = self.normalize_associated_types_in(ty);
self.infer_pat(*pat, &ty, BindingMode::default());
}

View File

@ -44,11 +44,11 @@ use std::sync::Arc;
use std::{fmt, iter, mem};
use hir_def::{
expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId,
HasModule, Lookup, TraitId, TypeAliasId, TypeParamId, generics::TypeParamProvenance,
expr::ExprId, generics::TypeParamProvenance, type_ref::Mutability, AdtId, AssocContainerId,
DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, TypeParamId,
};
use ra_db::{impl_intern_key, salsa, CrateId};
use hir_expand::name::Name;
use ra_db::{impl_intern_key, salsa, CrateId};
use crate::{
db::HirDatabase,
@ -360,9 +360,7 @@ impl Substs {
/// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
pub(crate) fn type_params(generic_params: &Generics) -> Substs {
Substs(
generic_params.iter().map(|(id, _)| Ty::Param(id)).collect(),
)
Substs(generic_params.iter().map(|(id, _)| Ty::Param(id)).collect())
}
/// Return Substs that replace each parameter by a bound variable.
@ -448,7 +446,9 @@ pub struct Binders<T> {
}
impl<T> Binders<T> {
pub fn new(num_binders: usize, value: T) -> Self { Self { num_binders, value } }
pub fn new(num_binders: usize, value: T) -> Self {
Self { num_binders, value }
}
}
impl<T: TypeWalk> Binders<T> {
@ -906,8 +906,7 @@ impl HirDisplay for ApplicationTy {
write!(f, ") -> {}", sig.ret().display(f.db))?;
}
TypeCtor::FnDef(def) => {
let sig = f.db.callable_item_signature(def)
.subst(&self.parameters);
let sig = f.db.callable_item_signature(def).subst(&self.parameters);
let name = match def {
CallableDef::FunctionId(ff) => f.db.function_data(ff).name.clone(),
CallableDef::StructId(s) => f.db.struct_data(s).name.clone(),
@ -1037,17 +1036,19 @@ impl HirDisplay for Ty {
Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
Ty::Projection(p_ty) => p_ty.hir_fmt(f)?,
Ty::Param(id) => {
let generic_params = f.db.generic_params(id.parent);
let param_data = &generic_params.types[id.local_id];
let generics = generics(f.db, id.parent);
let param_data = &generics.params.types[id.local_id];
match param_data.provenance {
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
}
TypeParamProvenance::ArgumentImplTrait => {
write!(f, "impl TODO")?
let bounds = f.db.generic_predicates_for_param(*id);
write!(f, "impl ")?;
write_bounds_like_dyn_trait(&bounds, f)?;
}
}
},
}
Ty::Bound(idx) => write!(f, "?{}", idx)?,
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
match self {
@ -1055,66 +1056,7 @@ impl HirDisplay for Ty {
Ty::Opaque(_) => write!(f, "impl ")?,
_ => unreachable!(),
};
// Note: This code is written to produce nice results (i.e.
// corresponding to surface Rust) for types that can occur in
// actual Rust. It will have weird results if the predicates
// aren't as expected (i.e. self types = $0, projection
// predicates for a certain trait come after the Implemented
// predicate for that trait).
let mut first = true;
let mut angle_open = false;
for p in predicates.iter() {
match p {
GenericPredicate::Implemented(trait_ref) => {
if angle_open {
write!(f, ">")?;
}
if !first {
write!(f, " + ")?;
}
// We assume that the self type is $0 (i.e. the
// existential) here, which is the only thing that's
// possible in actual Rust, and hence don't print it
write!(f, "{}", f.db.trait_data(trait_ref.trait_).name.clone())?;
if trait_ref.substs.len() > 1 {
write!(f, "<")?;
f.write_joined(&trait_ref.substs[1..], ", ")?;
// there might be assoc type bindings, so we leave the angle brackets open
angle_open = true;
}
}
GenericPredicate::Projection(projection_pred) => {
// in types in actual Rust, these will always come
// after the corresponding Implemented predicate
if angle_open {
write!(f, ", ")?;
} else {
write!(f, "<")?;
angle_open = true;
}
let name =
f.db.type_alias_data(projection_pred.projection_ty.associated_ty)
.name
.clone();
write!(f, "{} = ", name)?;
projection_pred.ty.hir_fmt(f)?;
}
GenericPredicate::Error => {
if angle_open {
// impl Trait<X, {error}>
write!(f, ", ")?;
} else if !first {
// impl Trait + {error}
write!(f, " + ")?;
}
p.hir_fmt(f)?;
}
}
first = false;
}
if angle_open {
write!(f, ">")?;
}
write_bounds_like_dyn_trait(&predicates, f)?;
}
Ty::Unknown => write!(f, "{{unknown}}")?,
Ty::Infer(..) => write!(f, "_")?,
@ -1123,6 +1065,71 @@ impl HirDisplay for Ty {
}
}
fn write_bounds_like_dyn_trait(
predicates: &[GenericPredicate],
f: &mut HirFormatter<impl HirDatabase>,
) -> fmt::Result {
// Note: This code is written to produce nice results (i.e.
// corresponding to surface Rust) for types that can occur in
// actual Rust. It will have weird results if the predicates
// aren't as expected (i.e. self types = $0, projection
// predicates for a certain trait come after the Implemented
// predicate for that trait).
let mut first = true;
let mut angle_open = false;
for p in predicates.iter() {
match p {
GenericPredicate::Implemented(trait_ref) => {
if angle_open {
write!(f, ">")?;
}
if !first {
write!(f, " + ")?;
}
// We assume that the self type is $0 (i.e. the
// existential) here, which is the only thing that's
// possible in actual Rust, and hence don't print it
write!(f, "{}", f.db.trait_data(trait_ref.trait_).name.clone())?;
if trait_ref.substs.len() > 1 {
write!(f, "<")?;
f.write_joined(&trait_ref.substs[1..], ", ")?;
// there might be assoc type bindings, so we leave the angle brackets open
angle_open = true;
}
}
GenericPredicate::Projection(projection_pred) => {
// in types in actual Rust, these will always come
// after the corresponding Implemented predicate
if angle_open {
write!(f, ", ")?;
} else {
write!(f, "<")?;
angle_open = true;
}
let name =
f.db.type_alias_data(projection_pred.projection_ty.associated_ty).name.clone();
write!(f, "{} = ", name)?;
projection_pred.ty.hir_fmt(f)?;
}
GenericPredicate::Error => {
if angle_open {
// impl Trait<X, {error}>
write!(f, ", ")?;
} else if !first {
// impl Trait + {error}
write!(f, " + ")?;
}
p.hir_fmt(f)?;
}
}
first = false;
}
if angle_open {
write!(f, ">")?;
}
Ok(())
}
impl TraitRef {
fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result {
if f.should_truncate() {

View File

@ -10,12 +10,13 @@ use std::sync::Arc;
use hir_def::{
builtin_type::BuiltinType,
generics::{WherePredicate, WherePredicateTarget},
generics::{WherePredicate, WherePredicateTarget, TypeParamProvenance},
path::{GenericArg, Path, PathSegment, PathSegments},
resolver::{HasResolver, Resolver, TypeNs},
type_ref::{TypeBound, TypeRef},
AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
TypeParamId
};
use ra_arena::map::ArenaMap;
use ra_db::CrateId;
@ -30,8 +31,6 @@ use crate::{
Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs,
TraitEnvironment, TraitRef, Ty, TypeCtor,
};
use hir_def::TypeParamId;
use hir_def::generics::TypeParamProvenance;
#[derive(Debug)]
pub struct TyLoweringContext<'a, DB: HirDatabase> {

View File

@ -856,11 +856,11 @@ trait Trait<T> {
fn foo(&self) -> T;
fn foo2(&self) -> i64;
}
fn bar(impl Trait<u64>) {}
fn bar(x: impl Trait<u16>) {}
struct S<T>(T);
impl<T> Trait<T> for S<T> {}
fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
x;
y;
let z = S(1);
@ -876,27 +876,32 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
@r###"
[30; 34) 'self': &Self
[55; 59) 'self': &Self
[99; 101) '{}': ()
[111; 112) 'x': impl Trait<u64>
[131; 132) 'y': &impl Trait<u64>
[152; 269) '{ ...2(); }': ()
[158; 159) 'x': impl Trait<u64>
[165; 166) 'y': &impl Trait<u64>
[176; 177) 'z': impl Trait<u64>
[180; 183) 'bar': fn bar() -> impl Trait<u64>
[180; 185) 'bar()': impl Trait<u64>
[191; 192) 'x': impl Trait<u64>
[191; 198) 'x.foo()': u64
[204; 205) 'y': &impl Trait<u64>
[204; 211) 'y.foo()': u64
[217; 218) 'z': impl Trait<u64>
[217; 224) 'z.foo()': u64
[230; 231) 'x': impl Trait<u64>
[230; 238) 'x.foo2()': i64
[244; 245) 'y': &impl Trait<u64>
[244; 252) 'y.foo2()': i64
[258; 259) 'z': impl Trait<u64>
[258; 266) 'z.foo2()': i64
[78; 79) 'x': impl Trait<u16>
[98; 100) '{}': ()
[155; 156) 'x': impl Trait<u64>
[175; 176) 'y': &impl Trait<u32>
[196; 324) '{ ...2(); }': ()
[202; 203) 'x': impl Trait<u64>
[209; 210) 'y': &impl Trait<u32>
[220; 221) 'z': S<u16>
[224; 225) 'S': S<u16>(u16) -> S<u16>
[224; 228) 'S(1)': S<u16>
[226; 227) '1': u16
[234; 237) 'bar': fn bar<S<u16>>(S<u16>) -> ()
[234; 240) 'bar(z)': ()
[238; 239) 'z': S<u16>
[246; 247) 'x': impl Trait<u64>
[246; 253) 'x.foo()': u64
[259; 260) 'y': &impl Trait<u32>
[259; 266) 'y.foo()': u32
[272; 273) 'z': S<u16>
[272; 279) 'z.foo()': u16
[285; 286) 'x': impl Trait<u64>
[285; 293) 'x.foo2()': i64
[299; 300) 'y': &impl Trait<u32>
[299; 307) 'y.foo2()': i64
[313; 314) 'z': S<u16>
[313; 321) 'z.foo2()': i64
"###
);
}