aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/lower.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/lower.rs')
-rw-r--r--crates/ra_hir/src/ty/lower.rs108
1 files changed, 53 insertions, 55 deletions
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 946e9e9fb..3fdb2ca92 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -19,7 +19,7 @@ use crate::{
19 generics::{GenericDef, WherePredicate}, 19 generics::{GenericDef, WherePredicate},
20 nameres::Namespace, 20 nameres::Namespace,
21 path::{GenericArg, PathSegment}, 21 path::{GenericArg, PathSegment},
22 resolve::{Resolution, Resolver}, 22 resolve::{Resolver, TypeNs},
23 ty::Adt, 23 ty::Adt,
24 type_ref::{TypeBound, TypeRef}, 24 type_ref::{TypeBound, TypeRef},
25 BuiltinType, Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField, 25 BuiltinType, Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField,
@@ -88,16 +88,47 @@ impl Ty {
88 88
89 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { 89 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty {
90 // Resolve the path (in type namespace) 90 // Resolve the path (in type namespace)
91 let (resolution, remaining_index) = resolver.resolve_path_segments(db, path).into_inner(); 91 let (resolution, remaining_index) = match resolver.resolve_path_in_type_ns(db, path) {
92 let resolution = resolution.take_types(); 92 Some(it) => it,
93 93 None => return Ty::Unknown,
94 let def = match resolution { 94 };
95 Some(Resolution::Def(def)) => def, 95
96 Some(Resolution::LocalBinding(..)) => { 96 let typable: TypableDef = match resolution {
97 // this should never happen 97 TypeNs::Trait(trait_) => {
98 panic!("path resolved to local binding in type ns"); 98 let segment = match remaining_index {
99 None => path.segments.last().expect("resolved path has at least one element"),
100 Some(i) => &path.segments[i - 1],
101 };
102 let trait_ref = TraitRef::from_resolved_path(db, resolver, trait_, segment, None);
103 return if let Some(remaining_index) = remaining_index {
104 if remaining_index == path.segments.len() - 1 {
105 let segment = &path.segments[remaining_index];
106 match trait_ref
107 .trait_
108 .associated_type_by_name_including_super_traits(db, &segment.name)
109 {
110 Some(associated_ty) => {
111 // FIXME handle type parameters on the segment
112 Ty::Projection(ProjectionTy {
113 associated_ty,
114 parameters: trait_ref.substs,
115 })
116 }
117 None => {
118 // associated type not found
119 Ty::Unknown
120 }
121 }
122 } else {
123 // FIXME more than one segment remaining, is this possible?
124 Ty::Unknown
125 }
126 } else {
127 // FIXME dyn Trait without the dyn
128 Ty::Unknown
129 };
99 } 130 }
100 Some(Resolution::GenericParam(idx)) => { 131 TypeNs::GenericParam(idx) => {
101 if remaining_index.is_some() { 132 if remaining_index.is_some() {
102 // e.g. T::Item 133 // e.g. T::Item
103 return Ty::Unknown; 134 return Ty::Unknown;
@@ -111,57 +142,24 @@ impl Ty {
111 .clone(), 142 .clone(),
112 }; 143 };
113 } 144 }
114 Some(Resolution::SelfType(impl_block)) => { 145 TypeNs::SelfType(impl_block) => {
115 if remaining_index.is_some() { 146 if remaining_index.is_some() {
116 // e.g. Self::Item 147 // e.g. Self::Item
117 return Ty::Unknown; 148 return Ty::Unknown;
118 } 149 }
119 return impl_block.target_ty(db); 150 return impl_block.target_ty(db);
120 } 151 }
121 None => { 152
122 // path did not resolve 153 TypeNs::Adt(it) => it.into(),
123 return Ty::Unknown; 154 TypeNs::BuiltinType(it) => it.into(),
124 } 155 TypeNs::TypeAlias(it) => it.into(),
156 // FIXME: report error
157 TypeNs::EnumVariant(_) => return Ty::Unknown,
125 }; 158 };
126 159
127 if let ModuleDef::Trait(trait_) = def { 160 let ty = db.type_for_def(typable, Namespace::Types);
128 let segment = match remaining_index { 161 let substs = Ty::substs_from_path(db, resolver, path, typable);
129 None => path.segments.last().expect("resolved path has at least one element"), 162 ty.subst(&substs)
130 Some(i) => &path.segments[i - 1],
131 };
132 let trait_ref = TraitRef::from_resolved_path(db, resolver, trait_, segment, None);
133 if let Some(remaining_index) = remaining_index {
134 if remaining_index == path.segments.len() - 1 {
135 let segment = &path.segments[remaining_index];
136 let associated_ty = match trait_ref
137 .trait_
138 .associated_type_by_name_including_super_traits(db, &segment.name)
139 {
140 Some(t) => t,
141 None => {
142 // associated type not found
143 return Ty::Unknown;
144 }
145 };
146 // FIXME handle type parameters on the segment
147 Ty::Projection(ProjectionTy { associated_ty, parameters: trait_ref.substs })
148 } else {
149 // FIXME more than one segment remaining, is this possible?
150 Ty::Unknown
151 }
152 } else {
153 // FIXME dyn Trait without the dyn
154 Ty::Unknown
155 }
156 } else {
157 let typable: TypableDef = match def.into() {
158 None => return Ty::Unknown,
159 Some(it) => it,
160 };
161 let ty = db.type_for_def(typable, Namespace::Types);
162 let substs = Ty::substs_from_path(db, resolver, path, typable);
163 ty.subst(&substs)
164 }
165 } 163 }
166 164
167 pub(super) fn substs_from_path_segment( 165 pub(super) fn substs_from_path_segment(
@@ -278,8 +276,8 @@ impl TraitRef {
278 path: &Path, 276 path: &Path,
279 explicit_self_ty: Option<Ty>, 277 explicit_self_ty: Option<Ty>,
280 ) -> Option<Self> { 278 ) -> Option<Self> {
281 let resolved = match resolver.resolve_path_without_assoc_items(db, &path).take_types()? { 279 let resolved = match resolver.resolve_path_in_type_ns_fully(db, &path)? {
282 Resolution::Def(ModuleDef::Trait(tr)) => tr, 280 TypeNs::Trait(tr) => tr,
283 _ => return None, 281 _ => return None,
284 }; 282 };
285 let segment = path.segments.last().expect("path should have at least one segment"); 283 let segment = path.segments.last().expect("path should have at least one segment");