diff options
Diffstat (limited to 'crates/ra_hir_ty/src/lib.rs')
-rw-r--r-- | crates/ra_hir_ty/src/lib.rs | 153 |
1 files changed, 80 insertions, 73 deletions
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() { |