Repository: rust-analyzer/rust-analyzer (rust)

Issue:
Null response on signature help after whitespace
Given

    fn test(_a:i8, _b:i8){}
    fn main() {
        // This works.
        test(<CURSOR>
    }

Requesting `textDocument/signatureHelp` works as expected. However, if a user inserts a space and the client then re-requests `textDocument/signatureHelp`, with the new location, the response is null. I.e.

    fn test(_a:i8, _b:i8){}
    fn main() {
        // Null response
        test( <CURSOR>
    }

Here are the messages exchanged between ycmd and rust-analyzer:

```
2021-04-14 23:35:04,083 - DEBUG - TX: Sending message: b'Content-Length: 1332\r\n\r\n{"id":1,"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{"experimental":{"serverStatusNotification":true,"statusNotification":true},"textDocument":{"codeAction":{"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}}},"completion":{"completionItem":{"documentationFormat":["plaintext","markdown"]},"completionItemKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]}},"documentSymbol":{"hierarchicalDocumentSymbolSupport":false,"labelSupport":false,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}},"hover":{"contentFormat":["plaintext","markdown"]},"signatureHelp":{"signatureInformation":{"documentationFormat":["plaintext","markdown"],"parameterInformation":{"labelOffsetSupport":true}}},"synchronization":{"didSave":true}},"workspace":{"applyEdit":true,"configuration":true,"didChangeWatchedFiles":{"dynamicRegistration":true},"symbol":{"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}},"workspaceEdit":{"documentChanges":true}}},"initializationOptions":{},"processId":6540,"rootPath":"/home/bstaletic/work/test/r","rootUri":"file:///home/bstaletic/work/test/r"}}'
2021-04-14 23:35:04,085 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","id":1,"result":{"capabilities":{"textDocumentSync":{"openClose":true,"change":2,"save":{}},"selectionRangeProvider":true,"hoverProvider":true,"completionProvider":{"triggerCharacters":[":",".","\'"]},"signatureHelpProvider":{"triggerCharacters":["(",","]},"definitionProvider":true,"typeDefinitionProvider":true,"implementationProvider":true,"referencesProvider":true,"documentHighlightProvider":true,"documentSymbolProvider":true,"workspaceSymbolProvider":true,"codeActionProvider":{"codeActionKinds":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite"],"resolveProvider":true},"codeLensProvider":{"resolveProvider":true},"documentFormattingProvider":true,"documentOnTypeFormattingProvider":{"firstTriggerCharacter":"=","moreTriggerCharacter":[".",">"]},"renameProvider":{"prepareProvider":true},"foldingRangeProvider":true,"workspace":{"fileOperations":{"willRename":{"filters":[{"scheme":"file","pattern":{"glob":"**/*.rs","matches":"file"}},{"scheme":"file","pattern":{"glob":"**","matches":"folder"}}]}}},"callHierarchyProvider":true,"semanticTokensProvider":{"legend":{"tokenTypes":["comment","keyword","string","number","regexp","operator","namespace","type","struct","class","interface","enum","enumMember","typeParameter","function","method","property","macro","variable","parameter","angle","attribute","boolean","brace","bracket","builtinType","characterLiteral","colon","comma","constParameter","dot","escapeSequence","formatSpecifier","generic","label","lifetime","parenthesis","punctuation","selfKeyword","semicolon","typeAlias","union","unresolvedReference"],"tokenModifiers":["documentation","declaration","definition","static","abstract","deprecated","readonly","constant","controlFlow","injected","mutable","consuming","unsafe","attribute","trait","callable","intraDocLink"]},"range":true,"full":{"delta":true}},"experimental":{"joinLines":true,"ssr":true,"onEnter":true,"parentModule":true,"runnables":{"kinds":["cargo"]}}},"serverInfo":{"name":"rust-analyzer","version":"2021-04-05"}}}'
2021-04-14 23:35:04,086 - DEBUG - TX: Sending notification: b'Content-Length: 52\r\n\r\n{"jsonrpc":"2.0","method":"initialized","params":{}}'
2021-04-14 23:35:04,086 - DEBUG - TX: Sending notification: b'Content-Length: 86\r\n\r\n{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{}}}'
2021-04-14 23:35:04,087 - DEBUG - TX: Sending notification: b'Content-Length: 226\r\n\r\n{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"languageId":"rust","text":"fn test(_a:i8, _b:i8){}\\nfn main() {\\n    test(\\n}\\n","uri":"file:///home/bstaletic/work/test/r/src/main.rs","version":1}}}'
2021-04-14 23:35:04,093 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","id":0,"method":"workspace/configuration","params":{"items":[{"section":"rust-analyzer"}]}}'
2021-04-14 23:35:04,094 - DEBUG - TX: Sending response: b'Content-Length: 40\r\n\r\n{"id":0,"jsonrpc":"2.0","result":[null]}'
2021-04-14 23:35:04,197 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","id":1,"method":"client/registerCapability","params":{"registrations":[{"id":"workspace/didChangeWatchedFiles","method":"workspace/didChangeWatchedFiles","registerOptions":{"watchers":[{"globPattern":"/home/bstaletic/work/test/r/**/*.rs"}]}}]}}'
2021-04-14 23:35:04,200 - DEBUG - TX: Sending response: b'Content-Length: 38\r\n\r\n{"id":1,"jsonrpc":"2.0","result":null}'
2021-04-14 23:35:04,227 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","method":"rust-analyzer/status","params":{"status":"readyPartial"}}'
2021-04-14 23:35:04,256 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","id":2,"method":"client/registerCapability","params":{"registrations":[{"id":"workspace/didChangeWatchedFiles","method":"workspace/didChangeWatchedFiles","registerOptions":{"watchers":[{"globPattern":"/home/bstaletic/work/test/r/**/*.rs"}]}}]}}'
2021-04-14 23:35:04,258 - DEBUG - TX: Sending response: b'Content-Length: 38\r\n\r\n{"id":2,"jsonrpc":"2.0","result":null}'
2021-04-14 23:35:04,264 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","method":"rust-analyzer/status","params":{"status":"loading"}}'
2021-04-14 23:35:04,271 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","method":"rust-analyzer/status","params":{"status":"ready"}}'
2021-04-14 23:35:04,353 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","diagnostics":[{"range":{"start":{"line":3,"character":0},"end":{"line":3,"character":1}},"severity":1,"source":"rustc","message":"mismatched closing delimiter: `}`\\nmismatched closing delimiter","relatedInformation":[{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":1,"character":10},"end":{"line":1,"character":11}}},"message":"closing delimiter possibly meant for this"},{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":2,"character":8},"end":{"line":2,"character":9}}},"message":"unclosed delimiter"}]},{"range":{"start":{"line":1,"character":10},"end":{"line":1,"character":11}},"severity":4,"source":"rustc","message":"closing delimiter possibly meant for this","relatedInformation":[{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":3,"character":0},"end":{"line":3,"character":1}}},"message":"original diagnostic"}]},{"range":{"start":{"line":2,"character":8},"end":{"line":2,"character":9}},"severity":4,"source":"rustc","message":"unclosed delimiter","relatedInformation":[{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":3,"character":0},"end":{"line":3,"character":1}}},"message":"original diagnostic"}]}],"version":1}}'
2021-04-14 23:35:04,366 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","diagnostics":[{"range":{"start":{"line":3,"character":0},"end":{"line":3,"character":1}},"severity":1,"source":"rustc","message":"mismatched closing delimiter: `}`\\nmismatched closing delimiter","relatedInformation":[{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":1,"character":10},"end":{"line":1,"character":11}}},"message":"closing delimiter possibly meant for this"},{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":2,"character":8},"end":{"line":2,"character":9}}},"message":"unclosed delimiter"}]},{"range":{"start":{"line":1,"character":10},"end":{"line":1,"character":11}},"severity":4,"source":"rustc","message":"closing delimiter possibly meant for this","relatedInformation":[{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":3,"character":0},"end":{"line":3,"character":1}}},"message":"original diagnostic"}]},{"range":{"start":{"line":2,"character":8},"end":{"line":2,"character":9}},"severity":4,"source":"rustc","message":"unclosed delimiter","relatedInformation":[{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":3,"character":0},"end":{"line":3,"character":1}}},"message":"original diagnostic"}]},{"range":{"start":{"line":2,"character":4},"end":{"line":2,"character":8}},"severity":1,"code":"E0061","codeDescription":{"href":"https://doc.rust-lang.org/error-index.html#E0061"},"source":"rustc","message":"this function takes 2 arguments but 0 arguments were supplied\\nexpected 2 arguments","relatedInformation":[{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":2,"character":8},"end":{"line":3,"character":1}}},"message":"supplied 0 arguments"},{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":0,"character":3},"end":{"line":0,"character":7}}},"message":"function defined here"}]},{"range":{"start":{"line":2,"character":8},"end":{"line":3,"character":1}},"severity":4,"code":"E0061","codeDescription":{"href":"https://doc.rust-lang.org/error-index.html#E0061"},"source":"rustc","message":"supplied 0 arguments","relatedInformation":[{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":2,"character":4},"end":{"line":2,"character":8}}},"message":"original diagnostic"}]},{"range":{"start":{"line":0,"character":3},"end":{"line":0,"character":7}},"severity":4,"code":"E0061","codeDescription":{"href":"https://doc.rust-lang.org/error-index.html#E0061"},"source":"rustc","message":"function defined here","relatedInformation":[{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":2,"character":4},"end":{"line":2,"character":8}}},"message":"original diagnostic"}]}],"version":1}}'
2021-04-14 23:35:08,356 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","diagnostics":[{"range":{"start":{"line":2,"character":9},"end":{"line":2,"character":9}},"severity":1,"source":"rust-analyzer","message":"Syntax Error: expected expression"},{"range":{"start":{"line":2,"character":4},"end":{"line":2,"character":9}},"severity":1,"code":"mismatched-arg-count","codeDescription":{"href":"https://rust-analyzer.github.io/manual.html#mismatched-arg-count"},"source":"rust-analyzer","message":"Expected 2 arguments, found 0"},{"range":{"start":{"line":3,"character":0},"end":{"line":3,"character":1}},"severity":1,"source":"rustc","message":"mismatched closing delimiter: `}`\\nmismatched closing delimiter","relatedInformation":[{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":1,"character":10},"end":{"line":1,"character":11}}},"message":"closing delimiter possibly meant for this"},{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":2,"character":8},"end":{"line":2,"character":9}}},"message":"unclosed delimiter"}]},{"range":{"start":{"line":1,"character":10},"end":{"line":1,"character":11}},"severity":4,"source":"rustc","message":"closing delimiter possibly meant for this","relatedInformation":[{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":3,"character":0},"end":{"line":3,"character":1}}},"message":"original diagnostic"}]},{"range":{"start":{"line":2,"character":8},"end":{"line":2,"character":9}},"severity":4,"source":"rustc","message":"unclosed delimiter","relatedInformation":[{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":3,"character":0},"end":{"line":3,"character":1}}},"message":"original diagnostic"}]},{"range":{"start":{"line":2,"character":4},"end":{"line":2,"character":8}},"severity":1,"code":"E0061","codeDescription":{"href":"https://doc.rust-lang.org/error-index.html#E0061"},"source":"rustc","message":"this function takes 2 arguments but 0 arguments were supplied\\nexpected 2 arguments","relatedInformation":[{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":2,"character":8},"end":{"line":3,"character":1}}},"message":"supplied 0 arguments"},{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":0,"character":3},"end":{"line":0,"character":7}}},"message":"function defined here"}]},{"range":{"start":{"line":2,"character":8},"end":{"line":3,"character":1}},"severity":4,"code":"E0061","codeDescription":{"href":"https://doc.rust-lang.org/error-index.html#E0061"},"source":"rustc","message":"supplied 0 arguments","relatedInformation":[{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":2,"character":4},"end":{"line":2,"character":8}}},"message":"original diagnostic"}]},{"range":{"start":{"line":0,"character":3},"end":{"line":0,"character":7}},"severity":4,"code":"E0061","codeDescription":{"href":"https://doc.rust-lang.org/error-index.html#E0061"},"source":"rustc","message":"function defined here","relatedInformation":[{"location":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","range":{"start":{"line":2,"character":4},"end":{"line":2,"character":8}}},"message":"original diagnostic"}]}],"version":1}}'
2021-04-14 23:35:12,488 - DEBUG - TX: Sending message: b'Content-Length: 181\r\n\r\n{"id":2,"jsonrpc":"2.0","method":"textDocument/signatureHelp","params":{"position":{"character":9,"line":2},"textDocument":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs"}}}'
2021-04-14 23:35:12,489 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","id":2,"result":{"signatures":[{"label":"fn test(_a: i8, _b: i8)","parameters":[{"label":[8,14]},{"label":[16,22]}],"active_parameter":0}],"activeParameter":0}}'
2021-04-14 23:35:13,625 - DEBUG - TX: Sending notification: b'Content-Length: 230\r\n\r\n{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"text":"fn test(_a:i8, _b:i8){}\\nfn main() {\\n    test( \\n}\\n"}],"textDocument":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs","version":2}}}'
2021-04-14 23:35:13,625 - DEBUG - TX: Sending message: b'Content-Length: 182\r\n\r\n{"id":3,"jsonrpc":"2.0","method":"textDocument/signatureHelp","params":{"position":{"character":10,"line":2},"textDocument":{"uri":"file:///home/bstaletic/work/test/r/src/main.rs"}}}'
2021-04-14 23:35:13,724 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","id":3,"result":null}'
```

The last 5 messages should explain the issue. This is a problem, because ycmd treats null results as "close the signature help popup".


Currently using this rust-analyzer (latest from rustup):
```
rust-analyzer --version
rust-analyzer 2021-04-05
```

but I was also able to repro with https://github.com/rust-analyzer/rust-analyzer/commit/10a243ea55565a0dd1de52f8f802c3e3a7bfef54

Pull request:
Return CallInfo for unclosed call expressions
Closes #8522
bors r+

Patch:
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 0acfa582a0..eba46a0569 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -2066,18 +2066,6 @@ impl Type {
         self.ty.dyn_trait().map(Into::into)
     }
 
-    /// If a type can be represented as `dyn Trait`, returns all traits accessible via this type,
-    /// or an empty iterator otherwise.
-    pub fn applicable_inherent_traits<'a>(
-        &'a self,
-        db: &'a dyn HirDatabase,
-    ) -> impl Iterator<Item = Trait> + 'a {
-        self.autoderef(db)
-            .filter_map(|derefed_type| derefed_type.ty.dyn_trait())
-            .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id))
-            .map(Trait::from)
-    }
-
     pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> {
         self.ty.impl_trait_bounds(db).map(|it| {
             it.into_iter()
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index c984148c3a..ccc9f22eb5 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -387,13 +387,7 @@ impl DefMap {
             .get_legacy_macro(name)
             .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public));
         let from_scope = self[module].scope.get(name);
-        let from_builtin = match self.block {
-            Some(_) => {
-                // Only resolve to builtins in the root `DefMap`.
-                PerNs::none()
-            }
-            None => BUILTIN_SCOPE.get(name).copied().unwrap_or_else(PerNs::none),
-        };
+        let from_builtin = BUILTIN_SCOPE.get(name).copied().unwrap_or_else(PerNs::none);
         let from_scope_or_builtin = match shadow {
             BuiltinShadowMode::Module => from_scope.or(from_builtin),
             BuiltinShadowMode::Other => {
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 0505fa4aea..113234fa48 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -56,7 +56,6 @@ pub use mapping::{
     to_foreign_def_id, to_placeholder_idx,
 };
 pub use traits::TraitEnvironment;
-pub use utils::all_super_traits;
 pub use walk::TypeWalk;
 
 pub use chalk_ir::{
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index 2f04ee57ae..5f6cb052af 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -78,7 +78,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
 
 /// Returns an iterator over the whole super trait hierarchy (including the
 /// trait itself).
-pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
+pub(super) fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
     // we need to take care a bit here to avoid infinite loops in case of cycles
     // (i.e. if we have `trait A: B; trait B: A;`)
     let mut result = vec![trait_];
diff --git a/crates/ide_assists/src/handlers/fill_match_arms.rs b/crates/ide_assists/src/handlers/fill_match_arms.rs
index 80bd1b7e8a..878b3a3fac 100644
--- a/crates/ide_assists/src/handlers/fill_match_arms.rs
+++ b/crates/ide_assists/src/handlers/fill_match_arms.rs
@@ -71,6 +71,12 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<
             return None;
         }
 
+        // We do not currently support filling match arms for a tuple
+        // containing a single enum.
+        if enum_defs.len() < 2 {
+            return None;
+        }
+
         // When calculating the match arms for a tuple of enums, we want
         // to create a match arm for each possible combination of enum
         // values. The `multi_cartesian_product` method transforms
@@ -508,7 +514,10 @@ fn main() {
 
     #[test]
     fn fill_match_arms_single_element_tuple_of_enum() {
-        check_assist(
+        // For now we don't hande the case of a single element tuple, but
+        // we could handle this in the future if `make::tuple_pat` allowed
+        // creating a tuple with a single pattern.
+        check_assist_not_applicable(
             fill_match_arms,
             r#"
             enum A { One, Two }
@@ -519,17 +528,6 @@ fn main() {
                 }
             }
             "#,
-            r#"
-            enum A { One, Two }
-
-            fn main() {
-                let a = A::One;
-                match (a, ) {
-                    $0(A::One,) => {}
-                    (A::Two,) => {}
-                }
-            }
-            "#,
         );
     }
 
diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs
index 8e211ae1ed..5e61ecb4db 100644
--- a/crates/ide_completion/src/completions/flyimport.rs
+++ b/crates/ide_completion/src/completions/flyimport.rs
@@ -1127,27 +1127,4 @@ impl Bar for Foo {
             expect![[r#""#]],
         );
     }
-
-    #[test]
-    fn no_inherent_candidates_proposed() {
-        check(
-            r#"
-mod baz {
-    pub trait DefDatabase {
-        fn method1(&self);
-    }
-    pub trait HirDatabase: DefDatabase {
-        fn method2(&self);
-    }
-}
-
-mod bar {
-    fn test(db: &dyn crate::baz::HirDatabase) {
-        db.metho$0
-    }
-}
-            "#,
-            expect![[r#""#]],
-        );
-    }
 }
diff --git a/crates/ide_db/src/call_info.rs b/crates/ide_db/src/call_info.rs
index e583a52f46..bad277a953 100644
--- a/crates/ide_db/src/call_info.rs
+++ b/crates/ide_db/src/call_info.rs
@@ -4,8 +4,9 @@ use either::Either;
 use hir::{HasAttrs, HirDisplay, Semantics, Type};
 use stdx::format_to;
 use syntax::{
+    algo,
     ast::{self, ArgListOwner, NameOwner},
-    match_ast, AstNode, SyntaxNode, SyntaxToken, TextRange, TextSize,
+    match_ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextSize,
 };
 
 use crate::RootDatabase;
@@ -43,7 +44,12 @@ pub fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo>
     let sema = Semantics::new(db);
     let file = sema.parse(position.file_id);
     let file = file.syntax();
-    let token = file.token_at_offset(position.offset).next()?;
+    let token = file
+        .token_at_offset(position.offset)
+        .left_biased()
+        // if the cursor is sandwiched between two space tokens and the call is unclosed
+        // this prevents us from leaving the CallExpression
+        .and_then(|tok| algo::skip_trivia_token(tok, Direction::Prev))?;
     let token = sema.descend_into_macros(token);
 
     let (callable, active_parameter) = call_info_impl(&sema, token)?;
diff --git a/crates/ide_db/src/helpers/import_assets.rs b/crates/ide_db/src/helpers/import_assets.rs
index 91d6a46651..8ce6483671 100644
--- a/crates/ide_db/src/helpers/import_assets.rs
+++ b/crates/ide_db/src/helpers/import_assets.rs
@@ -436,8 +436,6 @@ fn trait_applicable_items(
     })
     .collect();
 
-    let related_dyn_traits =
-        trait_candidate.receiver_ty.applicable_inherent_traits(db).collect::<FxHashSet<_>>();
     let mut located_imports = FxHashSet::default();
 
     if trait_assoc_item {
@@ -453,16 +451,12 @@ fn trait_applicable_items(
                             return None;
                         }
                     }
-                    let located_trait = assoc.containing_trait(db)?;
-                    if related_dyn_traits.contains(&located_trait) {
-                        return None;
-                    }
 
-                    let trait_item = ItemInNs::from(ModuleDef::from(located_trait));
+                    let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?));
                     let original_item = assoc_to_item(assoc);
                     located_imports.insert(LocatedImport::new(
-                        mod_path(trait_item)?,
-                        trait_item,
+                        mod_path(item)?,
+                        item,
                         original_item,
                         mod_path(original_item),
                     ));
@@ -479,15 +473,11 @@ fn trait_applicable_items(
             |_, function| {
                 let assoc = function.as_assoc_item(db)?;
                 if required_assoc_items.contains(&assoc) {
-                    let located_trait = assoc.containing_trait(db)?;
-                    if related_dyn_traits.contains(&located_trait) {
-                        return None;
-                    }
-                    let trait_item = ItemInNs::from(ModuleDef::from(located_trait));
+                    let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?));
                     let original_item = assoc_to_item(assoc);
                     located_imports.insert(LocatedImport::new(
-                        mod_path(trait_item)?,
-                        trait_item,
+                        mod_path(item)?,
+                        item,
                         original_item,
                         mod_path(original_item),
                     ));
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index 94d4f2cf0b..c6a7b99b7c 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -29,13 +29,9 @@ pub fn ty(text: &str) -> ast::Type {
 pub fn ty_unit() -> ast::Type {
     ty("()")
 }
+// FIXME: handle types of length == 1
 pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type {
-    let mut count: usize = 0;
-    let mut contents = types.into_iter().inspect(|_| count += 1).join(", ");
-    if count == 1 {
-        contents.push(',');
-    }
-
+    let contents = types.into_iter().join(", ");
     ty(&format!("({})", contents))
 }
 // FIXME: handle path to type
@@ -296,13 +292,11 @@ pub fn wildcard_pat() -> ast::WildcardPat {
 
 /// Creates a tuple of patterns from an iterator of patterns.
 ///
-/// Invariant: `pats` must be length > 0
+/// Invariant: `pats` must be length > 1
+///
+/// FIXME handle `pats` length == 1
 pub fn tuple_pat(pats: impl IntoIterator<Item = ast::Pat>) -> ast::TuplePat {
-    let mut count: usize = 0;
-    let mut pats_str = pats.into_iter().inspect(|_| count += 1).join(", ");
-    if count == 1 {
-        pats_str.push(',');
-    }
+    let pats_str = pats.into_iter().map(|p| p.to_string()).join(", ");
     return from_text(&format!("({})", pats_str));
 
     fn from_text(text: &str) -> ast::TuplePat {


Test patch:
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index 5948d0bc22..84c5c05fd3 100644
--- a/crates/hir_ty/src/tests/simple.rs
+++ b/crates/hir_ty/src/tests/simple.rs
@@ -1764,24 +1764,6 @@ fn main() {
     );
 }
 
-#[test]
-fn shadowing_primitive_with_inner_items() {
-    check_types(
-        r#"
-struct i32;
-struct Foo;
-
-impl i32 { fn foo(&self) -> Foo { Foo } }
-
-fn main() {
-    fn inner() {}
-    let x: i32 = i32;
-    x.foo();
-        //^ Foo
-}"#,
-    );
-}
-
 #[test]
 fn not_shadowing_primitive_by_module() {
     check_types(
diff --git a/crates/ide_db/src/call_info/tests.rs b/crates/ide_db/src/call_info/tests.rs
index 281a081a38..be1cc12de1 100644
--- a/crates/ide_db/src/call_info/tests.rs
+++ b/crates/ide_db/src/call_info/tests.rs
@@ -522,3 +522,30 @@ fn main(f: fn(i32, f64) -> char) {
             "#]],
     )
 }
+
+#[test]
+fn call_info_for_unclosed_call() {
+    check(
+        r#"
+fn foo(foo: u32, bar: u32) {}
+fn main() {
+    foo($0
+}"#,
+        expect![[r#"
+            fn foo(foo: u32, bar: u32)
+            (<foo: u32>, bar: u32)
+        "#]],
+    );
+    // check with surrounding space
+    check(
+        r#"
+fn foo(foo: u32, bar: u32) {}
+fn main() {
+    foo( $0
+}"#,
+        expect![[r#"
+            fn foo(foo: u32, bar: u32)
+            (<foo: u32>, bar: u32)
+        "#]],
+    )
+}