diff options
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r-- | crates/ra_hir_ty/src/infer.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lib.rs | 153 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 51 |
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; | |||
44 | use std::{fmt, iter, mem}; | 44 | use std::{fmt, iter, mem}; |
45 | 45 | ||
46 | use hir_def::{ | 46 | use 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 | }; |
50 | use ra_db::{impl_intern_key, salsa, CrateId}; | ||
51 | use hir_expand::name::Name; | 50 | use hir_expand::name::Name; |
51 | use ra_db::{impl_intern_key, salsa, CrateId}; | ||
52 | 52 | ||
53 | use crate::{ | 53 | use 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 | ||
450 | impl<T> Binders<T> { | 448 | 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 | } | ||
452 | } | 452 | } |
453 | 453 | ||
454 | impl<T: TypeWalk> Binders<T> { | 454 | impl<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 | ||
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 | |||
1126 | impl TraitRef { | 1133 | impl 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 | ||
11 | use hir_def::{ | 11 | use 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 | }; |
20 | use ra_arena::map::ArenaMap; | 21 | use ra_arena::map::ArenaMap; |
21 | use ra_db::CrateId; | 22 | use 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 | }; |
33 | use hir_def::TypeParamId; | ||
34 | use hir_def::generics::TypeParamProvenance; | ||
35 | 34 | ||
36 | #[derive(Debug)] | 35 | #[derive(Debug)] |
37 | pub struct TyLoweringContext<'a, DB: HirDatabase> { | 36 | pub 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 | } |
859 | fn bar(impl Trait<u64>) {} | 859 | fn bar(x: impl Trait<u16>) {} |
860 | struct S<T>(T); | 860 | struct S<T>(T); |
861 | impl<T> Trait<T> for S<T> {} | 861 | impl<T> Trait<T> for S<T> {} |
862 | 862 | ||
863 | fn test(x: impl Trait<u64>, y: &impl Trait<u64>) { | 863 | fn 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 | } |