Skip to content

Commit 3397ca6

Browse files
committed
Fix APIT some more
1 parent c6654fd commit 3397ca6

File tree

4 files changed

+115
-101
lines changed

4 files changed

+115
-101
lines changed

crates/ra_hir_ty/src/infer.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,8 +479,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
479479

480480
fn collect_fn(&mut self, data: &FunctionData) {
481481
let body = Arc::clone(&self.body); // avoid borrow checker problem
482-
for (type_ref, pat) in data.params.iter().zip(body.params.iter()) {
483-
let ty = self.make_ty_with_mode(type_ref, ImplTraitLoweringMode::Param);
482+
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver).with_impl_trait_mode(ImplTraitLoweringMode::Param);
483+
let param_tys = data.params.iter().map(|type_ref| Ty::from_hir(&ctx, type_ref)).collect::<Vec<_>>();
484+
for (ty, pat) in param_tys.into_iter().zip(body.params.iter()) {
485+
let ty = self.insert_type_vars(ty);
486+
let ty = self.normalize_associated_types_in(ty);
484487

485488
self.infer_pat(*pat, &ty, BindingMode::default());
486489
}

crates/ra_hir_ty/src/lib.rs

Lines changed: 80 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ use std::sync::Arc;
4444
use std::{fmt, iter, mem};
4545

4646
use hir_def::{
47-
expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId,
48-
HasModule, Lookup, TraitId, TypeAliasId, TypeParamId, generics::TypeParamProvenance,
47+
expr::ExprId, generics::TypeParamProvenance, type_ref::Mutability, AdtId, AssocContainerId,
48+
DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, TypeParamId,
4949
};
50-
use ra_db::{impl_intern_key, salsa, CrateId};
5150
use hir_expand::name::Name;
51+
use ra_db::{impl_intern_key, salsa, CrateId};
5252

5353
use crate::{
5454
db::HirDatabase,
@@ -360,9 +360,7 @@ impl Substs {
360360

361361
/// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
362362
pub(crate) fn type_params(generic_params: &Generics) -> Substs {
363-
Substs(
364-
generic_params.iter().map(|(id, _)| Ty::Param(id)).collect(),
365-
)
363+
Substs(generic_params.iter().map(|(id, _)| Ty::Param(id)).collect())
366364
}
367365

368366
/// Return Substs that replace each parameter by a bound variable.
@@ -448,7 +446,9 @@ pub struct Binders<T> {
448446
}
449447

450448
impl<T> Binders<T> {
451-
pub fn new(num_binders: usize, value: T) -> Self { Self { num_binders, value } }
449+
pub fn new(num_binders: usize, value: T) -> Self {
450+
Self { num_binders, value }
451+
}
452452
}
453453

454454
impl<T: TypeWalk> Binders<T> {
@@ -906,8 +906,7 @@ impl HirDisplay for ApplicationTy {
906906
write!(f, ") -> {}", sig.ret().display(f.db))?;
907907
}
908908
TypeCtor::FnDef(def) => {
909-
let sig = f.db.callable_item_signature(def)
910-
.subst(&self.parameters);
909+
let sig = f.db.callable_item_signature(def).subst(&self.parameters);
911910
let name = match def {
912911
CallableDef::FunctionId(ff) => f.db.function_data(ff).name.clone(),
913912
CallableDef::StructId(s) => f.db.struct_data(s).name.clone(),
@@ -1037,84 +1036,27 @@ impl HirDisplay for Ty {
10371036
Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
10381037
Ty::Projection(p_ty) => p_ty.hir_fmt(f)?,
10391038
Ty::Param(id) => {
1040-
let generic_params = f.db.generic_params(id.parent);
1041-
let param_data = &generic_params.types[id.local_id];
1039+
let generics = generics(f.db, id.parent);
1040+
let param_data = &generics.params.types[id.local_id];
10421041
match param_data.provenance {
10431042
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
10441043
write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
10451044
}
10461045
TypeParamProvenance::ArgumentImplTrait => {
1047-
write!(f, "impl TODO")?
1046+
let bounds = f.db.generic_predicates_for_param(*id);
1047+
write!(f, "impl ")?;
1048+
write_bounds_like_dyn_trait(&bounds, f)?;
10481049
}
10491050
}
1050-
},
1051+
}
10511052
Ty::Bound(idx) => write!(f, "?{}", idx)?,
10521053
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
10531054
match self {
10541055
Ty::Dyn(_) => write!(f, "dyn ")?,
10551056
Ty::Opaque(_) => write!(f, "impl ")?,
10561057
_ => unreachable!(),
10571058
};
1058-
// Note: This code is written to produce nice results (i.e.
1059-
// corresponding to surface Rust) for types that can occur in
1060-
// actual Rust. It will have weird results if the predicates
1061-
// aren't as expected (i.e. self types = $0, projection
1062-
// predicates for a certain trait come after the Implemented
1063-
// predicate for that trait).
1064-
let mut first = true;
1065-
let mut angle_open = false;
1066-
for p in predicates.iter() {
1067-
match p {
1068-
GenericPredicate::Implemented(trait_ref) => {
1069-
if angle_open {
1070-
write!(f, ">")?;
1071-
}
1072-
if !first {
1073-
write!(f, " + ")?;
1074-
}
1075-
// We assume that the self type is $0 (i.e. the
1076-
// existential) here, which is the only thing that's
1077-
// possible in actual Rust, and hence don't print it
1078-
write!(f, "{}", f.db.trait_data(trait_ref.trait_).name.clone())?;
1079-
if trait_ref.substs.len() > 1 {
1080-
write!(f, "<")?;
1081-
f.write_joined(&trait_ref.substs[1..], ", ")?;
1082-
// there might be assoc type bindings, so we leave the angle brackets open
1083-
angle_open = true;
1084-
}
1085-
}
1086-
GenericPredicate::Projection(projection_pred) => {
1087-
// in types in actual Rust, these will always come
1088-
// after the corresponding Implemented predicate
1089-
if angle_open {
1090-
write!(f, ", ")?;
1091-
} else {
1092-
write!(f, "<")?;
1093-
angle_open = true;
1094-
}
1095-
let name =
1096-
f.db.type_alias_data(projection_pred.projection_ty.associated_ty)
1097-
.name
1098-
.clone();
1099-
write!(f, "{} = ", name)?;
1100-
projection_pred.ty.hir_fmt(f)?;
1101-
}
1102-
GenericPredicate::Error => {
1103-
if angle_open {
1104-
// impl Trait<X, {error}>
1105-
write!(f, ", ")?;
1106-
} else if !first {
1107-
// impl Trait + {error}
1108-
write!(f, " + ")?;
1109-
}
1110-
p.hir_fmt(f)?;
1111-
}
1112-
}
1113-
first = false;
1114-
}
1115-
if angle_open {
1116-
write!(f, ">")?;
1117-
}
1059+
write_bounds_like_dyn_trait(&predicates, f)?;
11181060
}
11191061
Ty::Unknown => write!(f, "{{unknown}}")?,
11201062
Ty::Infer(..) => write!(f, "_")?,
@@ -1123,6 +1065,71 @@ impl HirDisplay for Ty {
11231065
}
11241066
}
11251067

1068+
fn write_bounds_like_dyn_trait(
1069+
predicates: &[GenericPredicate],
1070+
f: &mut HirFormatter<impl HirDatabase>,
1071+
) -> fmt::Result {
1072+
// Note: This code is written to produce nice results (i.e.
1073+
// corresponding to surface Rust) for types that can occur in
1074+
// actual Rust. It will have weird results if the predicates
1075+
// aren't as expected (i.e. self types = $0, projection
1076+
// predicates for a certain trait come after the Implemented
1077+
// predicate for that trait).
1078+
let mut first = true;
1079+
let mut angle_open = false;
1080+
for p in predicates.iter() {
1081+
match p {
1082+
GenericPredicate::Implemented(trait_ref) => {
1083+
if angle_open {
1084+
write!(f, ">")?;
1085+
}
1086+
if !first {
1087+
write!(f, " + ")?;
1088+
}
1089+
// We assume that the self type is $0 (i.e. the
1090+
// existential) here, which is the only thing that's
1091+
// possible in actual Rust, and hence don't print it
1092+
write!(f, "{}", f.db.trait_data(trait_ref.trait_).name.clone())?;
1093+
if trait_ref.substs.len() > 1 {
1094+
write!(f, "<")?;
1095+
f.write_joined(&trait_ref.substs[1..], ", ")?;
1096+
// there might be assoc type bindings, so we leave the angle brackets open
1097+
angle_open = true;
1098+
}
1099+
}
1100+
GenericPredicate::Projection(projection_pred) => {
1101+
// in types in actual Rust, these will always come
1102+
// after the corresponding Implemented predicate
1103+
if angle_open {
1104+
write!(f, ", ")?;
1105+
} else {
1106+
write!(f, "<")?;
1107+
angle_open = true;
1108+
}
1109+
let name =
1110+
f.db.type_alias_data(projection_pred.projection_ty.associated_ty).name.clone();
1111+
write!(f, "{} = ", name)?;
1112+
projection_pred.ty.hir_fmt(f)?;
1113+
}
1114+
GenericPredicate::Error => {
1115+
if angle_open {
1116+
// impl Trait<X, {error}>
1117+
write!(f, ", ")?;
1118+
} else if !first {
1119+
// impl Trait + {error}
1120+
write!(f, " + ")?;
1121+
}
1122+
p.hir_fmt(f)?;
1123+
}
1124+
}
1125+
first = false;
1126+
}
1127+
if angle_open {
1128+
write!(f, ">")?;
1129+
}
1130+
Ok(())
1131+
}
1132+
11261133
impl TraitRef {
11271134
fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result {
11281135
if f.should_truncate() {

crates/ra_hir_ty/src/lower.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ use std::sync::Arc;
1010

1111
use hir_def::{
1212
builtin_type::BuiltinType,
13-
generics::{WherePredicate, WherePredicateTarget},
13+
generics::{WherePredicate, WherePredicateTarget, TypeParamProvenance},
1414
path::{GenericArg, Path, PathSegment, PathSegments},
1515
resolver::{HasResolver, Resolver, TypeNs},
1616
type_ref::{TypeBound, TypeRef},
1717
AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
1818
LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
19+
TypeParamId
1920
};
2021
use ra_arena::map::ArenaMap;
2122
use ra_db::CrateId;
@@ -30,8 +31,6 @@ use crate::{
3031
Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs,
3132
TraitEnvironment, TraitRef, Ty, TypeCtor,
3233
};
33-
use hir_def::TypeParamId;
34-
use hir_def::generics::TypeParamProvenance;
3534

3635
#[derive(Debug)]
3736
pub struct TyLoweringContext<'a, DB: HirDatabase> {

crates/ra_hir_ty/src/tests/traits.rs

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -856,11 +856,11 @@ trait Trait<T> {
856856
fn foo(&self) -> T;
857857
fn foo2(&self) -> i64;
858858
}
859-
fn bar(impl Trait<u64>) {}
859+
fn bar(x: impl Trait<u16>) {}
860860
struct S<T>(T);
861861
impl<T> Trait<T> for S<T> {}
862862
863-
fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
863+
fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
864864
x;
865865
y;
866866
let z = S(1);
@@ -876,27 +876,32 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
876876
@r###"
877877
[30; 34) 'self': &Self
878878
[55; 59) 'self': &Self
879-
[99; 101) '{}': ()
880-
[111; 112) 'x': impl Trait<u64>
881-
[131; 132) 'y': &impl Trait<u64>
882-
[152; 269) '{ ...2(); }': ()
883-
[158; 159) 'x': impl Trait<u64>
884-
[165; 166) 'y': &impl Trait<u64>
885-
[176; 177) 'z': impl Trait<u64>
886-
[180; 183) 'bar': fn bar() -> impl Trait<u64>
887-
[180; 185) 'bar()': impl Trait<u64>
888-
[191; 192) 'x': impl Trait<u64>
889-
[191; 198) 'x.foo()': u64
890-
[204; 205) 'y': &impl Trait<u64>
891-
[204; 211) 'y.foo()': u64
892-
[217; 218) 'z': impl Trait<u64>
893-
[217; 224) 'z.foo()': u64
894-
[230; 231) 'x': impl Trait<u64>
895-
[230; 238) 'x.foo2()': i64
896-
[244; 245) 'y': &impl Trait<u64>
897-
[244; 252) 'y.foo2()': i64
898-
[258; 259) 'z': impl Trait<u64>
899-
[258; 266) 'z.foo2()': i64
879+
[78; 79) 'x': impl Trait<u16>
880+
[98; 100) '{}': ()
881+
[155; 156) 'x': impl Trait<u64>
882+
[175; 176) 'y': &impl Trait<u32>
883+
[196; 324) '{ ...2(); }': ()
884+
[202; 203) 'x': impl Trait<u64>
885+
[209; 210) 'y': &impl Trait<u32>
886+
[220; 221) 'z': S<u16>
887+
[224; 225) 'S': S<u16>(u16) -> S<u16>
888+
[224; 228) 'S(1)': S<u16>
889+
[226; 227) '1': u16
890+
[234; 237) 'bar': fn bar<S<u16>>(S<u16>) -> ()
891+
[234; 240) 'bar(z)': ()
892+
[238; 239) 'z': S<u16>
893+
[246; 247) 'x': impl Trait<u64>
894+
[246; 253) 'x.foo()': u64
895+
[259; 260) 'y': &impl Trait<u32>
896+
[259; 266) 'y.foo()': u32
897+
[272; 273) 'z': S<u16>
898+
[272; 279) 'z.foo()': u16
899+
[285; 286) 'x': impl Trait<u64>
900+
[285; 293) 'x.foo2()': i64
901+
[299; 300) 'y': &impl Trait<u32>
902+
[299; 307) 'y.foo2()': i64
903+
[313; 314) 'z': S<u16>
904+
[313; 321) 'z.foo2()': i64
900905
"###
901906
);
902907
}

0 commit comments

Comments
 (0)