aboutsummaryrefslogtreecommitdiff
path: root/crates/hir/src/source_analyzer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir/src/source_analyzer.rs')
-rw-r--r--crates/hir/src/source_analyzer.rs20
1 files changed, 16 insertions, 4 deletions
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index b5c65808e..3f940124c 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -143,7 +143,7 @@ impl SourceAnalyzer {
143 &self, 143 &self,
144 db: &dyn HirDatabase, 144 db: &dyn HirDatabase,
145 call: &ast::MethodCallExpr, 145 call: &ast::MethodCallExpr,
146 ) -> Option<FunctionId> { 146 ) -> Option<(FunctionId, Substitution)> {
147 let expr_id = self.expr_id(db, &call.clone().into())?; 147 let expr_id = self.expr_id(db, &call.clone().into())?;
148 self.infer.as_ref()?.method_resolution(expr_id) 148 self.infer.as_ref()?.method_resolution(expr_id)
149 } 149 }
@@ -161,7 +161,7 @@ impl SourceAnalyzer {
161 &self, 161 &self,
162 db: &dyn HirDatabase, 162 db: &dyn HirDatabase,
163 field: &ast::RecordExprField, 163 field: &ast::RecordExprField,
164 ) -> Option<(Field, Option<Local>)> { 164 ) -> Option<(Field, Option<Local>, Type)> {
165 let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?; 165 let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
166 let expr = ast::Expr::from(record_expr); 166 let expr = ast::Expr::from(record_expr);
167 let expr_id = self.body_source_map.as_ref()?.node_expr(InFile::new(self.file_id, &expr))?; 167 let expr_id = self.body_source_map.as_ref()?.node_expr(InFile::new(self.file_id, &expr))?;
@@ -178,10 +178,13 @@ impl SourceAnalyzer {
178 _ => None, 178 _ => None,
179 } 179 }
180 }; 180 };
181 let (_, subst) = self.infer.as_ref()?.type_of_expr.get(expr_id)?.as_adt()?;
181 let variant = self.infer.as_ref()?.variant_resolution_for_expr(expr_id)?; 182 let variant = self.infer.as_ref()?.variant_resolution_for_expr(expr_id)?;
182 let variant_data = variant.variant_data(db.upcast()); 183 let variant_data = variant.variant_data(db.upcast());
183 let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? }; 184 let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? };
184 Some((field.into(), local)) 185 let field_ty =
186 db.field_types(variant).get(field.local_id)?.clone().substitute(&Interner, subst);
187 Some((field.into(), local, Type::new_with_resolver(db, &self.resolver, field_ty)?))
185 } 188 }
186 189
187 pub(crate) fn resolve_record_pat_field( 190 pub(crate) fn resolve_record_pat_field(
@@ -286,7 +289,7 @@ impl SourceAnalyzer {
286 let ctx = body::LowerCtx::with_hygiene(db.upcast(), &hygiene); 289 let ctx = body::LowerCtx::with_hygiene(db.upcast(), &hygiene);
287 let hir_path = Path::from_src(path.clone(), &ctx)?; 290 let hir_path = Path::from_src(path.clone(), &ctx)?;
288 291
289 // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we 292 // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we are
290 // trying to resolve foo::bar. 293 // trying to resolve foo::bar.
291 if let Some(outer_path) = parent().and_then(ast::Path::cast) { 294 if let Some(outer_path) = parent().and_then(ast::Path::cast) {
292 if let Some(qualifier) = outer_path.qualifier() { 295 if let Some(qualifier) = outer_path.qualifier() {
@@ -295,6 +298,15 @@ impl SourceAnalyzer {
295 } 298 }
296 } 299 }
297 } 300 }
301 // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are
302 // trying to resolve foo::bar.
303 if let Some(use_tree) = parent().and_then(ast::UseTree::cast) {
304 if let Some(qualifier) = use_tree.path() {
305 if path == &qualifier && use_tree.coloncolon_token().is_some() {
306 return resolve_hir_path_qualifier(db, &self.resolver, &hir_path);
307 }
308 }
309 }
298 310
299 resolve_hir_path_(db, &self.resolver, &hir_path, prefer_value_ns) 311 resolve_hir_path_(db, &self.resolver, &hir_path, prefer_value_ns)
300 } 312 }