about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2022-04-06 20:22:12 +0200
committerLukas Wirth <lukastw97@gmail.com>2022-04-06 20:24:24 +0200
commit4a1423337ff311e81fd19c4166f08559b33f8b5b (patch)
treee66bfd3602f4741f8f1876f961da97ba069b0d18
parent7959c248761081fc9d38c84d0d8b0ad60d20771d (diff)
downloadrust-4a1423337ff311e81fd19c4166f08559b33f8b5b.tar.gz
rust-4a1423337ff311e81fd19c4166f08559b33f8b5b.zip
fix: Attempt to resolve paths in const arguments heuristically
While we don't support const args in type inference yet, we can at least
make use of the fallback path resolution to resolve paths in const args
in the IDE layer to enable some features for them.
-rw-r--r--crates/hir/src/source_analyzer.rs84
-rw-r--r--crates/hir_def/src/item_tree/lower.rs6
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_general.html1
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs1
4 files changed, 51 insertions, 41 deletions
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index e96c4007407..c9eb134e943 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -299,45 +299,53 @@ impl SourceAnalyzer {
         let parent = || parent.clone();
 
         let mut prefer_value_ns = false;
-        if let Some(path_expr) = parent().and_then(ast::PathExpr::cast) {
-            let expr_id = self.expr_id(db, &path_expr.into())?;
-            let infer = self.infer.as_ref()?;
-            if let Some(assoc) = infer.assoc_resolutions_for_expr(expr_id) {
-                return Some(PathResolution::Def(AssocItem::from(assoc).into()));
-            }
-            if let Some(VariantId::EnumVariantId(variant)) =
-                infer.variant_resolution_for_expr(expr_id)
-            {
-                return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
-            }
-            prefer_value_ns = true;
-        } else if let Some(path_pat) = parent().and_then(ast::PathPat::cast) {
-            let pat_id = self.pat_id(&path_pat.into())?;
-            if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) {
-                return Some(PathResolution::Def(AssocItem::from(assoc).into()));
-            }
-            if let Some(VariantId::EnumVariantId(variant)) =
-                self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
-            {
-                return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
-            }
-        } else if let Some(rec_lit) = parent().and_then(ast::RecordExpr::cast) {
-            let expr_id = self.expr_id(db, &rec_lit.into())?;
-            if let Some(VariantId::EnumVariantId(variant)) =
-                self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
-            {
-                return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
-            }
-        }
-
-        let record_pat = parent().and_then(ast::RecordPat::cast).map(ast::Pat::from);
-        let tuple_struct_pat = || parent().and_then(ast::TupleStructPat::cast).map(ast::Pat::from);
-        if let Some(pat) = record_pat.or_else(tuple_struct_pat) {
-            let pat_id = self.pat_id(&pat)?;
-            let variant_res_for_pat = self.infer.as_ref()?.variant_resolution_for_pat(pat_id);
-            if let Some(VariantId::EnumVariantId(variant)) = variant_res_for_pat {
-                return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
+        let resolved = (|| {
+            if let Some(path_expr) = parent().and_then(ast::PathExpr::cast) {
+                let expr_id = self.expr_id(db, &path_expr.into())?;
+                let infer = self.infer.as_ref()?;
+                if let Some(assoc) = infer.assoc_resolutions_for_expr(expr_id) {
+                    return Some(PathResolution::Def(AssocItem::from(assoc).into()));
+                }
+                if let Some(VariantId::EnumVariantId(variant)) =
+                    infer.variant_resolution_for_expr(expr_id)
+                {
+                    return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
+                }
+                prefer_value_ns = true;
+            } else if let Some(path_pat) = parent().and_then(ast::PathPat::cast) {
+                let pat_id = self.pat_id(&path_pat.into())?;
+                if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) {
+                    return Some(PathResolution::Def(AssocItem::from(assoc).into()));
+                }
+                if let Some(VariantId::EnumVariantId(variant)) =
+                    self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
+                {
+                    return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
+                }
+            } else if let Some(rec_lit) = parent().and_then(ast::RecordExpr::cast) {
+                let expr_id = self.expr_id(db, &rec_lit.into())?;
+                if let Some(VariantId::EnumVariantId(variant)) =
+                    self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
+                {
+                    return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
+                }
+            } else {
+                let record_pat = parent().and_then(ast::RecordPat::cast).map(ast::Pat::from);
+                let tuple_struct_pat =
+                    || parent().and_then(ast::TupleStructPat::cast).map(ast::Pat::from);
+                if let Some(pat) = record_pat.or_else(tuple_struct_pat) {
+                    let pat_id = self.pat_id(&pat)?;
+                    let variant_res_for_pat =
+                        self.infer.as_ref()?.variant_resolution_for_pat(pat_id);
+                    if let Some(VariantId::EnumVariantId(variant)) = variant_res_for_pat {
+                        return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
+                    }
+                }
             }
+            None
+        })();
+        if let resolved @ Some(_) = resolved {
+            return resolved;
         }
 
         // This must be a normal source file rather than macro file.
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 3fa2d9d32cc..d6c5feefa32 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -295,13 +295,13 @@ impl<'a> Ctx<'a> {
                         let mut pat = param.pat();
                         // FIXME: This really shouldn't be here, in fact FunctionData/ItemTree's function shouldn't know about
                         // pattern names at all
-                        let name = loop {
+                        let name = 'name: loop {
                             match pat {
                                 Some(ast::Pat::RefPat(ref_pat)) => pat = ref_pat.pat(),
                                 Some(ast::Pat::IdentPat(ident)) => {
-                                    break ident.name().map(|it| it.as_name())
+                                    break 'name ident.name().map(|it| it.as_name())
                                 }
-                                _ => break None,
+                                _ => break 'name None,
                             }
                         };
                         self.data().params.alloc(Param::Normal(name, ty))
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
index 1abb6eb8f39..7bb7ddd2804 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
@@ -118,6 +118,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">fn</span> <span class="function declaration">const_param</span><span class="angle">&lt;</span><span class="keyword">const</span> <span class="const_param declaration">FOO</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">usize</span> <span class="brace">{</span>
+    <span class="function">const_param</span><span class="operator">::</span><span class="angle">&lt;</span><span class="brace">{</span> <span class="const_param">FOO</span> <span class="brace">}</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="const_param">FOO</span>
 <span class="brace">}</span>
 
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index d7686695942..e436a0574b5 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -172,6 +172,7 @@ fn never() -> ! {
 }
 
 fn const_param<const FOO: usize>() -> usize {
+    const_param::<{ FOO }>();
     FOO
 }