Repository: rust-analyzer/rust-analyzer
Pull request #8819 (2021-05-13 02:55:20)

Use package root as `cargo check` working directory
Cargo commands are affected by the `.cargo/config` files above
their working directory. If cargo is invoked from above the directory
holding `Cargo.toml`, it may not pick up important settings like
registry replacements, causing it to behave differently or even fail.

Most cargo invocations are currently setting their working directories
to the directory containing `Cargo.toml`, but a couple of paths remain
in which cargo is invoked from the default workspace root instead.

This change fixes that, resolving some cargo check failures that I
experienced in a multi-root workspace in which packages used different
registries.


Patch:
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs
index 1682d8bde2..93cf6a3d68 100644
--- a/crates/flycheck/src/lib.rs
+++ b/crates/flycheck/src/lib.rs
@@ -215,6 +215,7 @@ impl FlycheckActor {
             } => {
                 let mut cmd = Command::new(toolchain::cargo());
                 cmd.arg(command);
+                cmd.current_dir(&self.workspace_root);
                 cmd.args(&["--workspace", "--message-format=json", "--manifest-path"])
                     .arg(self.workspace_root.join("Cargo.toml"));
 
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 6233bca83a..c9ef4b4205 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -873,10 +873,6 @@ impl Function {
         db.function_data(self.id).is_unsafe()
     }
 
-    pub fn is_async(self, db: &dyn HirDatabase) -> bool {
-        db.function_data(self.id).is_async()
-    }
-
     pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
         let krate = self.module(db).id.krate();
         hir_def::diagnostics::validate_body(db.upcast(), self.id.into(), sink);
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index 98b485b602..8360426f13 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -21,6 +21,8 @@ use profile::Count;
 use rustc_hash::FxHashMap;
 use syntax::{ast, AstNode, AstPtr};
 
+pub use lower::LowerCtx;
+
 use crate::{
     attr::{Attrs, RawAttrs},
     db::DefDatabase,
@@ -33,8 +35,6 @@ use crate::{
     UnresolvedMacro,
 };
 
-pub use lower::LowerCtx;
-
 /// A subset of Expander that only deals with cfg attributes. We only need it to
 /// avoid cyclic queries in crate def map during enum processing.
 #[derive(Debug)]
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs
index ee52794aa8..858e880381 100644
--- a/crates/hir_def/src/find_path.rs
+++ b/crates/hir_def/src/find_path.rs
@@ -5,10 +5,10 @@ use std::iter;
 use hir_expand::name::{known, AsName, Name};
 use rustc_hash::FxHashSet;
 
+use crate::nameres::DefMap;
 use crate::{
     db::DefDatabase,
     item_scope::ItemInNs,
-    nameres::DefMap,
     path::{ModPath, PathKind},
     visibility::Visibility,
     ModuleDefId, ModuleId,
@@ -134,16 +134,7 @@ fn find_path_inner(
     for (name, def_id) in root_def_map.extern_prelude() {
         if item == ItemInNs::Types(*def_id) {
             let name = scope_name.unwrap_or_else(|| name.clone());
-
-            let name_already_occupied_in_type_ns = def_map
-                .with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
-                    def_map[local_id].scope.get(&name).take_types().filter(|&id| id != *def_id)
-                })
-                .is_some();
-            return Some(ModPath::from_segments(
-                if name_already_occupied_in_type_ns { PathKind::Abs } else { PathKind::Plain },
-                vec![name],
-            ));
+            return Some(ModPath::from_segments(PathKind::Plain, vec![name]));
         }
     }
 
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 280c25f111..af98021441 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -118,7 +118,6 @@ register_builtin! {
     EAGER:
     (compile_error, CompileError) => compile_error_expand,
     (concat, Concat) => concat_expand,
-    (concat_idents, ConcatIdents) => concat_idents_expand,
     (include, Include) => include_expand,
     (include_bytes, IncludeBytes) => include_bytes_expand,
     (include_str, IncludeStr) => include_str_expand,
@@ -374,28 +373,6 @@ fn concat_expand(
     ExpandResult { value: Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)), err }
 }
 
-fn concat_idents_expand(
-    _db: &dyn AstDatabase,
-    _arg_id: EagerMacroId,
-    tt: &tt::Subtree,
-) -> ExpandResult<Option<ExpandedEager>> {
-    let mut err = None;
-    let mut ident = String::new();
-    for (i, t) in tt.token_trees.iter().enumerate() {
-        match t {
-            tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => {
-                ident.push_str(id.text.as_str());
-            }
-            tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
-            _ => {
-                err.get_or_insert(mbe::ExpandError::UnexpectedToken);
-            }
-        }
-    }
-    let ident = tt::Ident { text: ident.into(), id: tt::TokenId::unspecified() };
-    ExpandResult { value: Some(ExpandedEager::new(quote!(#ident), FragmentKind::Expr)), err }
-}
-
 fn relative_file(
     db: &dyn AstDatabase,
     call_id: MacroCallId,
@@ -817,16 +794,4 @@ mod tests {
             expect![[r#""foor0bar\nfalse""#]],
         );
     }
-
-    #[test]
-    fn test_concat_idents_expand() {
-        check_expansion(
-            r##"
-            #[rustc_builtin_macro]
-            macro_rules! concat_idents {}
-            concat_idents!(foo, bar);
-            "##,
-            expect![[r#"foobar"#]],
-        );
-    }
 }
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs
index 5a5dc9afdb..bcfd3e5242 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -212,7 +212,6 @@ pub mod known {
         std_panic,
         stringify,
         concat,
-        concat_idents,
         include,
         include_bytes,
         include_str,
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index 320694a17a..cb5a8e19a9 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -29,8 +29,7 @@ pub(crate) type DocumentationLink = String;
 /// Rewrite documentation links in markdown to point to an online host (e.g. docs.rs)
 pub(crate) fn rewrite_links(db: &RootDatabase, markdown: &str, definition: &Definition) -> String {
     let mut cb = broken_link_clone_cb;
-    let doc =
-        Parser::new_with_broken_link_callback(markdown, Options::ENABLE_TASKLISTS, Some(&mut cb));
+    let doc = Parser::new_with_broken_link_callback(markdown, Options::empty(), Some(&mut cb));
 
     let doc = map_links(doc, |target, title: &str| {
         // This check is imperfect, there's some overlap between valid intra-doc links
@@ -65,7 +64,8 @@ pub(crate) fn rewrite_links(db: &RootDatabase, markdown: &str, definition: &Defi
 pub(crate) fn remove_links(markdown: &str) -> String {
     let mut drop_link = false;
 
-    let opts = Options::ENABLE_TASKLISTS | Options::ENABLE_FOOTNOTES;
+    let mut opts = Options::empty();
+    opts.insert(Options::ENABLE_FOOTNOTES);
 
     let mut cb = |_: BrokenLink| {
         let empty = InlineStr::try_from("").unwrap();
@@ -123,7 +123,7 @@ pub(crate) fn extract_definitions_from_markdown(
 ) -> Vec<(TextRange, String, Option<hir::Namespace>)> {
     Parser::new_with_broken_link_callback(
         markdown,
-        Options::ENABLE_TASKLISTS,
+        Options::empty(),
         Some(&mut broken_link_clone_cb),
     )
     .into_offset_iter()
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index baed8e2170..b586dcc179 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -227,8 +227,8 @@ pub(super) fn element(
         k if k.is_keyword() => {
             let h = Highlight::new(HlTag::Keyword);
             match k {
-                T![await] => h | HlMod::Async | HlMod::ControlFlow,
-                T![break]
+                T![await]
+                | T![break]
                 | T![continue]
                 | T![else]
                 | T![if]
@@ -255,7 +255,6 @@ pub(super) fn element(
                     })
                     .map(|modifier| h | modifier)
                     .unwrap_or(h),
-                T![async] => h | HlMod::Async,
                 _ => h,
             }
         }
@@ -311,9 +310,6 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
                 if func.is_unsafe(db) {
                     h |= HlMod::Unsafe;
                 }
-                if func.is_async(db) {
-                    h |= HlMod::Async;
-                }
                 return h;
             }
             hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HlTag::Symbol(SymbolKind::Struct),
@@ -413,9 +409,6 @@ fn highlight_method_call(
     if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) {
         h |= HlMod::Unsafe;
     }
-    if func.is_async(sema.db) {
-        h |= HlMod::Async;
-    }
     if func.as_assoc_item(sema.db).and_then(|it| it.containing_trait(sema.db)).is_some() {
         h |= HlMod::Trait
     }
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs
index f4a2e7506a..a304b32506 100644
--- a/crates/ide/src/syntax_highlighting/tags.rs
+++ b/crates/ide/src/syntax_highlighting/tags.rs
@@ -65,8 +65,6 @@ pub enum HlMod {
     Static,
     /// Used for items in traits and trait impls.
     Trait,
-    /// Used with keywords like `async` and `await`.
-    Async,
     // Keep this last!
     /// Used for unsafe functions, mutable statics, union accesses and unsafe operations.
     Unsafe,
@@ -188,7 +186,6 @@ impl HlMod {
         HlMod::Mutable,
         HlMod::Static,
         HlMod::Trait,
-        HlMod::Async,
         HlMod::Unsafe,
     ];
 
@@ -206,7 +203,6 @@ impl HlMod {
             HlMod::Mutable => "mutable",
             HlMod::Static => "static",
             HlMod::Trait => "trait",
-            HlMod::Async => "async",
             HlMod::Unsafe => "unsafe",
         }
     }
diff --git a/crates/ide_assists/src/handlers/auto_import.rs b/crates/ide_assists/src/handlers/auto_import.rs
index 506cc292c4..a454a2af32 100644
--- a/crates/ide_assists/src/handlers/auto_import.rs
+++ b/crates/ide_assists/src/handlers/auto_import.rs
@@ -966,32 +966,6 @@ mod bar {
         println!("Hallo");
     }
 }
-"#,
-        );
-    }
-
-    #[test]
-    fn uses_abs_path_with_extern_crate_clash() {
-        check_assist(
-            auto_import,
-            r#"
-//- /main.rs crate:main deps:foo
-mod foo {}
-
-const _: () = {
-    Foo$0
-};
-//- /foo.rs crate:foo
-pub struct Foo
-"#,
-            r#"
-use ::foo::Foo;
-
-mod foo {}
-
-const _: () = {
-    Foo
-};
 "#,
         );
     }
diff --git a/crates/ide_assists/src/handlers/move_module_to_file.rs b/crates/ide_assists/src/handlers/move_module_to_file.rs
index 93f702c556..6e685b4b29 100644
--- a/crates/ide_assists/src/handlers/move_module_to_file.rs
+++ b/crates/ide_assists/src/handlers/move_module_to_file.rs
@@ -1,4 +1,4 @@
-use ast::edit::IndentLevel;
+use ast::{edit::IndentLevel, VisibilityOwner};
 use ide_db::base_db::AnchoredPathBuf;
 use stdx::format_to;
 use syntax::{
@@ -60,18 +60,12 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Opt
             };
 
             let mut buf = String::new();
+            if let Some(v) = module_ast.visibility() {
+                format_to!(buf, "{} ", v);
+            }
             format_to!(buf, "mod {};", module_name);
 
-            let replacement_start = if let Some(mod_token) = module_ast.mod_token() {
-                mod_token.text_range().start()
-            } else {
-                module_ast.syntax().text_range().start()
-            };
-
-            builder.replace(
-                TextRange::new(replacement_start, module_ast.syntax().text_range().end()),
-                buf,
-            );
+            builder.replace(module_ast.syntax().text_range(), buf);
 
             let dst = AnchoredPathBuf { anchor: ctx.frange.file_id, path };
             builder.create_file(dst, contents);
@@ -190,26 +184,4 @@ pub(crate) mod tests;
         cov_mark::check!(available_before_curly);
         check_assist_not_applicable(move_module_to_file, r#"mod m { $0 }"#);
     }
-
-    #[test]
-    fn keep_outer_comments_and_attributes() {
-        check_assist(
-            move_module_to_file,
-            r#"
-/// doc comment
-#[attribute]
-mod $0tests {
-    #[test] fn t() {}
-}
-"#,
-            r#"
-//- /main.rs
-/// doc comment
-#[attribute]
-mod tests;
-//- /tests.rs
-#[test] fn t() {}
-"#,
-        );
-    }
 }
diff --git a/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs b/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs
index a3bfa221c2..0fec961b43 100644
--- a/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs
+++ b/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs
@@ -17,7 +17,7 @@ use ide_db::ty_filter::TryEnum;
 
 // Assist: replace_unwrap_with_match
 //
-// Replaces `unwrap` with a `match` expression. Works for Result and Option.
+// Replaces `unwrap` a `match` expression. Works for Result and Option.
 //
 // ```
 // enum Result<T, E> { Ok(T), Err(E) }
diff --git a/crates/project_model/src/build_data.rs b/crates/project_model/src/build_data.rs
index 7b88dca630..3aa546980c 100644
--- a/crates/project_model/src/build_data.rs
+++ b/crates/project_model/src/build_data.rs
@@ -143,6 +143,7 @@ impl WorkspaceBuildData {
             cmd.env("RA_RUSTC_WRAPPER", "1");
         }
 
+        cmd.current_dir(cargo_toml.parent().unwrap());
         cmd.args(&["check", "--quiet", "--workspace", "--message-format=json", "--manifest-path"])
             .arg(cargo_toml.as_ref());
 
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs
index c9d38693e8..ecab89b2a8 100644
--- a/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/crates/rust-analyzer/src/semantic_tokens.rs
@@ -91,7 +91,6 @@ define_semantic_token_modifiers![
     (INJECTED, "injected"),
     (MUTABLE, "mutable"),
     (CONSUMING, "consuming"),
-    (ASYNC, "async"),
     (UNSAFE, "unsafe"),
     (ATTRIBUTE_MODIFIER, "attribute"),
     (TRAIT_MODIFIER, "trait"),
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 8ce4aa2423..ecf6fd12fe 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -496,7 +496,6 @@ fn semantic_token_type_and_modifiers(
             HlMod::ControlFlow => semantic_tokens::CONTROL_FLOW,
             HlMod::Mutable => semantic_tokens::MUTABLE,
             HlMod::Consuming => semantic_tokens::CONSUMING,
-            HlMod::Async => semantic_tokens::ASYNC,
             HlMod::Unsafe => semantic_tokens::UNSAFE,
             HlMod::Callable => semantic_tokens::CALLABLE,
             HlMod::Static => lsp_types::SemanticTokenModifier::STATIC,
diff --git a/crates/syntax/src/parsing.rs b/crates/syntax/src/parsing.rs
index 431ed06999..333bde54ab 100644
--- a/crates/syntax/src/parsing.rs
+++ b/crates/syntax/src/parsing.rs
@@ -6,13 +6,14 @@ mod text_token_source;
 mod text_tree_sink;
 mod reparsing;
 
-use parser::SyntaxKind;
+use crate::{syntax_node::GreenNode, AstNode, SyntaxError, SyntaxNode};
 use text_token_source::TextTokenSource;
 use text_tree_sink::TextTreeSink;
 
-use crate::{syntax_node::GreenNode, AstNode, SyntaxError, SyntaxNode};
+pub(crate) use lexer::*;
 
-pub(crate) use crate::parsing::{lexer::*, reparsing::incremental_reparse};
+pub(crate) use self::reparsing::incremental_reparse;
+use parser::SyntaxKind;
 
 pub(crate) fn parse_text(text: &str) -> (GreenNode, Vec<SyntaxError>) {
     let (tokens, lexer_errors) = tokenize(&text);
diff --git a/docs/dev/style.md b/docs/dev/style.md
index 9b0ddec662..d24a5952ed 100644
--- a/docs/dev/style.md
+++ b/docs/dev/style.md
@@ -636,10 +636,6 @@ use crate::{}
 
 // Finally, parent and child modules, but prefer `use crate::`.
 use super::{}
-
-// Re-exports are treated as item definitions rather than imports, so they go
-// after imports and modules. Use them sparingly.
-pub use crate::x::Z;
 ```
 
 **Rationale:** consistency.
@@ -698,9 +694,6 @@ Avoid local `use MyEnum::*` imports.
 Prefer `use crate::foo::bar` to `use super::bar` or `use self::bar::baz`.
 **Rationale:** consistency, this is the style which works in all cases.
 
-By default, avoid re-exports.
-**Rationale:** for non-library code, re-exports introduce two ways to use something and allow for inconsistency.
-
 ## Order of Items
 
 Optimize for the reader who sees the file for the first time, and wants to get a general idea about what's going on.


Test patch:
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index 33bc6b0f3b..df41921949 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
@@ -234,15 +234,4 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
             <span class="variable declaration">Nope</span> <span class="operator">=&gt;</span> <span class="variable">Nope</span><span class="comma">,</span>
         <span class="brace">}</span>
     <span class="brace">}</span>
-<span class="brace">}</span>
-
-<span class="keyword async">async</span> <span class="keyword">fn</span> <span class="function declaration async">learn_and_sing</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
-    <span class="keyword">let</span> <span class="variable declaration">song</span> <span class="operator">=</span> <span class="unresolved_reference">learn_song</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="operator">.</span><span class="keyword control async">await</span><span class="semicolon">;</span>
-    <span class="unresolved_reference">sing_song</span><span class="parenthesis">(</span><span class="variable consuming">song</span><span class="parenthesis">)</span><span class="operator">.</span><span class="keyword control async">await</span><span class="semicolon">;</span>
-<span class="brace">}</span>
-
-<span class="keyword async">async</span> <span class="keyword">fn</span> <span class="function declaration async">async_main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
-    <span class="keyword">let</span> <span class="variable declaration">f1</span> <span class="operator">=</span> <span class="function async">learn_and_sing</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="keyword">let</span> <span class="variable declaration">f2</span> <span class="operator">=</span> <span class="unresolved_reference">dance</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    futures::<span class="macro">join!</span><span class="parenthesis">(</span>f1<span class="comma">,</span> f2<span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span></code></pre>
\ No newline at end of file
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index 32f2d9038e..b6e952b088 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -208,17 +208,6 @@ impl<T> Option<T> {
         }
     }
 }
-
-async fn learn_and_sing() {
-    let song = learn_song().await;
-    sing_song(song).await;
-}
-
-async fn async_main() {
-    let f1 = learn_and_sing();
-    let f2 = dance();
-    futures::join!(f1, f2);
-}
 "#
         .trim(),
         expect_file!["./test_data/highlighting.html"],