Repository: rust-analyzer/rust-analyzer
Pull request #8076 (2021-03-17 21:30:31)

Add test for self-calling inner function
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/4438 (and duplicates)

bors r+


Patch:
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index fce09a9e71..2a79c892b5 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -333,19 +333,17 @@ fn concat_expand(
 fn relative_file(
     db: &dyn AstDatabase,
     call_id: MacroCallId,
-    path_str: &str,
+    path: &str,
     allow_recursion: bool,
-) -> Result<FileId, mbe::ExpandError> {
+) -> Option<FileId> {
     let call_site = call_id.as_file().original_file(db);
-    let path = AnchoredPath { anchor: call_site, path: path_str };
-    let res = db
-        .resolve_path(path)
-        .ok_or_else(|| mbe::ExpandError::Other(format!("failed to load file `{}`", path_str)))?;
+    let path = AnchoredPath { anchor: call_site, path };
+    let res = db.resolve_path(path)?;
     // Prevent include itself
     if res == call_site && !allow_recursion {
-        Err(mbe::ExpandError::Other(format!("recursive inclusion of `{}`", path_str)))
+        None
     } else {
-        Ok(res)
+        Some(res)
     }
 }
 
@@ -366,7 +364,8 @@ fn include_expand(
 ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
     let res = (|| {
         let path = parse_string(tt)?;
-        let file_id = relative_file(db, arg_id.into(), &path, false)?;
+        let file_id = relative_file(db, arg_id.into(), &path, false)
+            .ok_or_else(|| mbe::ExpandError::ConversionError)?;
 
         Ok(parse_to_token_tree(&db.file_text(file_id))
             .ok_or_else(|| mbe::ExpandError::ConversionError)?
@@ -418,8 +417,8 @@ fn include_str_expand(
     // Ideally, we'd be able to offer a precise expansion if the user asks for macro
     // expansion.
     let file_id = match relative_file(db, arg_id.into(), &path, true) {
-        Ok(file_id) => file_id,
-        Err(_) => {
+        Some(file_id) => file_id,
+        None => {
             return ExpandResult::ok(Some((quote!(""), FragmentKind::Expr)));
         }
     };


Test patch:
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs
index faa1332970..f8e6f70e87 100644
--- a/crates/hir_def/src/body/tests.rs
+++ b/crates/hir_def/src/body/tests.rs
@@ -137,7 +137,7 @@ fn f() {
     include!(invalid);
   //^^^^^^^^^^^^^^^^^ could not convert tokens
     include!("does not exist");
-  //^^^^^^^^^^^^^^^^^^^^^^^^^^ failed to load file `does not exist`
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^ could not convert tokens
 
     env!(invalid);
   //^^^^^^^^^^^^^ could not convert tokens
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index a89061c2e8..6becd9ff1e 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -196,7 +196,7 @@ fn builtin_macro_fails_expansion() {
           macro_rules! include { () => {} }
 
           include!("doesntexist");
-        //^^^^^^^^^^^^^^^^^^^^^^^^ failed to load file `doesntexist`
+        //^^^^^^^^^^^^^^^^^^^^^^^^ could not convert tokens
         "#,
     );
 }
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 93d3ad020a..8270fa2193 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -3253,3 +3253,24 @@ fn f() {
         "#,
     );
 }
+
+#[test]
+fn nested_inner_function_calling_self() {
+    check_infer(
+        r#"
+struct S;
+fn f() {
+    fn inner() -> S {
+        let s = inner();
+    }
+}
+        "#,
+        expect![[r#"
+            17..73 '{     ...   } }': ()
+            39..71 '{     ...     }': ()
+            53..54 's': S
+            57..62 'inner': fn inner() -> S
+            57..64 'inner()': S
+        "#]],
+    )
+}