]> git.lizzy.rs Git - rust.git/blob - crates/ide-completion/src/context.rs
Auto merge of #12120 - iDawer:ide.sig_help, r=Veykril
[rust.git] / crates / ide-completion / src / context.rs
1 //! See `CompletionContext` structure.
2
3 use std::iter;
4
5 use base_db::SourceDatabaseExt;
6 use hir::{
7     HasAttrs, Local, Name, PathResolution, ScopeDef, Semantics, SemanticsScope, Type, TypeInfo,
8 };
9 use ide_db::{
10     active_parameter::ActiveParameter,
11     base_db::{FilePosition, SourceDatabase},
12     famous_defs::FamousDefs,
13     FxHashMap, FxHashSet, RootDatabase,
14 };
15 use syntax::{
16     algo::{find_node_at_offset, non_trivia_sibling},
17     ast::{self, AttrKind, HasName, NameOrNameRef},
18     match_ast, AstNode, NodeOrToken,
19     SyntaxKind::{self, *},
20     SyntaxNode, SyntaxToken, TextRange, TextSize, T,
21 };
22 use text_edit::Indel;
23
24 use crate::{
25     patterns::{
26         determine_location, determine_prev_sibling, is_in_loop_body, is_in_token_of_for_loop,
27         previous_token, ImmediateLocation, ImmediatePrevSibling,
28     },
29     CompletionConfig,
30 };
31
32 const COMPLETION_MARKER: &str = "intellijRulezz";
33
34 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
35 pub(crate) enum PatternRefutability {
36     Refutable,
37     Irrefutable,
38 }
39
40 pub(crate) enum Visible {
41     Yes,
42     Editable,
43     No,
44 }
45
46 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
47 pub(super) enum PathKind {
48     Expr,
49     Type,
50     Attr { kind: AttrKind, annotated_item_kind: Option<SyntaxKind> },
51     Derive,
52     // This should be removed in favor of `has_macro_bang` in PathCompletionContext
53     Mac,
54     Pat,
55     Vis { has_in_token: bool },
56     Use,
57 }
58
59 #[derive(Debug)]
60 pub(crate) struct PathCompletionCtx {
61     /// If this is a call with () already there (or {} in case of record patterns)
62     pub(super) has_call_parens: bool,
63     /// Whether this path stars with a `::`.
64     pub(super) is_absolute_path: bool,
65     /// The qualifier of the current path if it exists.
66     pub(super) qualifier: Option<PathQualifierCtx>,
67     pub(super) kind: Option<PathKind>,
68     /// Whether the path segment has type args or not.
69     pub(super) has_type_args: bool,
70     /// `true` if we are a statement or a last expr in the block.
71     pub(super) can_be_stmt: bool,
72     pub(super) in_loop_body: bool,
73 }
74
75 #[derive(Debug)]
76 pub(crate) struct PathQualifierCtx {
77     pub(crate) path: ast::Path,
78     pub(crate) resolution: Option<PathResolution>,
79     /// Whether this path consists solely of `super` segments
80     pub(crate) is_super_chain: bool,
81     /// Whether the qualifier comes from a use tree parent or not
82     pub(crate) use_tree_parent: bool,
83 }
84
85 #[derive(Debug)]
86 pub(super) struct PatternContext {
87     pub(super) refutability: PatternRefutability,
88     pub(super) param_ctx: Option<(ast::ParamList, ast::Param, ParamKind)>,
89     pub(super) has_type_ascription: bool,
90     pub(super) parent_pat: Option<ast::Pat>,
91     pub(super) ref_token: Option<SyntaxToken>,
92     pub(super) mut_token: Option<SyntaxToken>,
93 }
94
95 #[derive(Debug)]
96 pub(super) enum LifetimeContext {
97     LifetimeParam { is_decl: bool, param: ast::LifetimeParam },
98     Lifetime,
99     LabelRef,
100     LabelDef,
101 }
102
103 #[derive(Debug)]
104 #[allow(dead_code)]
105 pub(super) enum NameContext {
106     Const,
107     ConstParam,
108     Enum,
109     Function,
110     IdentPat,
111     MacroDef,
112     MacroRules,
113     /// Fake node
114     Module(ast::Module),
115     RecordField,
116     Rename,
117     SelfParam,
118     Static,
119     Struct,
120     Trait,
121     TypeAlias,
122     TypeParam,
123     Union,
124     Variant,
125 }
126
127 #[derive(Clone, Debug, PartialEq, Eq)]
128 pub(crate) enum ParamKind {
129     Function(ast::Fn),
130     Closure(ast::ClosureExpr),
131 }
132
133 /// `CompletionContext` is created early during completion to figure out, where
134 /// exactly is the cursor, syntax-wise.
135 #[derive(Debug)]
136 pub(crate) struct CompletionContext<'a> {
137     pub(super) sema: Semantics<'a, RootDatabase>,
138     pub(super) scope: SemanticsScope<'a>,
139     pub(super) db: &'a RootDatabase,
140     pub(super) config: &'a CompletionConfig,
141     pub(super) position: FilePosition,
142
143     /// The token before the cursor, in the original file.
144     pub(super) original_token: SyntaxToken,
145     /// The token before the cursor, in the macro-expanded file.
146     pub(super) token: SyntaxToken,
147     /// The crate of the current file.
148     pub(super) krate: hir::Crate,
149     /// The module of the `scope`.
150     pub(super) module: hir::Module,
151
152     /// The expected name of what we are completing.
153     /// This is usually the parameter name of the function argument we are completing.
154     pub(super) expected_name: Option<NameOrNameRef>,
155     /// The expected type of what we are completing.
156     pub(super) expected_type: Option<Type>,
157
158     /// The parent function of the cursor position if it exists.
159     pub(super) function_def: Option<ast::Fn>,
160     /// The parent impl of the cursor position if it exists.
161     pub(super) impl_def: Option<ast::Impl>,
162     /// The NameLike under the cursor in the original file if it exists.
163     pub(super) name_syntax: Option<ast::NameLike>,
164     /// Are we completing inside a let statement with a missing semicolon?
165     pub(super) incomplete_let: bool,
166
167     pub(super) completion_location: Option<ImmediateLocation>,
168     pub(super) prev_sibling: Option<ImmediatePrevSibling>,
169     pub(super) fake_attribute_under_caret: Option<ast::Attr>,
170     pub(super) previous_token: Option<SyntaxToken>,
171
172     pub(super) name_ctx: Option<NameContext>,
173     pub(super) lifetime_ctx: Option<LifetimeContext>,
174     pub(super) pattern_ctx: Option<PatternContext>,
175     pub(super) path_context: Option<PathCompletionCtx>,
176
177     pub(super) existing_derives: FxHashSet<hir::Macro>,
178
179     pub(super) locals: FxHashMap<Name, Local>,
180 }
181
182 impl<'a> CompletionContext<'a> {
183     /// The range of the identifier that is being completed.
184     pub(crate) fn source_range(&self) -> TextRange {
185         // check kind of macro-expanded token, but use range of original token
186         let kind = self.token.kind();
187         match kind {
188             CHAR => {
189                 // assume we are completing a lifetime but the user has only typed the '
190                 cov_mark::hit!(completes_if_lifetime_without_idents);
191                 TextRange::at(self.original_token.text_range().start(), TextSize::from(1))
192             }
193             IDENT | LIFETIME_IDENT | UNDERSCORE => self.original_token.text_range(),
194             _ if kind.is_keyword() => self.original_token.text_range(),
195             _ => TextRange::empty(self.position.offset),
196         }
197     }
198
199     pub(crate) fn name_ref(&self) -> Option<&ast::NameRef> {
200         self.name_syntax.as_ref().and_then(ast::NameLike::as_name_ref)
201     }
202
203     pub(crate) fn lifetime(&self) -> Option<&ast::Lifetime> {
204         self.name_syntax.as_ref().and_then(ast::NameLike::as_lifetime)
205     }
206
207     pub(crate) fn previous_token_is(&self, kind: SyntaxKind) -> bool {
208         self.previous_token.as_ref().map_or(false, |tok| tok.kind() == kind)
209     }
210
211     pub(crate) fn famous_defs(&self) -> FamousDefs {
212         FamousDefs(&self.sema, self.krate)
213     }
214
215     pub(crate) fn dot_receiver(&self) -> Option<&ast::Expr> {
216         match &self.completion_location {
217             Some(
218                 ImmediateLocation::MethodCall { receiver, .. }
219                 | ImmediateLocation::FieldAccess { receiver, .. },
220             ) => receiver.as_ref(),
221             _ => None,
222         }
223     }
224
225     pub(crate) fn has_dot_receiver(&self) -> bool {
226         matches!(
227             &self.completion_location,
228             Some(ImmediateLocation::FieldAccess { receiver, .. } | ImmediateLocation::MethodCall { receiver,.. })
229                 if receiver.is_some()
230         )
231     }
232
233     pub(crate) fn expects_assoc_item(&self) -> bool {
234         matches!(self.completion_location, Some(ImmediateLocation::Trait | ImmediateLocation::Impl))
235     }
236
237     pub(crate) fn expects_variant(&self) -> bool {
238         matches!(self.name_ctx, Some(NameContext::Variant))
239     }
240
241     pub(crate) fn expects_non_trait_assoc_item(&self) -> bool {
242         matches!(self.completion_location, Some(ImmediateLocation::Impl))
243     }
244
245     pub(crate) fn expects_item(&self) -> bool {
246         matches!(self.completion_location, Some(ImmediateLocation::ItemList))
247     }
248
249     pub(crate) fn expects_generic_arg(&self) -> bool {
250         matches!(self.completion_location, Some(ImmediateLocation::GenericArgList(_)))
251     }
252
253     pub(crate) fn has_block_expr_parent(&self) -> bool {
254         matches!(self.completion_location, Some(ImmediateLocation::StmtList))
255     }
256
257     pub(crate) fn expects_ident_ref_expr(&self) -> bool {
258         matches!(self.completion_location, Some(ImmediateLocation::RefExpr))
259     }
260
261     pub(crate) fn expect_field(&self) -> bool {
262         matches!(self.completion_location, Some(ImmediateLocation::TupleField))
263             || matches!(self.name_ctx, Some(NameContext::RecordField))
264     }
265
266     pub(crate) fn has_impl_or_trait_prev_sibling(&self) -> bool {
267         matches!(
268             self.prev_sibling,
269             Some(ImmediatePrevSibling::ImplDefType | ImmediatePrevSibling::TraitDefName)
270         )
271     }
272
273     pub(crate) fn has_impl_prev_sibling(&self) -> bool {
274         matches!(self.prev_sibling, Some(ImmediatePrevSibling::ImplDefType))
275     }
276
277     pub(crate) fn has_visibility_prev_sibling(&self) -> bool {
278         matches!(self.prev_sibling, Some(ImmediatePrevSibling::Visibility))
279     }
280
281     pub(crate) fn after_if(&self) -> bool {
282         matches!(self.prev_sibling, Some(ImmediatePrevSibling::IfExpr))
283     }
284
285     pub(crate) fn is_path_disallowed(&self) -> bool {
286         self.previous_token_is(T![unsafe])
287             || matches!(
288                 self.prev_sibling,
289                 Some(ImmediatePrevSibling::Attribute | ImmediatePrevSibling::Visibility)
290             )
291             || matches!(
292                 self.completion_location,
293                 Some(ImmediateLocation::RecordPat(_) | ImmediateLocation::RecordExpr(_))
294             )
295             || matches!(self.name_ctx, Some(NameContext::Module(_) | NameContext::Rename))
296     }
297
298     pub(crate) fn expects_expression(&self) -> bool {
299         matches!(self.path_context, Some(PathCompletionCtx { kind: Some(PathKind::Expr), .. }))
300     }
301
302     pub(crate) fn expects_type(&self) -> bool {
303         matches!(self.path_context, Some(PathCompletionCtx { kind: Some(PathKind::Type), .. }))
304     }
305
306     pub(crate) fn path_is_call(&self) -> bool {
307         self.path_context.as_ref().map_or(false, |it| it.has_call_parens)
308     }
309
310     pub(crate) fn is_non_trivial_path(&self) -> bool {
311         matches!(
312             self.path_context,
313             Some(
314                 PathCompletionCtx { is_absolute_path: true, .. }
315                     | PathCompletionCtx { qualifier: Some(_), .. }
316             )
317         )
318     }
319
320     pub(crate) fn path_qual(&self) -> Option<&ast::Path> {
321         self.path_context.as_ref().and_then(|it| it.qualifier.as_ref().map(|it| &it.path))
322     }
323
324     pub(crate) fn path_kind(&self) -> Option<PathKind> {
325         self.path_context.as_ref().and_then(|it| it.kind)
326     }
327
328     pub(crate) fn is_immediately_after_macro_bang(&self) -> bool {
329         self.token.kind() == BANG && self.token.parent().map_or(false, |it| it.kind() == MACRO_CALL)
330     }
331
332     /// Checks if an item is visible and not `doc(hidden)` at the completion site.
333     pub(crate) fn is_visible<I>(&self, item: &I) -> Visible
334     where
335         I: hir::HasVisibility + hir::HasAttrs + hir::HasCrate + Copy,
336     {
337         self.is_visible_impl(&item.visibility(self.db), &item.attrs(self.db), item.krate(self.db))
338     }
339
340     pub(crate) fn is_scope_def_hidden(&self, scope_def: ScopeDef) -> bool {
341         if let (Some(attrs), Some(krate)) = (scope_def.attrs(self.db), scope_def.krate(self.db)) {
342             return self.is_doc_hidden(&attrs, krate);
343         }
344
345         false
346     }
347
348     /// Check if an item is `#[doc(hidden)]`.
349     pub(crate) fn is_item_hidden(&self, item: &hir::ItemInNs) -> bool {
350         let attrs = item.attrs(self.db);
351         let krate = item.krate(self.db);
352         match (attrs, krate) {
353             (Some(attrs), Some(krate)) => self.is_doc_hidden(&attrs, krate),
354             _ => false,
355         }
356     }
357     /// Whether the given trait is an operator trait or not.
358     pub(crate) fn is_ops_trait(&self, trait_: hir::Trait) -> bool {
359         match trait_.attrs(self.db).lang() {
360             Some(lang) => OP_TRAIT_LANG_NAMES.contains(&lang.as_str()),
361             None => false,
362         }
363     }
364
365     /// A version of [`SemanticsScope::process_all_names`] that filters out `#[doc(hidden)]` items.
366     pub(crate) fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
367         let _p = profile::span("CompletionContext::process_all_names");
368         self.scope.process_all_names(&mut |name, def| {
369             if self.is_scope_def_hidden(def) {
370                 return;
371             }
372
373             f(name, def);
374         });
375     }
376
377     pub(crate) fn process_all_names_raw(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
378         let _p = profile::span("CompletionContext::process_all_names_raw");
379         self.scope.process_all_names(&mut |name, def| f(name, def));
380     }
381
382     fn is_visible_impl(
383         &self,
384         vis: &hir::Visibility,
385         attrs: &hir::Attrs,
386         defining_crate: hir::Crate,
387     ) -> Visible {
388         if !vis.is_visible_from(self.db, self.module.into()) {
389             if !self.config.enable_private_editable {
390                 return Visible::No;
391             }
392             // If the definition location is editable, also show private items
393             let root_file = defining_crate.root_file(self.db);
394             let source_root_id = self.db.file_source_root(root_file);
395             let is_editable = !self.db.source_root(source_root_id).is_library;
396             return if is_editable { Visible::Editable } else { Visible::No };
397         }
398
399         if self.is_doc_hidden(attrs, defining_crate) {
400             Visible::No
401         } else {
402             Visible::Yes
403         }
404     }
405
406     fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool {
407         // `doc(hidden)` items are only completed within the defining crate.
408         self.krate != defining_crate && attrs.has_doc_hidden()
409     }
410 }
411
412 // CompletionContext construction
413 impl<'a> CompletionContext<'a> {
414     pub(super) fn new(
415         db: &'a RootDatabase,
416         position @ FilePosition { file_id, offset }: FilePosition,
417         config: &'a CompletionConfig,
418     ) -> Option<CompletionContext<'a>> {
419         let _p = profile::span("CompletionContext::new");
420         let sema = Semantics::new(db);
421
422         let original_file = sema.parse(file_id);
423
424         // Insert a fake ident to get a valid parse tree. We will use this file
425         // to determine context, though the original_file will be used for
426         // actual completion.
427         let file_with_fake_ident = {
428             let parse = db.parse(file_id);
429             let edit = Indel::insert(offset, COMPLETION_MARKER.to_string());
430             parse.reparse(&edit).tree()
431         };
432         let fake_ident_token =
433             file_with_fake_ident.syntax().token_at_offset(offset).right_biased()?;
434
435         let original_token = original_file.syntax().token_at_offset(offset).left_biased()?;
436         let token = sema.descend_into_macros_single(original_token.clone());
437         let scope = sema.scope_at_offset(&token.parent()?, offset)?;
438         let krate = scope.krate();
439         let module = scope.module();
440
441         let mut locals = FxHashMap::default();
442         scope.process_all_names(&mut |name, scope| {
443             if let ScopeDef::Local(local) = scope {
444                 locals.insert(name, local);
445             }
446         });
447
448         let mut ctx = CompletionContext {
449             sema,
450             scope,
451             db,
452             config,
453             position,
454             original_token,
455             token,
456             krate,
457             module,
458             expected_name: None,
459             expected_type: None,
460             function_def: None,
461             impl_def: None,
462             name_syntax: None,
463             lifetime_ctx: None,
464             pattern_ctx: None,
465             name_ctx: None,
466             completion_location: None,
467             prev_sibling: None,
468             fake_attribute_under_caret: None,
469             previous_token: None,
470             path_context: None,
471             locals,
472             incomplete_let: false,
473             existing_derives: Default::default(),
474         };
475         ctx.expand_and_fill(
476             original_file.syntax().clone(),
477             file_with_fake_ident.syntax().clone(),
478             offset,
479             fake_ident_token,
480         );
481         Some(ctx)
482     }
483
484     /// Expand attributes and macro calls at the current cursor position for both the original file
485     /// and fake file repeatedly. As soon as one of the two expansions fail we stop so the original
486     /// and speculative states stay in sync.
487     fn expand_and_fill(
488         &mut self,
489         mut original_file: SyntaxNode,
490         mut speculative_file: SyntaxNode,
491         mut offset: TextSize,
492         mut fake_ident_token: SyntaxToken,
493     ) {
494         let _p = profile::span("CompletionContext::expand_and_fill");
495         let mut derive_ctx = None;
496
497         'expansion: loop {
498             let parent_item =
499                 |item: &ast::Item| item.syntax().ancestors().skip(1).find_map(ast::Item::cast);
500             let ancestor_items = iter::successors(
501                 Option::zip(
502                     find_node_at_offset::<ast::Item>(&original_file, offset),
503                     find_node_at_offset::<ast::Item>(&speculative_file, offset),
504                 ),
505                 |(a, b)| parent_item(a).zip(parent_item(b)),
506             );
507
508             // first try to expand attributes as these are always the outermost macro calls
509             'ancestors: for (actual_item, item_with_fake_ident) in ancestor_items {
510                 match (
511                     self.sema.expand_attr_macro(&actual_item),
512                     self.sema.speculative_expand_attr_macro(
513                         &actual_item,
514                         &item_with_fake_ident,
515                         fake_ident_token.clone(),
516                     ),
517                 ) {
518                     // maybe parent items have attributes, so continue walking the ancestors
519                     (None, None) => continue 'ancestors,
520                     // successful expansions
521                     (Some(actual_expansion), Some((fake_expansion, fake_mapped_token))) => {
522                         let new_offset = fake_mapped_token.text_range().start();
523                         if new_offset > actual_expansion.text_range().end() {
524                             // offset outside of bounds from the original expansion,
525                             // stop here to prevent problems from happening
526                             break 'expansion;
527                         }
528                         original_file = actual_expansion;
529                         speculative_file = fake_expansion;
530                         fake_ident_token = fake_mapped_token;
531                         offset = new_offset;
532                         continue 'expansion;
533                     }
534                     // exactly one expansion failed, inconsistent state so stop expanding completely
535                     _ => break 'expansion,
536                 }
537             }
538
539             // No attributes have been expanded, so look for macro_call! token trees or derive token trees
540             let orig_tt = match find_node_at_offset::<ast::TokenTree>(&original_file, offset) {
541                 Some(it) => it,
542                 None => break 'expansion,
543             };
544             let spec_tt = match find_node_at_offset::<ast::TokenTree>(&speculative_file, offset) {
545                 Some(it) => it,
546                 None => break 'expansion,
547             };
548
549             // Expand pseudo-derive expansion
550             if let (Some(orig_attr), Some(spec_attr)) = (
551                 orig_tt.syntax().parent().and_then(ast::Meta::cast).and_then(|it| it.parent_attr()),
552                 spec_tt.syntax().parent().and_then(ast::Meta::cast).and_then(|it| it.parent_attr()),
553             ) {
554                 if let (Some(actual_expansion), Some((fake_expansion, fake_mapped_token))) = (
555                     self.sema.expand_derive_as_pseudo_attr_macro(&orig_attr),
556                     self.sema.speculative_expand_derive_as_pseudo_attr_macro(
557                         &orig_attr,
558                         &spec_attr,
559                         fake_ident_token.clone(),
560                     ),
561                 ) {
562                     derive_ctx = Some((
563                         actual_expansion,
564                         fake_expansion,
565                         fake_mapped_token.text_range().start(),
566                         orig_attr,
567                     ));
568                 }
569                 // at this point we won't have any more successful expansions, so stop
570                 break 'expansion;
571             }
572
573             // Expand fn-like macro calls
574             if let (Some(actual_macro_call), Some(macro_call_with_fake_ident)) = (
575                 orig_tt.syntax().ancestors().find_map(ast::MacroCall::cast),
576                 spec_tt.syntax().ancestors().find_map(ast::MacroCall::cast),
577             ) {
578                 let mac_call_path0 = actual_macro_call.path().as_ref().map(|s| s.syntax().text());
579                 let mac_call_path1 =
580                     macro_call_with_fake_ident.path().as_ref().map(|s| s.syntax().text());
581
582                 // inconsistent state, stop expanding
583                 if mac_call_path0 != mac_call_path1 {
584                     break 'expansion;
585                 }
586                 let speculative_args = match macro_call_with_fake_ident.token_tree() {
587                     Some(tt) => tt,
588                     None => break 'expansion,
589                 };
590
591                 match (
592                     self.sema.expand(&actual_macro_call),
593                     self.sema.speculative_expand(
594                         &actual_macro_call,
595                         &speculative_args,
596                         fake_ident_token.clone(),
597                     ),
598                 ) {
599                     // successful expansions
600                     (Some(actual_expansion), Some((fake_expansion, fake_mapped_token))) => {
601                         let new_offset = fake_mapped_token.text_range().start();
602                         if new_offset > actual_expansion.text_range().end() {
603                             // offset outside of bounds from the original expansion,
604                             // stop here to prevent problems from happening
605                             break 'expansion;
606                         }
607                         original_file = actual_expansion;
608                         speculative_file = fake_expansion;
609                         fake_ident_token = fake_mapped_token;
610                         offset = new_offset;
611                         continue 'expansion;
612                     }
613                     // at least on expansion failed, we won't have anything to expand from this point
614                     // onwards so break out
615                     _ => break 'expansion,
616                 }
617             }
618
619             // none of our states have changed so stop the loop
620             break 'expansion;
621         }
622
623         self.fill(&original_file, speculative_file, offset, derive_ctx);
624     }
625
626     /// Calculate the expected type and name of the cursor position.
627     fn expected_type_and_name(&self) -> (Option<Type>, Option<NameOrNameRef>) {
628         let mut node = match self.token.parent() {
629             Some(it) => it,
630             None => return (None, None),
631         };
632         loop {
633             break match_ast! {
634                 match node {
635                     ast::LetStmt(it) => {
636                         cov_mark::hit!(expected_type_let_with_leading_char);
637                         cov_mark::hit!(expected_type_let_without_leading_char);
638                         let ty = it.pat()
639                             .and_then(|pat| self.sema.type_of_pat(&pat))
640                             .or_else(|| it.initializer().and_then(|it| self.sema.type_of_expr(&it)))
641                             .map(TypeInfo::original);
642                         let name = match it.pat() {
643                             Some(ast::Pat::IdentPat(ident)) => ident.name().map(NameOrNameRef::Name),
644                             Some(_) | None => None,
645                         };
646
647                         (ty, name)
648                     },
649                     ast::LetExpr(it) => {
650                         cov_mark::hit!(expected_type_if_let_without_leading_char);
651                         let ty = it.pat()
652                             .and_then(|pat| self.sema.type_of_pat(&pat))
653                             .or_else(|| it.expr().and_then(|it| self.sema.type_of_expr(&it)))
654                             .map(TypeInfo::original);
655                         (ty, None)
656                     },
657                     ast::ArgList(_) => {
658                         cov_mark::hit!(expected_type_fn_param);
659                         ActiveParameter::at_token(
660                             &self.sema,
661                             self.token.clone(),
662                         ).map(|ap| {
663                             let name = ap.ident().map(NameOrNameRef::Name);
664                             let ty = if has_ref(&self.token) {
665                                 cov_mark::hit!(expected_type_fn_param_ref);
666                                 ap.ty.remove_ref()
667                             } else {
668                                 Some(ap.ty)
669                             };
670                             (ty, name)
671                         })
672                         .unwrap_or((None, None))
673                     },
674                     ast::RecordExprFieldList(it) => {
675                         // wouldn't try {} be nice...
676                         (|| {
677                             if self.token.kind() == T![..]
678                                 || self.token.prev_token().map(|t| t.kind()) == Some(T![..])
679                             {
680                                 cov_mark::hit!(expected_type_struct_func_update);
681                                 let record_expr = it.syntax().parent().and_then(ast::RecordExpr::cast)?;
682                                 let ty = self.sema.type_of_expr(&record_expr.into())?;
683                                 Some((
684                                     Some(ty.original),
685                                     None
686                                 ))
687                             } else {
688                                 cov_mark::hit!(expected_type_struct_field_without_leading_char);
689                                 let expr_field = self.token.prev_sibling_or_token()?
690                                     .into_node()
691                                     .and_then(ast::RecordExprField::cast)?;
692                                 let (_, _, ty) = self.sema.resolve_record_field(&expr_field)?;
693                                 Some((
694                                     Some(ty),
695                                     expr_field.field_name().map(NameOrNameRef::NameRef),
696                                 ))
697                             }
698                         })().unwrap_or((None, None))
699                     },
700                     ast::RecordExprField(it) => {
701                         if let Some(expr) = it.expr() {
702                             cov_mark::hit!(expected_type_struct_field_with_leading_char);
703                             (
704                                 self.sema.type_of_expr(&expr).map(TypeInfo::original),
705                                 it.field_name().map(NameOrNameRef::NameRef),
706                             )
707                         } else {
708                             cov_mark::hit!(expected_type_struct_field_followed_by_comma);
709                             let ty = self.sema.resolve_record_field(&it)
710                                 .map(|(_, _, ty)| ty);
711                             (
712                                 ty,
713                                 it.field_name().map(NameOrNameRef::NameRef),
714                             )
715                         }
716                     },
717                     ast::MatchExpr(it) => {
718                         cov_mark::hit!(expected_type_match_arm_without_leading_char);
719                         let ty = it.expr().and_then(|e| self.sema.type_of_expr(&e)).map(TypeInfo::original);
720                         (ty, None)
721                     },
722                     ast::IfExpr(it) => {
723                         let ty = it.condition()
724                             .and_then(|e| self.sema.type_of_expr(&e))
725                             .map(TypeInfo::original);
726                         (ty, None)
727                     },
728                     ast::IdentPat(it) => {
729                         cov_mark::hit!(expected_type_if_let_with_leading_char);
730                         cov_mark::hit!(expected_type_match_arm_with_leading_char);
731                         let ty = self.sema.type_of_pat(&ast::Pat::from(it)).map(TypeInfo::original);
732                         (ty, None)
733                     },
734                     ast::Fn(it) => {
735                         cov_mark::hit!(expected_type_fn_ret_with_leading_char);
736                         cov_mark::hit!(expected_type_fn_ret_without_leading_char);
737                         let def = self.sema.to_def(&it);
738                         (def.map(|def| def.ret_type(self.db)), None)
739                     },
740                     ast::ClosureExpr(it) => {
741                         let ty = self.sema.type_of_expr(&it.into());
742                         ty.and_then(|ty| ty.original.as_callable(self.db))
743                             .map(|c| (Some(c.return_type()), None))
744                             .unwrap_or((None, None))
745                     },
746                     ast::ParamList(_) => (None, None),
747                     ast::Stmt(_) => (None, None),
748                     ast::Item(_) => (None, None),
749                     _ => {
750                         match node.parent() {
751                             Some(n) => {
752                                 node = n;
753                                 continue;
754                             },
755                             None => (None, None),
756                         }
757                     },
758                 }
759             };
760         }
761     }
762
763     /// Fill the completion context, this is what does semantic reasoning about the surrounding context
764     /// of the completion location.
765     fn fill(
766         &mut self,
767         original_file: &SyntaxNode,
768         file_with_fake_ident: SyntaxNode,
769         offset: TextSize,
770         derive_ctx: Option<(SyntaxNode, SyntaxNode, TextSize, ast::Attr)>,
771     ) {
772         let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased().unwrap();
773         let syntax_element = NodeOrToken::Token(fake_ident_token);
774         if is_in_token_of_for_loop(syntax_element.clone()) {
775             // for pat $0
776             // there is nothing to complete here except `in` keyword
777             // don't bother populating the context
778             // FIXME: the completion calculations should end up good enough
779             // such that this special case becomes unnecessary
780             return;
781         }
782
783         self.previous_token = previous_token(syntax_element.clone());
784         self.fake_attribute_under_caret = syntax_element.ancestors().find_map(ast::Attr::cast);
785
786         self.incomplete_let =
787             syntax_element.ancestors().take(6).find_map(ast::LetStmt::cast).map_or(false, |it| {
788                 it.syntax().text_range().end() == syntax_element.text_range().end()
789             });
790
791         (self.expected_type, self.expected_name) = self.expected_type_and_name();
792
793         // Overwrite the path kind for derives
794         if let Some((original_file, file_with_fake_ident, offset, origin_attr)) = derive_ctx {
795             self.existing_derives = self
796                 .sema
797                 .resolve_derive_macro(&origin_attr)
798                 .into_iter()
799                 .flatten()
800                 .flatten()
801                 .collect();
802
803             if let Some(ast::NameLike::NameRef(name_ref)) =
804                 find_node_at_offset(&file_with_fake_ident, offset)
805             {
806                 self.name_syntax =
807                     find_node_at_offset(&original_file, name_ref.syntax().text_range().start());
808                 if let Some((path_ctx, _)) =
809                     Self::classify_name_ref(&self.sema, &original_file, name_ref)
810                 {
811                     self.path_context =
812                         Some(PathCompletionCtx { kind: Some(PathKind::Derive), ..path_ctx });
813                 }
814             }
815             return;
816         }
817
818         let name_like = match find_node_at_offset(&file_with_fake_ident, offset) {
819             Some(it) => it,
820             None => return,
821         };
822         self.completion_location =
823             determine_location(&self.sema, original_file, offset, &name_like);
824         self.prev_sibling = determine_prev_sibling(&name_like);
825         self.name_syntax =
826             find_node_at_offset(original_file, name_like.syntax().text_range().start());
827         self.impl_def = self
828             .sema
829             .token_ancestors_with_macros(self.token.clone())
830             .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
831             .find_map(ast::Impl::cast);
832         self.function_def = self
833             .sema
834             .token_ancestors_with_macros(self.token.clone())
835             .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
836             .find_map(ast::Fn::cast);
837
838         match name_like {
839             ast::NameLike::Lifetime(lifetime) => {
840                 self.lifetime_ctx = Self::classify_lifetime(&self.sema, original_file, lifetime);
841             }
842             ast::NameLike::NameRef(name_ref) => {
843                 if let Some((path_ctx, pat_ctx)) =
844                     Self::classify_name_ref(&self.sema, original_file, name_ref)
845                 {
846                     self.path_context = Some(path_ctx);
847                     self.pattern_ctx = pat_ctx;
848                 }
849             }
850             ast::NameLike::Name(name) => {
851                 if let Some((name_ctx, pat_ctx)) =
852                     Self::classify_name(&self.sema, original_file, name)
853                 {
854                     self.pattern_ctx = pat_ctx;
855                     self.name_ctx = Some(name_ctx);
856                 }
857             }
858         }
859     }
860
861     fn classify_lifetime(
862         _sema: &Semantics<RootDatabase>,
863         _original_file: &SyntaxNode,
864         lifetime: ast::Lifetime,
865     ) -> Option<LifetimeContext> {
866         let parent = lifetime.syntax().parent()?;
867         if parent.kind() == ERROR {
868             return None;
869         }
870
871         Some(match_ast! {
872             match parent {
873                 ast::LifetimeParam(param) => LifetimeContext::LifetimeParam {
874                     is_decl: param.lifetime().as_ref() == Some(&lifetime),
875                     param
876                 },
877                 ast::BreakExpr(_) => LifetimeContext::LabelRef,
878                 ast::ContinueExpr(_) => LifetimeContext::LabelRef,
879                 ast::Label(_) => LifetimeContext::LabelDef,
880                 _ => LifetimeContext::Lifetime,
881             }
882         })
883     }
884
885     fn classify_name(
886         _sema: &Semantics<RootDatabase>,
887         original_file: &SyntaxNode,
888         name: ast::Name,
889     ) -> Option<(NameContext, Option<PatternContext>)> {
890         let parent = name.syntax().parent()?;
891         let mut pat_ctx = None;
892         let name_ctx = match_ast! {
893             match parent {
894                 ast::Const(_) => NameContext::Const,
895                 ast::ConstParam(_) => NameContext::ConstParam,
896                 ast::Enum(_) => NameContext::Enum,
897                 ast::Fn(_) => NameContext::Function,
898                 ast::IdentPat(bind_pat) => {
899                     let is_name_in_field_pat = bind_pat
900                         .syntax()
901                         .parent()
902                         .and_then(ast::RecordPatField::cast)
903                         .map_or(false, |pat_field| pat_field.name_ref().is_none());
904                     if !is_name_in_field_pat {
905                         pat_ctx = Some(pattern_context_for(original_file, bind_pat.into()));
906                     }
907
908                     NameContext::IdentPat
909                 },
910                 ast::MacroDef(_) => NameContext::MacroDef,
911                 ast::MacroRules(_) => NameContext::MacroRules,
912                 ast::Module(module) => NameContext::Module(module),
913                 ast::RecordField(_) => NameContext::RecordField,
914                 ast::Rename(_) => NameContext::Rename,
915                 ast::SelfParam(_) => NameContext::SelfParam,
916                 ast::Static(_) => NameContext::Static,
917                 ast::Struct(_) => NameContext::Struct,
918                 ast::Trait(_) => NameContext::Trait,
919                 ast::TypeAlias(_) => NameContext::TypeAlias,
920                 ast::TypeParam(_) => NameContext::TypeParam,
921                 ast::Union(_) => NameContext::Union,
922                 ast::Variant(_) => NameContext::Variant,
923                 _ => return None,
924             }
925         };
926         Some((name_ctx, pat_ctx))
927     }
928
929     fn classify_name_ref(
930         sema: &Semantics<RootDatabase>,
931         original_file: &SyntaxNode,
932         name_ref: ast::NameRef,
933     ) -> Option<(PathCompletionCtx, Option<PatternContext>)> {
934         let parent = name_ref.syntax().parent()?;
935         let segment = ast::PathSegment::cast(parent)?;
936         let path = segment.parent_path();
937
938         let mut path_ctx = PathCompletionCtx {
939             has_call_parens: false,
940             is_absolute_path: false,
941             qualifier: None,
942             has_type_args: false,
943             can_be_stmt: false,
944             in_loop_body: false,
945             kind: None,
946         };
947         let mut pat_ctx = None;
948         path_ctx.in_loop_body = is_in_loop_body(name_ref.syntax());
949
950         path_ctx.kind = path.syntax().ancestors().find_map(|it| {
951             // using Option<Option<PathKind>> as extra controlflow
952             let kind = match_ast! {
953                 match it {
954                     ast::PathType(_) => Some(PathKind::Type),
955                     ast::PathExpr(it) => {
956                         path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
957                         Some(PathKind::Expr)
958                     },
959                     ast::TupleStructPat(it) => {
960                         path_ctx.has_call_parens = true;
961                         pat_ctx = Some(pattern_context_for(original_file, it.into()));
962                         Some(PathKind::Pat)
963                     },
964                     ast::RecordPat(it) => {
965                         path_ctx.has_call_parens = true;
966                         pat_ctx = Some(pattern_context_for(original_file, it.into()));
967                         Some(PathKind::Pat)
968                     },
969                     ast::PathPat(it) => {
970                         pat_ctx = Some(pattern_context_for(original_file, it.into()));
971                         Some(PathKind::Pat)
972                     },
973                     ast::MacroCall(it) => it.excl_token().and(Some(PathKind::Mac)),
974                     ast::Meta(meta) => (|| {
975                         let attr = meta.parent_attr()?;
976                         let kind = attr.kind();
977                         let attached = attr.syntax().parent()?;
978                         let is_trailing_outer_attr = kind != AttrKind::Inner
979                             && non_trivia_sibling(attr.syntax().clone().into(), syntax::Direction::Next).is_none();
980                         let annotated_item_kind = if is_trailing_outer_attr {
981                             None
982                         } else {
983                             Some(attached.kind())
984                         };
985                         Some(PathKind::Attr {
986                             kind,
987                             annotated_item_kind,
988                         })
989                     })(),
990                     ast::Visibility(it) => Some(PathKind::Vis { has_in_token: it.in_token().is_some() }),
991                     ast::UseTree(_) => Some(PathKind::Use),
992                     _ => return None,
993                 }
994             };
995             Some(kind)
996         }).flatten();
997         path_ctx.has_type_args = segment.generic_arg_list().is_some();
998
999         if let Some((path, use_tree_parent)) = path_or_use_tree_qualifier(&path) {
1000             if !use_tree_parent {
1001                 path_ctx.is_absolute_path =
1002                     path.top_path().segment().map_or(false, |it| it.coloncolon_token().is_some());
1003             }
1004
1005             let path = path
1006                 .segment()
1007                 .and_then(|it| find_node_in_file(original_file, &it))
1008                 .map(|it| it.parent_path());
1009             path_ctx.qualifier = path.map(|path| {
1010                 let res = sema.resolve_path(&path);
1011                 let is_super_chain = iter::successors(Some(path.clone()), |p| p.qualifier())
1012                     .all(|p| p.segment().and_then(|s| s.super_token()).is_some());
1013                 PathQualifierCtx { path, resolution: res, is_super_chain, use_tree_parent }
1014             });
1015             return Some((path_ctx, pat_ctx));
1016         }
1017
1018         if let Some(segment) = path.segment() {
1019             if segment.coloncolon_token().is_some() {
1020                 path_ctx.is_absolute_path = true;
1021                 return Some((path_ctx, pat_ctx));
1022             }
1023         }
1024
1025         // Find either enclosing expr statement (thing with `;`) or a
1026         // block. If block, check that we are the last expr.
1027         path_ctx.can_be_stmt = name_ref
1028             .syntax()
1029             .ancestors()
1030             .find_map(|node| {
1031                 if let Some(stmt) = ast::ExprStmt::cast(node.clone()) {
1032                     return Some(stmt.syntax().text_range() == name_ref.syntax().text_range());
1033                 }
1034                 if let Some(stmt_list) = ast::StmtList::cast(node) {
1035                     return Some(
1036                         stmt_list.tail_expr().map(|e| e.syntax().text_range())
1037                             == Some(name_ref.syntax().text_range()),
1038                     );
1039                 }
1040                 None
1041             })
1042             .unwrap_or(false);
1043         Some((path_ctx, pat_ctx))
1044     }
1045 }
1046
1047 fn pattern_context_for(original_file: &SyntaxNode, pat: ast::Pat) -> PatternContext {
1048     let mut is_param = None;
1049     let (refutability, has_type_ascription) =
1050     pat
1051         .syntax()
1052         .ancestors()
1053         .skip_while(|it| ast::Pat::can_cast(it.kind()))
1054         .next()
1055         .map_or((PatternRefutability::Irrefutable, false), |node| {
1056             let refutability = match_ast! {
1057                 match node {
1058                     ast::LetStmt(let_) => return (PatternRefutability::Irrefutable, let_.ty().is_some()),
1059                     ast::Param(param) => {
1060                         let has_type_ascription = param.ty().is_some();
1061                         is_param = (|| {
1062                             let fake_param_list = param.syntax().parent().and_then(ast::ParamList::cast)?;
1063                             let param_list = find_node_in_file_compensated(original_file, &fake_param_list)?;
1064                             let param_list_owner = param_list.syntax().parent()?;
1065                             let kind = match_ast! {
1066                                 match param_list_owner {
1067                                     ast::ClosureExpr(closure) => ParamKind::Closure(closure),
1068                                     ast::Fn(fn_) => ParamKind::Function(fn_),
1069                                     _ => return None,
1070                                 }
1071                             };
1072                             Some((param_list, param, kind))
1073                         })();
1074                         return (PatternRefutability::Irrefutable, has_type_ascription)
1075                     },
1076                     ast::MatchArm(_) => PatternRefutability::Refutable,
1077                     ast::LetExpr(_) => PatternRefutability::Refutable,
1078                     ast::ForExpr(_) => PatternRefutability::Irrefutable,
1079                     _ => PatternRefutability::Irrefutable,
1080                 }
1081             };
1082             (refutability, false)
1083         });
1084     let (ref_token, mut_token) = match &pat {
1085         ast::Pat::IdentPat(it) => (it.ref_token(), it.mut_token()),
1086         _ => (None, None),
1087     };
1088     PatternContext {
1089         refutability,
1090         param_ctx: is_param,
1091         has_type_ascription,
1092         parent_pat: pat.syntax().parent().and_then(ast::Pat::cast),
1093         mut_token,
1094         ref_token,
1095     }
1096 }
1097
1098 /// Attempts to find `node` inside `syntax` via `node`'s text range.
1099 fn find_node_in_file<N: AstNode>(syntax: &SyntaxNode, node: &N) -> Option<N> {
1100     let syntax_range = syntax.text_range();
1101     let range = node.syntax().text_range();
1102     let intersection = range.intersect(syntax_range)?;
1103     syntax.covering_element(intersection).ancestors().find_map(N::cast)
1104 }
1105
1106 /// Attempts to find `node` inside `syntax` via `node`'s text range while compensating
1107 /// for the offset introduced by the fake ident.
1108 /// This is wrong if `node` comes before the insertion point! Use `find_node_in_file` instead.
1109 fn find_node_in_file_compensated<N: AstNode>(syntax: &SyntaxNode, node: &N) -> Option<N> {
1110     let syntax_range = syntax.text_range();
1111     let range = node.syntax().text_range();
1112     let end = range.end().checked_sub(TextSize::try_from(COMPLETION_MARKER.len()).ok()?)?;
1113     if end < range.start() {
1114         return None;
1115     }
1116     let range = TextRange::new(range.start(), end);
1117     // our inserted ident could cause `range` to be go outside of the original syntax, so cap it
1118     let intersection = range.intersect(syntax_range)?;
1119     syntax.covering_element(intersection).ancestors().find_map(N::cast)
1120 }
1121
1122 fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<(ast::Path, bool)> {
1123     if let Some(qual) = path.qualifier() {
1124         return Some((qual, false));
1125     }
1126     let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?;
1127     let use_tree = use_tree_list.syntax().parent().and_then(ast::UseTree::cast)?;
1128     Some((use_tree.path()?, true))
1129 }
1130
1131 fn has_ref(token: &SyntaxToken) -> bool {
1132     let mut token = token.clone();
1133     for skip in [IDENT, WHITESPACE, T![mut]] {
1134         if token.kind() == skip {
1135             token = match token.prev_token() {
1136                 Some(it) => it,
1137                 None => return false,
1138             }
1139         }
1140     }
1141     token.kind() == T![&]
1142 }
1143
1144 const OP_TRAIT_LANG_NAMES: &[&str] = &[
1145     "add_assign",
1146     "add",
1147     "bitand_assign",
1148     "bitand",
1149     "bitor_assign",
1150     "bitor",
1151     "bitxor_assign",
1152     "bitxor",
1153     "deref_mut",
1154     "deref",
1155     "div_assign",
1156     "div",
1157     "eq",
1158     "fn_mut",
1159     "fn_once",
1160     "fn",
1161     "index_mut",
1162     "index",
1163     "mul_assign",
1164     "mul",
1165     "neg",
1166     "not",
1167     "partial_ord",
1168     "rem_assign",
1169     "rem",
1170     "shl_assign",
1171     "shl",
1172     "shr_assign",
1173     "shr",
1174     "sub",
1175 ];
1176
1177 #[cfg(test)]
1178 mod tests {
1179     use expect_test::{expect, Expect};
1180     use hir::HirDisplay;
1181
1182     use crate::tests::{position, TEST_CONFIG};
1183
1184     use super::CompletionContext;
1185
1186     fn check_expected_type_and_name(ra_fixture: &str, expect: Expect) {
1187         let (db, pos) = position(ra_fixture);
1188         let config = TEST_CONFIG;
1189         let completion_context = CompletionContext::new(&db, pos, &config).unwrap();
1190
1191         let ty = completion_context
1192             .expected_type
1193             .map(|t| t.display_test(&db).to_string())
1194             .unwrap_or("?".to_owned());
1195
1196         let name = completion_context
1197             .expected_name
1198             .map_or_else(|| "?".to_owned(), |name| name.to_string());
1199
1200         expect.assert_eq(&format!("ty: {}, name: {}", ty, name));
1201     }
1202
1203     #[test]
1204     fn expected_type_let_without_leading_char() {
1205         cov_mark::check!(expected_type_let_without_leading_char);
1206         check_expected_type_and_name(
1207             r#"
1208 fn foo() {
1209     let x: u32 = $0;
1210 }
1211 "#,
1212             expect![[r#"ty: u32, name: x"#]],
1213         );
1214     }
1215
1216     #[test]
1217     fn expected_type_let_with_leading_char() {
1218         cov_mark::check!(expected_type_let_with_leading_char);
1219         check_expected_type_and_name(
1220             r#"
1221 fn foo() {
1222     let x: u32 = c$0;
1223 }
1224 "#,
1225             expect![[r#"ty: u32, name: x"#]],
1226         );
1227     }
1228
1229     #[test]
1230     fn expected_type_let_pat() {
1231         check_expected_type_and_name(
1232             r#"
1233 fn foo() {
1234     let x$0 = 0u32;
1235 }
1236 "#,
1237             expect![[r#"ty: u32, name: ?"#]],
1238         );
1239         check_expected_type_and_name(
1240             r#"
1241 fn foo() {
1242     let $0 = 0u32;
1243 }
1244 "#,
1245             expect![[r#"ty: u32, name: ?"#]],
1246         );
1247     }
1248
1249     #[test]
1250     fn expected_type_fn_param() {
1251         cov_mark::check!(expected_type_fn_param);
1252         check_expected_type_and_name(
1253             r#"
1254 fn foo() { bar($0); }
1255 fn bar(x: u32) {}
1256 "#,
1257             expect![[r#"ty: u32, name: x"#]],
1258         );
1259         check_expected_type_and_name(
1260             r#"
1261 fn foo() { bar(c$0); }
1262 fn bar(x: u32) {}
1263 "#,
1264             expect![[r#"ty: u32, name: x"#]],
1265         );
1266     }
1267
1268     #[test]
1269     fn expected_type_fn_param_ref() {
1270         cov_mark::check!(expected_type_fn_param_ref);
1271         check_expected_type_and_name(
1272             r#"
1273 fn foo() { bar(&$0); }
1274 fn bar(x: &u32) {}
1275 "#,
1276             expect![[r#"ty: u32, name: x"#]],
1277         );
1278         check_expected_type_and_name(
1279             r#"
1280 fn foo() { bar(&mut $0); }
1281 fn bar(x: &mut u32) {}
1282 "#,
1283             expect![[r#"ty: u32, name: x"#]],
1284         );
1285         check_expected_type_and_name(
1286             r#"
1287 fn foo() { bar(& c$0); }
1288 fn bar(x: &u32) {}
1289         "#,
1290             expect![[r#"ty: u32, name: x"#]],
1291         );
1292         check_expected_type_and_name(
1293             r#"
1294 fn foo() { bar(&mut c$0); }
1295 fn bar(x: &mut u32) {}
1296 "#,
1297             expect![[r#"ty: u32, name: x"#]],
1298         );
1299         check_expected_type_and_name(
1300             r#"
1301 fn foo() { bar(&c$0); }
1302 fn bar(x: &u32) {}
1303         "#,
1304             expect![[r#"ty: u32, name: x"#]],
1305         );
1306     }
1307
1308     #[test]
1309     fn expected_type_struct_field_without_leading_char() {
1310         cov_mark::check!(expected_type_struct_field_without_leading_char);
1311         check_expected_type_and_name(
1312             r#"
1313 struct Foo { a: u32 }
1314 fn foo() {
1315     Foo { a: $0 };
1316 }
1317 "#,
1318             expect![[r#"ty: u32, name: a"#]],
1319         )
1320     }
1321
1322     #[test]
1323     fn expected_type_struct_field_followed_by_comma() {
1324         cov_mark::check!(expected_type_struct_field_followed_by_comma);
1325         check_expected_type_and_name(
1326             r#"
1327 struct Foo { a: u32 }
1328 fn foo() {
1329     Foo { a: $0, };
1330 }
1331 "#,
1332             expect![[r#"ty: u32, name: a"#]],
1333         )
1334     }
1335
1336     #[test]
1337     fn expected_type_generic_struct_field() {
1338         check_expected_type_and_name(
1339             r#"
1340 struct Foo<T> { a: T }
1341 fn foo() -> Foo<u32> {
1342     Foo { a: $0 }
1343 }
1344 "#,
1345             expect![[r#"ty: u32, name: a"#]],
1346         )
1347     }
1348
1349     #[test]
1350     fn expected_type_struct_field_with_leading_char() {
1351         cov_mark::check!(expected_type_struct_field_with_leading_char);
1352         check_expected_type_and_name(
1353             r#"
1354 struct Foo { a: u32 }
1355 fn foo() {
1356     Foo { a: c$0 };
1357 }
1358 "#,
1359             expect![[r#"ty: u32, name: a"#]],
1360         );
1361     }
1362
1363     #[test]
1364     fn expected_type_match_arm_without_leading_char() {
1365         cov_mark::check!(expected_type_match_arm_without_leading_char);
1366         check_expected_type_and_name(
1367             r#"
1368 enum E { X }
1369 fn foo() {
1370    match E::X { $0 }
1371 }
1372 "#,
1373             expect![[r#"ty: E, name: ?"#]],
1374         );
1375     }
1376
1377     #[test]
1378     fn expected_type_match_arm_with_leading_char() {
1379         cov_mark::check!(expected_type_match_arm_with_leading_char);
1380         check_expected_type_and_name(
1381             r#"
1382 enum E { X }
1383 fn foo() {
1384    match E::X { c$0 }
1385 }
1386 "#,
1387             expect![[r#"ty: E, name: ?"#]],
1388         );
1389     }
1390
1391     #[test]
1392     fn expected_type_if_let_without_leading_char() {
1393         cov_mark::check!(expected_type_if_let_without_leading_char);
1394         check_expected_type_and_name(
1395             r#"
1396 enum Foo { Bar, Baz, Quux }
1397
1398 fn foo() {
1399     let f = Foo::Quux;
1400     if let $0 = f { }
1401 }
1402 "#,
1403             expect![[r#"ty: Foo, name: ?"#]],
1404         )
1405     }
1406
1407     #[test]
1408     fn expected_type_if_let_with_leading_char() {
1409         cov_mark::check!(expected_type_if_let_with_leading_char);
1410         check_expected_type_and_name(
1411             r#"
1412 enum Foo { Bar, Baz, Quux }
1413
1414 fn foo() {
1415     let f = Foo::Quux;
1416     if let c$0 = f { }
1417 }
1418 "#,
1419             expect![[r#"ty: Foo, name: ?"#]],
1420         )
1421     }
1422
1423     #[test]
1424     fn expected_type_fn_ret_without_leading_char() {
1425         cov_mark::check!(expected_type_fn_ret_without_leading_char);
1426         check_expected_type_and_name(
1427             r#"
1428 fn foo() -> u32 {
1429     $0
1430 }
1431 "#,
1432             expect![[r#"ty: u32, name: ?"#]],
1433         )
1434     }
1435
1436     #[test]
1437     fn expected_type_fn_ret_with_leading_char() {
1438         cov_mark::check!(expected_type_fn_ret_with_leading_char);
1439         check_expected_type_and_name(
1440             r#"
1441 fn foo() -> u32 {
1442     c$0
1443 }
1444 "#,
1445             expect![[r#"ty: u32, name: ?"#]],
1446         )
1447     }
1448
1449     #[test]
1450     fn expected_type_fn_ret_fn_ref_fully_typed() {
1451         check_expected_type_and_name(
1452             r#"
1453 fn foo() -> u32 {
1454     foo$0
1455 }
1456 "#,
1457             expect![[r#"ty: u32, name: ?"#]],
1458         )
1459     }
1460
1461     #[test]
1462     fn expected_type_closure_param_return() {
1463         // FIXME: make this work with `|| $0`
1464         check_expected_type_and_name(
1465             r#"
1466 //- minicore: fn
1467 fn foo() {
1468     bar(|| a$0);
1469 }
1470
1471 fn bar(f: impl FnOnce() -> u32) {}
1472 "#,
1473             expect![[r#"ty: u32, name: ?"#]],
1474         );
1475     }
1476
1477     #[test]
1478     fn expected_type_generic_function() {
1479         check_expected_type_and_name(
1480             r#"
1481 fn foo() {
1482     bar::<u32>($0);
1483 }
1484
1485 fn bar<T>(t: T) {}
1486 "#,
1487             expect![[r#"ty: u32, name: t"#]],
1488         );
1489     }
1490
1491     #[test]
1492     fn expected_type_generic_method() {
1493         check_expected_type_and_name(
1494             r#"
1495 fn foo() {
1496     S(1u32).bar($0);
1497 }
1498
1499 struct S<T>(T);
1500 impl<T> S<T> {
1501     fn bar(self, t: T) {}
1502 }
1503 "#,
1504             expect![[r#"ty: u32, name: t"#]],
1505         );
1506     }
1507
1508     #[test]
1509     fn expected_type_functional_update() {
1510         cov_mark::check!(expected_type_struct_func_update);
1511         check_expected_type_and_name(
1512             r#"
1513 struct Foo { field: u32 }
1514 fn foo() {
1515     Foo {
1516         ..$0
1517     }
1518 }
1519 "#,
1520             expect![[r#"ty: Foo, name: ?"#]],
1521         );
1522     }
1523
1524     #[test]
1525     fn expected_type_param_pat() {
1526         check_expected_type_and_name(
1527             r#"
1528 struct Foo { field: u32 }
1529 fn foo(a$0: Foo) {}
1530 "#,
1531             expect![[r#"ty: Foo, name: ?"#]],
1532         );
1533         check_expected_type_and_name(
1534             r#"
1535 struct Foo { field: u32 }
1536 fn foo($0: Foo) {}
1537 "#,
1538             // FIXME make this work, currently fails due to pattern recovery eating the `:`
1539             expect![[r#"ty: ?, name: ?"#]],
1540         );
1541     }
1542 }