aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/nameres.rs23
-rw-r--r--crates/ra_hir/src/resolve.rs78
-rw-r--r--crates/ra_hir/src/ty.rs55
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap14
4 files changed, 93 insertions, 77 deletions
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index b78a178c1..b18721104 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -119,10 +119,6 @@ impl<T> PerNs<T> {
119 self.types.is_some() && self.values.is_some() 119 self.types.is_some() && self.values.is_some()
120 } 120 }
121 121
122 pub fn is_values(&self) -> bool {
123 self.values.is_some() && self.types.is_none()
124 }
125
126 pub fn take(self, namespace: Namespace) -> Option<T> { 122 pub fn take(self, namespace: Namespace) -> Option<T> {
127 match namespace { 123 match namespace {
128 Namespace::Types => self.types, 124 Namespace::Types => self.types,
@@ -671,23 +667,20 @@ impl ItemMap {
671 } 667 }
672 } 668 }
673 } 669 }
674 ModuleDef::Struct(s) => { 670 s => {
675 return ResolvePathResult::with(
676 PerNs::types((*s).into()),
677 ReachedFixedPoint::Yes,
678 Some(i),
679 );
680 }
681 _ => {
682 // could be an inherent method call in UFCS form 671 // could be an inherent method call in UFCS form
683 // (`Struct::method`), or some other kind of associated 672 // (`Struct::method`), or some other kind of associated item
684 // item... Which we currently don't handle (TODO)
685 log::debug!( 673 log::debug!(
686 "path segment {:?} resolved to non-module {:?}, but is not last", 674 "path segment {:?} resolved to non-module {:?}, but is not last",
687 segment.name, 675 segment.name,
688 curr, 676 curr,
689 ); 677 );
690 return ResolvePathResult::empty(ReachedFixedPoint::Yes); 678
679 return ResolvePathResult::with(
680 PerNs::types((*s).into()),
681 ReachedFixedPoint::Yes,
682 Some(i),
683 );
691 } 684 }
692 }; 685 };
693 } 686 }
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index 00b55eae9..9f4d4ab42 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -33,27 +33,68 @@ pub(crate) struct ExprScope {
33} 33}
34 34
35#[derive(Debug, Clone)] 35#[derive(Debug, Clone)]
36pub enum PathResult { 36pub struct PathResult {
37 /// Path was fully resolved 37 /// The actual path resolution
38 FullyResolved(PerNs<Resolution>), 38 resolution: PerNs<Resolution>,
39 /// Path was partially resolved, first element contains the resolution 39 /// The first index in the path that we
40 /// second contains the index in the Path.segments which we were unable to resolve 40 /// were unable to resolve.
41 PartiallyResolved(PerNs<Resolution>, usize), 41 /// When path is fully resolved, this is 0.
42 remaining_index: usize,
42} 43}
43 44
44impl PathResult { 45impl PathResult {
45 pub fn segment_index(&self) -> Option<usize> { 46 /// Returns the remaining index in the result
46 match self { 47 /// returns None if the path was fully resolved
47 PathResult::FullyResolved(_) => None, 48 pub fn remaining_index(&self) -> Option<usize> {
48 PathResult::PartiallyResolved(_, ref i) => Some(*i), 49 if self.remaining_index > 0 {
50 Some(self.remaining_index)
51 } else {
52 None
49 } 53 }
50 } 54 }
51 55
52 /// Consumes `PathResult` and returns the contained `PerNs<Resolution>` 56 /// Consumes `PathResult` and returns the contained `PerNs<Resolution>`
57 /// if the path was fully resolved, meaning we have no remaining items
53 pub fn into_per_ns(self) -> PerNs<Resolution> { 58 pub fn into_per_ns(self) -> PerNs<Resolution> {
54 match self { 59 if self.remaining_index().is_none() {
55 PathResult::FullyResolved(def) => def, 60 self.resolution
56 PathResult::PartiallyResolved(def, _) => def, 61 } else {
62 PerNs::none()
63 }
64 }
65
66 /// Consumes `PathResult` and returns the resolution and the
67 /// remaining_index as a tuple.
68 pub fn into_inner(self) -> (PerNs<Resolution>, Option<usize>) {
69 let index = self.remaining_index();
70 (self.resolution, index)
71 }
72
73 /// Path is fully resolved when `remaining_index` is none
74 /// and the resolution contains anything
75 pub fn is_fully_resolved(&self) -> bool {
76 !self.resolution.is_none() && self.remaining_index().is_none()
77 }
78
79 /// Empty path result is where the resolution is `none`
80 /// and the remaining index is 0
81 pub fn is_empty(&self) -> bool {
82 self.resolution.is_none() && self.remaining_index().is_none()
83 }
84
85 fn empty() -> PathResult {
86 PathResult { resolution: PerNs::none(), remaining_index: 0 }
87 }
88
89 fn from_resolution(res: PerNs<Resolution>) -> PathResult {
90 PathResult::from_resolution_with_index(res, 0)
91 }
92
93 fn from_resolution_with_index(res: PerNs<Resolution>, remaining_index: usize) -> PathResult {
94 if res.is_none() {
95 PathResult::empty()
96 } else {
97 PathResult { resolution: res, remaining_index }
57 } 98 }
58 } 99 }
59} 100}
@@ -94,24 +135,23 @@ impl Resolver {
94 } 135 }
95 136
96 pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PathResult { 137 pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PathResult {
97 use self::PathResult::*;
98 if let Some(name) = path.as_ident() { 138 if let Some(name) = path.as_ident() {
99 FullyResolved(self.resolve_name(db, name)) 139 PathResult::from_resolution(self.resolve_name(db, name))
100 } else if path.is_self() { 140 } else if path.is_self() {
101 FullyResolved(self.resolve_name(db, &Name::self_param())) 141 PathResult::from_resolution(self.resolve_name(db, &Name::self_param()))
102 } else { 142 } else {
103 let (item_map, module) = match self.module() { 143 let (item_map, module) = match self.module() {
104 Some(m) => m, 144 Some(m) => m,
105 _ => return FullyResolved(PerNs::none()), 145 _ => return PathResult::empty(),
106 }; 146 };
107 let (module_res, segment_index) = item_map.resolve_path(db, module, path); 147 let (module_res, segment_index) = item_map.resolve_path(db, module, path);
108 148
109 let def = module_res.map(Resolution::Def); 149 let def = module_res.map(Resolution::Def);
110 150
111 if let Some(index) = segment_index { 151 if let Some(index) = segment_index {
112 PartiallyResolved(def, index) 152 PathResult::from_resolution_with_index(def, index)
113 } else { 153 } else {
114 FullyResolved(def) 154 PathResult::from_resolution(def)
115 } 155 }
116 } 156 }
117 } 157 }
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 2751ab3ab..b1f35ab1f 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -32,20 +32,17 @@ use rustc_hash::FxHashMap;
32 32
33use test_utils::tested_by; 33use test_utils::tested_by;
34 34
35use ra_syntax::ast::NameOwner;
36
37use crate::{ 35use crate::{
38 Function, Struct, StructField, Enum, EnumVariant, Path, Name, 36 Function, Struct, StructField, Enum, EnumVariant, Path, Name,
39 Const,
40 FnSignature, ModuleDef, AdtDef, 37 FnSignature, ModuleDef, AdtDef,
41 HirDatabase, 38 HirDatabase,
42 type_ref::{TypeRef, Mutability}, 39 type_ref::{TypeRef, Mutability},
43 name::{KnownName, AsName}, 40 name::{KnownName},
44 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self}, 41 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self},
45 generics::GenericParams, 42 generics::GenericParams,
46 path::GenericArg, 43 path::GenericArg,
47 adt::VariantDef, 44 adt::VariantDef,
48 resolve::{Resolver, Resolution, PathResult}, nameres::Namespace 45 resolve::{Resolver, Resolution}, nameres::Namespace
49}; 46};
50 47
51/// The ID of a type variable. 48/// The ID of a type variable.
@@ -681,19 +678,6 @@ fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
681 Ty::FnDef { def: def.into(), sig, name, substs } 678 Ty::FnDef { def: def.into(), sig, name, substs }
682} 679}
683 680
684fn type_for_const(db: &impl HirDatabase, resolver: &Resolver, def: Const) -> Ty {
685 let node = def.source(db).1;
686
687 let tr = node
688 .type_ref()
689 .map(TypeRef::from_ast)
690 .as_ref()
691 .map(|tr| Ty::from_hir(db, resolver, tr))
692 .unwrap_or_else(|| Ty::Unknown);
693
694 tr
695}
696
697/// Compute the type of a tuple struct constructor. 681/// Compute the type of a tuple struct constructor.
698fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { 682fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
699 let var_data = def.variant_data(db); 683 let var_data = def.variant_data(db);
@@ -1190,21 +1174,28 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1190 fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path) -> Option<Ty> { 1174 fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path) -> Option<Ty> {
1191 let resolved = resolver.resolve_path(self.db, &path); 1175 let resolved = resolver.resolve_path(self.db, &path);
1192 1176
1193 let (resolved, segment_index) = match resolved { 1177 let (def, remaining_index) = resolved.into_inner();
1194 PathResult::FullyResolved(def) => (def.take_values()?, None), 1178
1195 PathResult::PartiallyResolved(def, index) => (def.take_types()?, Some(index)), 1179 // if the remaining_index is None, we expect the path
1196 }; 1180 // to be fully resolved, in this case we continue with
1181 // the default by attempting to `take_values´ from the resolution.
1182 // Otherwise the path was partially resolved, which means
1183 // we might have resolved into a type for which
1184 // we may find some associated item starting at the
1185 // path.segment pointed to by `remaining_index´
1186 let resolved =
1187 if remaining_index.is_none() { def.take_values()? } else { def.take_types()? };
1197 1188
1198 match resolved { 1189 match resolved {
1199 Resolution::Def(def) => { 1190 Resolution::Def(def) => {
1200 let typable: Option<TypableDef> = def.into(); 1191 let typable: Option<TypableDef> = def.into();
1201 let typable = typable?; 1192 let typable = typable?;
1202 1193
1203 if let Some(segment_index) = segment_index { 1194 if let Some(remaining_index) = remaining_index {
1204 let ty = self.db.type_for_def(typable, Namespace::Types); 1195 let ty = self.db.type_for_def(typable, Namespace::Types);
1205 // TODO: What to do if segment_index is not the last segment 1196 // TODO: Keep resolving the segments
1206 // in the path 1197 // if we have more segments to process
1207 let segment = &path.segments[segment_index]; 1198 let segment = &path.segments[remaining_index];
1208 1199
1209 // Attempt to find an impl_item for the type which has a name matching 1200 // Attempt to find an impl_item for the type which has a name matching
1210 // the current segment 1201 // the current segment
@@ -1216,17 +1207,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1216 } 1207 }
1217 None 1208 None
1218 } 1209 }
1219 crate::ImplItem::Const(c) => {
1220 let node = c.source(self.db).1;
1221
1222 if let Some(name) = node.name().map(|n| n.as_name()) {
1223 if segment.name == name {
1224 return Some(type_for_const(self.db, resolver, c));
1225 }
1226 }
1227 1210
1228 None 1211 // TODO: Resolve associated const
1229 } 1212 crate::ImplItem::Const(_) => None,
1230 1213
1231 // TODO: Resolve associated types 1214 // TODO: Resolve associated types
1232 crate::ImplItem::Type(_) => None, 1215 crate::ImplItem::Type(_) => None,
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap
index 14ab8ba96..131d1fa16 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap
@@ -1,14 +1,14 @@
1--- 1---
2created: "2019-02-20T11:04:56.553382800Z" 2created: "2019-02-21T21:51:46.497925200Z"
3creator: [email protected] 3creator: [email protected]
4source: crates/ra_hir/src/ty/tests.rs 4source: crates/ra_hir/src/ty/tests.rs
5expression: "&result" 5expression: "&result"
6--- 6---
7[227; 305) '{ ...:ID; }': () 7[227; 305) '{ ...:ID; }': ()
8[237; 238) 'x': u32 8[237; 238) 'x': [unknown]
9[241; 252) 'Struct::FOO': u32 9[241; 252) 'Struct::FOO': [unknown]
10[262; 263) 'y': u32 10[262; 263) 'y': [unknown]
11[266; 275) 'Enum::BAR': u32 11[266; 275) 'Enum::BAR': [unknown]
12[285; 286) 'z': u32 12[285; 286) 'z': [unknown]
13[289; 302) 'TraitTest::ID': u32 13[289; 302) 'TraitTest::ID': [unknown]
14 14