aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir_ty/src/infer.rs7
-rw-r--r--crates/ra_hir_ty/src/lib.rs153
-rw-r--r--crates/ra_hir_ty/src/lower.rs5
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs51
4 files changed, 115 insertions, 101 deletions
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index 0d65984ee..8d5b7c943 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -479,8 +479,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
479 479
480 fn collect_fn(&mut self, data: &FunctionData) { 480 fn collect_fn(&mut self, data: &FunctionData) {
481 let body = Arc::clone(&self.body); // avoid borrow checker problem 481 let body = Arc::clone(&self.body); // avoid borrow checker problem
482 for (type_ref, pat) in data.params.iter().zip(body.params.iter()) { 482 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver).with_impl_trait_mode(ImplTraitLoweringMode::Param);
483 let ty = self.make_ty_with_mode(type_ref, 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);
484 487
485 self.infer_pat(*pat, &ty, BindingMode::default()); 488 self.infer_pat(*pat, &ty, BindingMode::default());
486 } 489 }
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 1e162943c..6eccd7fa8 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -44,11 +44,11 @@ use std::sync::Arc;
44use std::{fmt, iter, mem}; 44use std::{fmt, iter, mem};
45 45
46use hir_def::{ 46use hir_def::{
47 expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId, 47 expr::ExprId, generics::TypeParamProvenance, type_ref::Mutability, AdtId, AssocContainerId,
48 HasModule, Lookup, TraitId, TypeAliasId, TypeParamId, generics::TypeParamProvenance, 48 DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, TypeParamId,
49}; 49};
50use ra_db::{impl_intern_key, salsa, CrateId};
51use hir_expand::name::Name; 50use hir_expand::name::Name;
51use ra_db::{impl_intern_key, salsa, CrateId};
52 52
53use crate::{ 53use crate::{
54 db::HirDatabase, 54 db::HirDatabase,
@@ -360,9 +360,7 @@ impl Substs {
360 360
361 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). 361 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
362 pub(crate) fn type_params(generic_params: &Generics) -> Substs { 362 pub(crate) fn type_params(generic_params: &Generics) -> Substs {
363 Substs( 363 Substs(generic_params.iter().map(|(id, _)| Ty::Param(id)).collect())
364 generic_params.iter().map(|(id, _)| Ty::Param(id)).collect(),
365 )
366 } 364 }
367 365
368 /// Return Substs that replace each parameter by a bound variable. 366 /// Return Substs that replace each parameter by a bound variable.
@@ -448,7 +446,9 @@ pub struct Binders<T> {
448} 446}
449 447
450impl<T> Binders<T> { 448impl<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 }
452} 452}
453 453
454impl<T: TypeWalk> Binders<T> { 454impl<T: TypeWalk> Binders<T> {
@@ -906,8 +906,7 @@ impl HirDisplay for ApplicationTy {
906 write!(f, ") -> {}", sig.ret().display(f.db))?; 906 write!(f, ") -> {}", sig.ret().display(f.db))?;
907 } 907 }
908 TypeCtor::FnDef(def) => { 908 TypeCtor::FnDef(def) => {
909 let sig = f.db.callable_item_signature(def) 909 let sig = f.db.callable_item_signature(def).subst(&self.parameters);
910 .subst(&self.parameters);
911 let name = match def { 910 let name = match def {
912 CallableDef::FunctionId(ff) => f.db.function_data(ff).name.clone(), 911 CallableDef::FunctionId(ff) => f.db.function_data(ff).name.clone(),
913 CallableDef::StructId(s) => f.db.struct_data(s).name.clone(), 912 CallableDef::StructId(s) => f.db.struct_data(s).name.clone(),
@@ -1037,17 +1036,19 @@ impl HirDisplay for Ty {
1037 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, 1036 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
1038 Ty::Projection(p_ty) => p_ty.hir_fmt(f)?, 1037 Ty::Projection(p_ty) => p_ty.hir_fmt(f)?,
1039 Ty::Param(id) => { 1038 Ty::Param(id) => {
1040 let generic_params = f.db.generic_params(id.parent); 1039 let generics = generics(f.db, id.parent);
1041 let param_data = &generic_params.types[id.local_id]; 1040 let param_data = &generics.params.types[id.local_id];
1042 match param_data.provenance { 1041 match param_data.provenance {
1043 TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => { 1042 TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
1044 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? 1043 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
1045 } 1044 }
1046 TypeParamProvenance::ArgumentImplTrait => { 1045 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)?;
1048 } 1049 }
1049 } 1050 }
1050 }, 1051 }
1051 Ty::Bound(idx) => write!(f, "?{}", idx)?, 1052 Ty::Bound(idx) => write!(f, "?{}", idx)?,
1052 Ty::Dyn(predicates) | Ty::Opaque(predicates) => { 1053 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
1053 match self { 1054 match self {
@@ -1055,66 +1056,7 @@ impl HirDisplay for Ty {
1055 Ty::Opaque(_) => write!(f, "impl ")?, 1056 Ty::Opaque(_) => write!(f, "impl ")?,
1056 _ => unreachable!(), 1057 _ => unreachable!(),
1057 }; 1058 };
1058 // Note: This code is written to produce nice results (i.e. 1059 write_bounds_like_dyn_trait(&predicates, f)?;
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 }
1118 } 1060 }
1119 Ty::Unknown => write!(f, "{{unknown}}")?, 1061 Ty::Unknown => write!(f, "{{unknown}}")?,
1120 Ty::Infer(..) => write!(f, "_")?, 1062 Ty::Infer(..) => write!(f, "_")?,
@@ -1123,6 +1065,71 @@ impl HirDisplay for Ty {
1123 } 1065 }
1124} 1066}
1125 1067
1068fn 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
1126impl TraitRef { 1133impl TraitRef {
1127 fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result { 1134 fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result {
1128 if f.should_truncate() { 1135 if f.should_truncate() {
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index 42367b181..e375c4847 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -10,12 +10,13 @@ use std::sync::Arc;
10 10
11use hir_def::{ 11use hir_def::{
12 builtin_type::BuiltinType, 12 builtin_type::BuiltinType,
13 generics::{WherePredicate, WherePredicateTarget}, 13 generics::{WherePredicate, WherePredicateTarget, TypeParamProvenance},
14 path::{GenericArg, Path, PathSegment, PathSegments}, 14 path::{GenericArg, Path, PathSegment, PathSegments},
15 resolver::{HasResolver, Resolver, TypeNs}, 15 resolver::{HasResolver, Resolver, TypeNs},
16 type_ref::{TypeBound, TypeRef}, 16 type_ref::{TypeBound, TypeRef},
17 AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, 17 AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
18 LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, 18 LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
19 TypeParamId
19}; 20};
20use ra_arena::map::ArenaMap; 21use ra_arena::map::ArenaMap;
21use ra_db::CrateId; 22use ra_db::CrateId;
@@ -30,8 +31,6 @@ use crate::{
30 Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs, 31 Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs,
31 TraitEnvironment, TraitRef, Ty, TypeCtor, 32 TraitEnvironment, TraitRef, Ty, TypeCtor,
32}; 33};
33use hir_def::TypeParamId;
34use hir_def::generics::TypeParamProvenance;
35 34
36#[derive(Debug)] 35#[derive(Debug)]
37pub struct TyLoweringContext<'a, DB: HirDatabase> { 36pub struct TyLoweringContext<'a, DB: HirDatabase> {
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index e6f697fa3..bae5eae07 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -856,11 +856,11 @@ trait Trait<T> {
856 fn foo(&self) -> T; 856 fn foo(&self) -> T;
857 fn foo2(&self) -> i64; 857 fn foo2(&self) -> i64;
858} 858}
859fn bar(impl Trait<u64>) {} 859fn bar(x: impl Trait<u16>) {}
860struct S<T>(T); 860struct S<T>(T);
861impl<T> Trait<T> for S<T> {} 861impl<T> Trait<T> for S<T> {}
862 862
863fn test(x: impl Trait<u64>, y: &impl Trait<u64>) { 863fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
864 x; 864 x;
865 y; 865 y;
866 let z = S(1); 866 let z = S(1);
@@ -876,27 +876,32 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
876 @r###" 876 @r###"
877 [30; 34) 'self': &Self 877 [30; 34) 'self': &Self
878 [55; 59) 'self': &Self 878 [55; 59) 'self': &Self
879 [99; 101) '{}': () 879 [78; 79) 'x': impl Trait<u16>
880 [111; 112) 'x': impl Trait<u64> 880 [98; 100) '{}': ()
881 [131; 132) 'y': &impl Trait<u64> 881 [155; 156) 'x': impl Trait<u64>
882 [152; 269) '{ ...2(); }': () 882 [175; 176) 'y': &impl Trait<u32>
883 [158; 159) 'x': impl Trait<u64> 883 [196; 324) '{ ...2(); }': ()
884 [165; 166) 'y': &impl Trait<u64> 884 [202; 203) 'x': impl Trait<u64>
885 [176; 177) 'z': impl Trait<u64> 885 [209; 210) 'y': &impl Trait<u32>
886 [180; 183) 'bar': fn bar() -> impl Trait<u64> 886 [220; 221) 'z': S<u16>
887 [180; 185) 'bar()': impl Trait<u64> 887 [224; 225) 'S': S<u16>(u16) -> S<u16>
888 [191; 192) 'x': impl Trait<u64> 888 [224; 228) 'S(1)': S<u16>
889 [191; 198) 'x.foo()': u64 889 [226; 227) '1': u16
890 [204; 205) 'y': &impl Trait<u64> 890 [234; 237) 'bar': fn bar<S<u16>>(S<u16>) -> ()
891 [204; 211) 'y.foo()': u64 891 [234; 240) 'bar(z)': ()
892 [217; 218) 'z': impl Trait<u64> 892 [238; 239) 'z': S<u16>
893 [217; 224) 'z.foo()': u64 893 [246; 247) 'x': impl Trait<u64>
894 [230; 231) 'x': impl Trait<u64> 894 [246; 253) 'x.foo()': u64
895 [230; 238) 'x.foo2()': i64 895 [259; 260) 'y': &impl Trait<u32>
896 [244; 245) 'y': &impl Trait<u64> 896 [259; 266) 'y.foo()': u32
897 [244; 252) 'y.foo2()': i64 897 [272; 273) 'z': S<u16>
898 [258; 259) 'z': impl Trait<u64> 898 [272; 279) 'z.foo()': u16
899 [258; 266) 'z.foo2()': i64 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
900 "### 905 "###
901 ); 906 );
902} 907}