Skip to main content

ide/
signature_help.rs

1//! This module provides primitives for showing type and function parameter information when editing
2//! a call or use-site.
3
4use std::collections::BTreeSet;
5
6use either::Either;
7use hir::{
8    AssocItem, DisplayTarget, GenericDef, GenericParam, HirDisplay, ModuleDef, PathResolution,
9    Semantics, Trait,
10};
11use ide_db::{
12    FilePosition, FxIndexMap,
13    active_parameter::{callable_for_arg_list, generic_def_for_node},
14    documentation::{Documentation, HasDocs},
15};
16use itertools::Itertools;
17use span::Edition;
18use stdx::format_to;
19use syntax::{
20    AstNode, Direction, NodeOrToken, SyntaxElementChildren, SyntaxNode, SyntaxToken, T, TextRange,
21    TextSize, ToSmolStr, algo,
22    ast::{self, AstChildren},
23    match_ast,
24};
25
26use crate::RootDatabase;
27
28/// Contains information about an item signature as seen from a use site.
29///
30/// This includes the "active parameter", which is the parameter whose value is currently being
31/// edited.
32#[derive(Debug)]
33pub struct SignatureHelp {
34    pub doc: Option<Documentation<'static>>,
35    pub signature: String,
36    pub active_parameter: Option<usize>,
37    parameters: Vec<TextRange>,
38}
39
40impl SignatureHelp {
41    pub fn parameter_labels(&self) -> impl Iterator<Item = &str> + '_ {
42        self.parameters.iter().map(move |&it| &self.signature[it])
43    }
44
45    pub fn parameter_ranges(&self) -> &[TextRange] {
46        &self.parameters
47    }
48
49    fn push_call_param(&mut self, param: &str) {
50        self.push_param("(", param);
51    }
52
53    fn push_generic_param(&mut self, param: &str) {
54        self.push_param("<", param);
55    }
56
57    fn push_record_field(&mut self, param: &str) {
58        self.push_param("{ ", param);
59    }
60
61    fn push_param(&mut self, opening_delim: &str, param: &str) {
62        if !self.signature.ends_with(opening_delim) {
63            self.signature.push_str(", ");
64        }
65        let start = TextSize::of(&self.signature);
66        self.signature.push_str(param);
67        let end = TextSize::of(&self.signature);
68        self.parameters.push(TextRange::new(start, end))
69    }
70}
71
72/// Computes parameter information for the given position.
73pub(crate) fn signature_help(
74    db: &RootDatabase,
75    FilePosition { file_id, offset }: FilePosition,
76) -> Option<SignatureHelp> {
77    let sema = Semantics::new(db);
78    let file = sema.parse_guess_edition(file_id);
79    let file = file.syntax();
80    let token = file
81        .token_at_offset(offset)
82        .left_biased()
83        // if the cursor is sandwiched between two space tokens and the call is unclosed
84        // this prevents us from leaving the CallExpression
85        .and_then(|tok| algo::skip_trivia_token(tok, Direction::Prev))?;
86    let token = sema.descend_into_macros_single_exact(token);
87    let edition = sema.attach_first_edition(file_id).edition(db);
88    let display_target = sema.first_crate(file_id)?.to_display_target(db);
89
90    for node in token.parent_ancestors() {
91        match_ast! {
92            match node {
93                ast::ArgList(arg_list) => {
94                    let cursor_outside = arg_list.r_paren_token().as_ref() == Some(&token);
95                    if cursor_outside {
96                        continue;
97                    }
98                    return signature_help_for_call(&sema, arg_list, token, edition, display_target);
99                },
100                ast::GenericArgList(garg_list) => {
101                    let cursor_outside = garg_list.r_angle_token().as_ref() == Some(&token);
102                    if cursor_outside {
103                        continue;
104                    }
105                    return signature_help_for_generics(&sema, garg_list, token, edition, display_target);
106                },
107                ast::RecordExpr(record) => {
108                    let cursor_outside = record.record_expr_field_list().and_then(|list| list.r_curly_token()).as_ref() == Some(&token);
109                    if cursor_outside {
110                        continue;
111                    }
112                    return signature_help_for_record_lit(&sema, record, token, edition, display_target);
113                },
114                ast::RecordPat(record) => {
115                    let cursor_outside = record.record_pat_field_list().and_then(|list| list.r_curly_token()).as_ref() == Some(&token);
116                    if cursor_outside {
117                        continue;
118                    }
119                    return signature_help_for_record_pat(&sema, record, token, edition, display_target);
120                },
121                ast::TupleStructPat(tuple_pat) => {
122                    let cursor_outside = tuple_pat.r_paren_token().as_ref() == Some(&token);
123                    if cursor_outside {
124                        continue;
125                    }
126                    return signature_help_for_tuple_struct_pat(&sema, tuple_pat, token, edition, display_target);
127                },
128                ast::TuplePat(tuple_pat) => {
129                    let cursor_outside = tuple_pat.r_paren_token().as_ref() == Some(&token);
130                    if cursor_outside {
131                        continue;
132                    }
133                    return signature_help_for_tuple_pat(&sema, tuple_pat, token, display_target);
134                },
135                ast::TupleExpr(tuple_expr) => {
136                    let cursor_outside = tuple_expr.r_paren_token().as_ref() == Some(&token);
137                    if cursor_outside {
138                        continue;
139                    }
140                    return signature_help_for_tuple_expr(&sema, tuple_expr, token, display_target);
141                },
142                _ => (),
143            }
144        }
145
146        // Stop at multi-line expressions, since the signature of the outer call is not very
147        // helpful inside them.
148        if let Some(expr) = ast::Expr::cast(node.clone())
149            && !matches!(expr, ast::Expr::RecordExpr(..))
150            && expr.syntax().text().contains_char('\n')
151        {
152            break;
153        }
154    }
155
156    None
157}
158
159fn signature_help_for_call(
160    sema: &Semantics<'_, RootDatabase>,
161    arg_list: ast::ArgList,
162    token: SyntaxToken,
163    edition: Edition,
164    display_target: DisplayTarget,
165) -> Option<SignatureHelp> {
166    let (callable, active_parameter) =
167        callable_for_arg_list(sema, arg_list, token.text_range().start())?;
168
169    let mut res =
170        SignatureHelp { doc: None, signature: String::new(), parameters: vec![], active_parameter };
171
172    let db = sema.db;
173    let mut fn_params = None;
174    match callable.kind() {
175        hir::CallableKind::Function(func) => {
176            res.doc = func.docs(db).map(Documentation::into_owned);
177            if func.is_const(db) {
178                format_to!(res.signature, "const ");
179            }
180            if func.is_async(db) {
181                format_to!(res.signature, "async ");
182            }
183            if func.is_unsafe(db) {
184                format_to!(res.signature, "unsafe ");
185            }
186            format_to!(res.signature, "fn {}", func.name(db).display(db, edition));
187
188            let generic_params = GenericDef::Function(func)
189                .params(db)
190                .iter()
191                .filter(|param| match param {
192                    GenericParam::TypeParam(type_param) => !type_param.is_implicit(db),
193                    GenericParam::ConstParam(_) | GenericParam::LifetimeParam(_) => true,
194                })
195                .map(|param| param.display(db, display_target))
196                .join(", ");
197            if !generic_params.is_empty() {
198                format_to!(res.signature, "<{}>", generic_params);
199            }
200
201            fn_params = Some(match callable.receiver_param(db) {
202                Some(_self) => func.params_without_self(db),
203                None => func.assoc_fn_params(db),
204            });
205        }
206        hir::CallableKind::TupleStruct(strukt) => {
207            res.doc = strukt.docs(db).map(Documentation::into_owned);
208            format_to!(res.signature, "struct {}", strukt.name(db).display(db, edition));
209
210            let generic_params = GenericDef::Adt(strukt.into())
211                .params(db)
212                .iter()
213                .map(|param| param.display(db, display_target))
214                .join(", ");
215            if !generic_params.is_empty() {
216                format_to!(res.signature, "<{}>", generic_params);
217            }
218        }
219        hir::CallableKind::TupleEnumVariant(variant) => {
220            res.doc = variant.docs(db).map(Documentation::into_owned);
221            format_to!(
222                res.signature,
223                "enum {}",
224                variant.parent_enum(db).name(db).display(db, edition),
225            );
226
227            let generic_params = GenericDef::Adt(variant.parent_enum(db).into())
228                .params(db)
229                .iter()
230                .map(|param| param.display(db, display_target))
231                .join(", ");
232            if !generic_params.is_empty() {
233                format_to!(res.signature, "<{}>", generic_params);
234            }
235
236            format_to!(res.signature, "::{}", variant.name(db).display(db, edition))
237        }
238        hir::CallableKind::Closure(closure) => {
239            let fn_trait = closure.fn_trait(db);
240            format_to!(res.signature, "impl {fn_trait}")
241        }
242        hir::CallableKind::FnPtr => format_to!(res.signature, "fn"),
243        hir::CallableKind::FnImpl(fn_trait) => match callable.ty().as_adt() {
244            // FIXME: Render docs of the concrete trait impl function
245            Some(adt) => format_to!(
246                res.signature,
247                "<{} as {fn_trait}>::{}",
248                adt.name(db).display(db, edition),
249                fn_trait.function_name()
250            ),
251            None => format_to!(res.signature, "impl {fn_trait}"),
252        },
253    }
254
255    res.signature.push('(');
256    {
257        if let Some((self_param, _)) = callable.receiver_param(db) {
258            format_to!(res.signature, "{}", self_param.display(db, display_target))
259        }
260        let mut buf = String::new();
261        for (idx, p) in callable.params().into_iter().enumerate() {
262            buf.clear();
263            if let Some(param) = sema.source(p.clone()) {
264                match param.value {
265                    Either::Right(param) => match param.pat() {
266                        Some(pat) => format_to!(buf, "{}: ", pat),
267                        None => format_to!(buf, "?: "),
268                    },
269                    Either::Left(_) => format_to!(buf, "self: "),
270                }
271            }
272            // APITs (argument position `impl Trait`s) are inferred as {unknown} as the user is
273            // in the middle of entering call arguments.
274            // In that case, fall back to render definitions of the respective parameters.
275            // This is overly conservative: we do not substitute known type vars
276            // (see FIXME in tests::impl_trait) and falling back on any unknowns.
277            match (p.ty().contains_unknown(), fn_params.as_deref()) {
278                (true, Some(fn_params)) => {
279                    format_to!(buf, "{}", fn_params[idx].ty().display(db, display_target))
280                }
281                _ => format_to!(buf, "{}", p.ty().display(db, display_target)),
282            }
283            res.push_call_param(&buf);
284        }
285    }
286    res.signature.push(')');
287
288    let mut render = |ret_type: hir::Type<'_>| {
289        if !ret_type.is_unit() {
290            format_to!(res.signature, " -> {}", ret_type.display(db, display_target));
291        }
292    };
293    match callable.kind() {
294        hir::CallableKind::Function(func) => render(func.async_ret_type(db).unwrap_or_else(|| {
295            if callable.return_type().contains_unknown() {
296                func.ret_type(db)
297            } else {
298                callable.return_type()
299            }
300        })),
301        hir::CallableKind::Closure(_) | hir::CallableKind::FnPtr | hir::CallableKind::FnImpl(_) => {
302            render(callable.return_type())
303        }
304        hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {}
305    }
306    Some(res)
307}
308
309fn signature_help_for_generics(
310    sema: &Semantics<'_, RootDatabase>,
311    arg_list: ast::GenericArgList,
312    token: SyntaxToken,
313    edition: Edition,
314    display_target: DisplayTarget,
315) -> Option<SignatureHelp> {
316    let (generics_def, mut active_parameter, first_arg_is_non_lifetime, variant) =
317        generic_def_for_node(sema, &arg_list, &token)?;
318    let mut res = SignatureHelp {
319        doc: None,
320        signature: String::new(),
321        parameters: vec![],
322        active_parameter: None,
323    };
324
325    let db = sema.db;
326    match generics_def {
327        hir::GenericDef::Function(it) => {
328            res.doc = it.docs(db).map(Documentation::into_owned);
329            format_to!(res.signature, "fn {}", it.name(db).display(db, edition));
330        }
331        hir::GenericDef::Adt(hir::Adt::Enum(it)) => {
332            res.doc = it.docs(db).map(Documentation::into_owned);
333            format_to!(res.signature, "enum {}", it.name(db).display(db, edition));
334            if let Some(variant) = variant {
335                // In paths, generics of an enum can be specified *after* one of its variants.
336                // eg. `None::<u8>`
337                // We'll use the signature of the enum, but include the docs of the variant.
338                res.doc = variant.docs(db).map(Documentation::into_owned);
339            }
340        }
341        hir::GenericDef::Adt(hir::Adt::Struct(it)) => {
342            res.doc = it.docs(db).map(Documentation::into_owned);
343            format_to!(res.signature, "struct {}", it.name(db).display(db, edition));
344        }
345        hir::GenericDef::Adt(hir::Adt::Union(it)) => {
346            res.doc = it.docs(db).map(Documentation::into_owned);
347            format_to!(res.signature, "union {}", it.name(db).display(db, edition));
348        }
349        hir::GenericDef::Trait(it) => {
350            res.doc = it.docs(db).map(Documentation::into_owned);
351            format_to!(res.signature, "trait {}", it.name(db).display(db, edition));
352        }
353        hir::GenericDef::TypeAlias(it) => {
354            res.doc = it.docs(db).map(Documentation::into_owned);
355            format_to!(res.signature, "type {}", it.name(db).display(db, edition));
356        }
357        // These don't have generic args that can be specified
358        hir::GenericDef::Impl(_) | hir::GenericDef::Const(_) | hir::GenericDef::Static(_) => {
359            return None;
360        }
361    }
362
363    let params = generics_def.params(sema.db);
364    let num_lifetime_params =
365        params.iter().take_while(|param| matches!(param, GenericParam::LifetimeParam(_))).count();
366    if first_arg_is_non_lifetime {
367        // Lifetime parameters were omitted.
368        active_parameter += num_lifetime_params;
369    }
370    res.active_parameter = Some(active_parameter);
371
372    res.signature.push('<');
373    let mut buf = String::new();
374    for param in params {
375        if let hir::GenericParam::TypeParam(ty) = param
376            && ty.is_implicit(db)
377        {
378            continue;
379        }
380
381        buf.clear();
382        format_to!(buf, "{}", param.display(db, display_target));
383        match param {
384            GenericParam::TypeParam(param) => {
385                if let Some(ty) = param.default(db) {
386                    format_to!(buf, " = {}", ty.display(db, display_target));
387                }
388            }
389            GenericParam::ConstParam(param) => {
390                if let Some(expr) = param.default(db, display_target) {
391                    format_to!(buf, " = {}", expr);
392                }
393            }
394            _ => {}
395        }
396        res.push_generic_param(&buf);
397    }
398    if let hir::GenericDef::Trait(tr) = generics_def {
399        add_assoc_type_bindings(db, &mut res, tr, arg_list, edition);
400    }
401    res.signature.push('>');
402
403    Some(res)
404}
405
406fn add_assoc_type_bindings(
407    db: &RootDatabase,
408    res: &mut SignatureHelp,
409    tr: Trait,
410    args: ast::GenericArgList,
411    edition: Edition,
412) {
413    if args.syntax().ancestors().find_map(ast::TypeBound::cast).is_none() {
414        // Assoc type bindings are only valid in type bound position.
415        return;
416    }
417
418    let present_bindings = args
419        .generic_args()
420        .filter_map(|arg| match arg {
421            ast::GenericArg::AssocTypeArg(arg) => arg.name_ref().map(|n| n.to_string()),
422            _ => None,
423        })
424        .collect::<BTreeSet<_>>();
425
426    let mut buf = String::new();
427    for binding in &present_bindings {
428        buf.clear();
429        format_to!(buf, "{} = …", binding);
430        res.push_generic_param(&buf);
431    }
432
433    for item in tr.items_with_supertraits(db) {
434        if let AssocItem::TypeAlias(ty) = item {
435            let name = ty.name(db).display_no_db(edition).to_smolstr();
436            if !present_bindings.contains(&*name) {
437                buf.clear();
438                format_to!(buf, "{} = …", name);
439                res.push_generic_param(&buf);
440            }
441        }
442    }
443}
444
445fn signature_help_for_record_lit(
446    sema: &Semantics<'_, RootDatabase>,
447    record: ast::RecordExpr,
448    token: SyntaxToken,
449    edition: Edition,
450    display_target: DisplayTarget,
451) -> Option<SignatureHelp> {
452    signature_help_for_record_(
453        sema,
454        record.record_expr_field_list()?.syntax().children_with_tokens(),
455        &record.path()?,
456        record
457            .record_expr_field_list()?
458            .fields()
459            .filter_map(|field| sema.resolve_record_field(&field))
460            .map(|(field, _, ty)| (field, ty)),
461        token,
462        edition,
463        display_target,
464    )
465}
466
467fn signature_help_for_record_pat(
468    sema: &Semantics<'_, RootDatabase>,
469    record: ast::RecordPat,
470    token: SyntaxToken,
471    edition: Edition,
472    display_target: DisplayTarget,
473) -> Option<SignatureHelp> {
474    signature_help_for_record_(
475        sema,
476        record.record_pat_field_list()?.syntax().children_with_tokens(),
477        &record.path()?,
478        record
479            .record_pat_field_list()?
480            .fields()
481            .filter_map(|field| sema.resolve_record_pat_field(&field)),
482        token,
483        edition,
484        display_target,
485    )
486}
487
488fn signature_help_for_tuple_struct_pat(
489    sema: &Semantics<'_, RootDatabase>,
490    pat: ast::TupleStructPat,
491    token: SyntaxToken,
492    edition: Edition,
493    display_target: DisplayTarget,
494) -> Option<SignatureHelp> {
495    let path = pat.path()?;
496    let path_res = sema.resolve_path(&path)?;
497    let mut res = SignatureHelp {
498        doc: None,
499        signature: String::new(),
500        parameters: vec![],
501        active_parameter: None,
502    };
503    let db = sema.db;
504
505    let fields: Vec<_> = if let PathResolution::Def(ModuleDef::EnumVariant(variant)) = path_res {
506        let en = variant.parent_enum(db);
507
508        res.doc = en.docs(db).map(Documentation::into_owned);
509        format_to!(
510            res.signature,
511            "enum {}::{} (",
512            en.name(db).display(db, edition),
513            variant.name(db).display(db, edition)
514        );
515        variant.fields(db)
516    } else {
517        let adt = match path_res {
518            PathResolution::SelfType(imp) => imp.self_ty(db).as_adt()?,
519            PathResolution::Def(ModuleDef::Adt(adt)) => adt,
520            _ => return None,
521        };
522
523        match adt {
524            hir::Adt::Struct(it) => {
525                res.doc = it.docs(db).map(Documentation::into_owned);
526                format_to!(res.signature, "struct {} (", it.name(db).display(db, edition));
527                it.fields(db)
528            }
529            _ => return None,
530        }
531    };
532    Some(signature_help_for_tuple_pat_ish(
533        db,
534        res,
535        pat.syntax(),
536        token,
537        pat.fields(),
538        fields.into_iter().map(|it| it.ty(db).to_type(db)),
539        display_target,
540    ))
541}
542
543fn signature_help_for_tuple_pat(
544    sema: &Semantics<'_, RootDatabase>,
545    pat: ast::TuplePat,
546    token: SyntaxToken,
547    display_target: DisplayTarget,
548) -> Option<SignatureHelp> {
549    let db = sema.db;
550    let field_pats = pat.fields();
551    let pat = pat.into();
552    let ty = sema.type_of_pat(&pat)?;
553    let fields = ty.original.tuple_fields(db);
554
555    Some(signature_help_for_tuple_pat_ish(
556        db,
557        SignatureHelp {
558            doc: None,
559            signature: String::from('('),
560            parameters: vec![],
561            active_parameter: None,
562        },
563        pat.syntax(),
564        token,
565        field_pats,
566        fields.into_iter(),
567        display_target,
568    ))
569}
570
571fn signature_help_for_tuple_expr(
572    sema: &Semantics<'_, RootDatabase>,
573    expr: ast::TupleExpr,
574    token: SyntaxToken,
575    display_target: DisplayTarget,
576) -> Option<SignatureHelp> {
577    let active_parameter = Some(
578        expr.syntax()
579            .children_with_tokens()
580            .filter_map(NodeOrToken::into_token)
581            .filter(|t| t.kind() == T![,])
582            .take_while(|t| t.text_range().start() <= token.text_range().start())
583            .count(),
584    );
585
586    let db = sema.db;
587    let mut res = SignatureHelp {
588        doc: None,
589        signature: String::from('('),
590        parameters: vec![],
591        active_parameter,
592    };
593    let expr = sema.type_of_expr(&expr.into())?;
594    let fields = expr.original.tuple_fields(db);
595    let mut buf = String::new();
596    for ty in fields {
597        format_to!(buf, "{}", ty.display_truncated(db, Some(20), display_target));
598        res.push_call_param(&buf);
599        buf.clear();
600    }
601    res.signature.push(')');
602    Some(res)
603}
604
605fn signature_help_for_record_<'db>(
606    sema: &Semantics<'db, RootDatabase>,
607    field_list_children: SyntaxElementChildren,
608    path: &ast::Path,
609    fields2: impl Iterator<Item = (hir::Field, hir::Type<'db>)>,
610    token: SyntaxToken,
611    edition: Edition,
612    display_target: DisplayTarget,
613) -> Option<SignatureHelp> {
614    let active_parameter = field_list_children
615        .filter_map(NodeOrToken::into_token)
616        .filter(|t| t.kind() == T![,])
617        .take_while(|t| t.text_range().start() <= token.text_range().start())
618        .count();
619
620    let mut res = SignatureHelp {
621        doc: None,
622        signature: String::new(),
623        parameters: vec![],
624        active_parameter: Some(active_parameter),
625    };
626
627    let fields;
628
629    let db = sema.db;
630    let path_res = sema.resolve_path(path)?;
631    if let PathResolution::Def(ModuleDef::EnumVariant(variant)) = path_res {
632        fields = variant.fields(db);
633        let en = variant.parent_enum(db);
634
635        res.doc = en.docs(db).map(Documentation::into_owned);
636        format_to!(
637            res.signature,
638            "enum {}::{} {{ ",
639            en.name(db).display(db, edition),
640            variant.name(db).display(db, edition)
641        );
642    } else {
643        let adt = match path_res {
644            PathResolution::SelfType(imp) => imp.self_ty(db).as_adt()?,
645            PathResolution::Def(ModuleDef::Adt(adt)) => adt,
646            _ => return None,
647        };
648
649        match adt {
650            hir::Adt::Struct(it) => {
651                fields = it.fields(db);
652                res.doc = it.docs(db).map(Documentation::into_owned);
653                format_to!(res.signature, "struct {} {{ ", it.name(db).display(db, edition));
654            }
655            hir::Adt::Union(it) => {
656                fields = it.fields(db);
657                res.doc = it.docs(db).map(Documentation::into_owned);
658                format_to!(res.signature, "union {} {{ ", it.name(db).display(db, edition));
659            }
660            _ => return None,
661        }
662    }
663
664    let mut fields =
665        fields.into_iter().map(|field| (field.name(db), Some(field))).collect::<FxIndexMap<_, _>>();
666    let mut buf = String::new();
667    for (field, ty) in fields2 {
668        let name = field.name(db);
669        format_to!(
670            buf,
671            "{}: {}",
672            name.display(db, edition),
673            ty.display_truncated(db, Some(20), display_target)
674        );
675        res.push_record_field(&buf);
676        buf.clear();
677
678        if let Some(field) = fields.get_mut(&name) {
679            *field = None;
680        }
681    }
682    for (name, field) in fields {
683        let Some(field) = field else { continue };
684        format_to!(
685            buf,
686            "{}: {}",
687            name.display(db, edition),
688            field.ty(db).display_truncated(db, Some(20), display_target)
689        );
690        res.push_record_field(&buf);
691        buf.clear();
692    }
693    res.signature.push_str(" }");
694    Some(res)
695}
696
697fn signature_help_for_tuple_pat_ish<'db>(
698    db: &'db RootDatabase,
699    mut res: SignatureHelp,
700    pat: &SyntaxNode,
701    token: SyntaxToken,
702    mut field_pats: AstChildren<ast::Pat>,
703    fields: impl ExactSizeIterator<Item = hir::Type<'db>>,
704    display_target: DisplayTarget,
705) -> SignatureHelp {
706    let rest_pat = field_pats.find(|it| matches!(it, ast::Pat::RestPat(_)));
707    let is_left_of_rest_pat =
708        rest_pat.is_none_or(|it| token.text_range().start() < it.syntax().text_range().end());
709
710    let commas = pat
711        .children_with_tokens()
712        .filter_map(NodeOrToken::into_token)
713        .filter(|t| t.kind() == T![,]);
714
715    res.active_parameter = {
716        Some(if is_left_of_rest_pat {
717            commas.take_while(|t| t.text_range().start() <= token.text_range().start()).count()
718        } else {
719            let n_commas = commas
720                .collect::<Vec<_>>()
721                .into_iter()
722                .rev()
723                .take_while(|t| t.text_range().start() > token.text_range().start())
724                .count();
725            fields.len().saturating_sub(1).saturating_sub(n_commas)
726        })
727    };
728
729    let mut buf = String::new();
730    for ty in fields {
731        format_to!(buf, "{}", ty.display_truncated(db, Some(20), display_target));
732        res.push_call_param(&buf);
733        buf.clear();
734    }
735    res.signature.push(')');
736    res
737}
738#[cfg(test)]
739mod tests {
740
741    use expect_test::{Expect, expect};
742    use ide_db::FilePosition;
743    use stdx::format_to;
744    use test_fixture::ChangeFixture;
745
746    use crate::RootDatabase;
747
748    /// Creates analysis from a multi-file fixture, returns positions marked with $0.
749    pub(crate) fn position(
750        #[rust_analyzer::rust_fixture] ra_fixture: &str,
751    ) -> (RootDatabase, FilePosition) {
752        let mut database = RootDatabase::default();
753        let change_fixture = ChangeFixture::parse(ra_fixture);
754        database.apply_change(change_fixture.change);
755        let (file_id, range_or_offset) =
756            change_fixture.file_position.expect("expected a marker ($0)");
757        let offset = range_or_offset.expect_offset();
758        let position = FilePosition { file_id: file_id.file_id(), offset };
759        (database, position)
760    }
761
762    #[track_caller]
763    fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
764        let (db, position) = position(ra_fixture);
765        let sig_help = hir::attach_db(&db, || crate::signature_help::signature_help(&db, position));
766        let actual = match sig_help {
767            Some(sig_help) => {
768                let mut rendered = String::new();
769                if let Some(docs) = &sig_help.doc {
770                    format_to!(rendered, "{}\n------\n", docs.as_str());
771                }
772                format_to!(rendered, "{}\n", sig_help.signature);
773                let mut offset = 0;
774                for (i, range) in sig_help.parameter_ranges().iter().enumerate() {
775                    let is_active = sig_help.active_parameter == Some(i);
776
777                    let start = u32::from(range.start());
778                    let gap = start.checked_sub(offset).unwrap_or_else(|| {
779                        panic!("parameter ranges out of order: {:?}", sig_help.parameter_ranges())
780                    });
781                    rendered.extend(std::iter::repeat_n(' ', gap as usize));
782                    let param_text = &sig_help.signature[*range];
783                    let width = param_text.chars().count(); // …
784                    let marker = if is_active { '^' } else { '-' };
785                    rendered.extend(std::iter::repeat_n(marker, width));
786                    offset += gap + u32::from(range.len());
787                }
788                if !sig_help.parameter_ranges().is_empty() {
789                    format_to!(rendered, "\n");
790                }
791                rendered
792            }
793            None => String::new(),
794        };
795        expect.assert_eq(&actual);
796    }
797
798    #[test]
799    fn test_fn_signature_two_args() {
800        check(
801            r#"
802//- minicore: sized, fn
803fn foo(x: u32, y: u32) -> u32 {x + y}
804fn bar() { foo($03, ); }
805"#,
806            expect![[r#"
807                fn foo(x: u32, y: u32) -> u32
808                       ^^^^^^  ------
809            "#]],
810        );
811        check(
812            r#"
813//- minicore: sized, fn
814fn foo(x: u32, y: u32) -> u32 {x + y}
815fn bar() { foo(3$0, ); }
816"#,
817            expect![[r#"
818                fn foo(x: u32, y: u32) -> u32
819                       ^^^^^^  ------
820            "#]],
821        );
822        check(
823            r#"
824//- minicore: sized, fn
825fn foo(x: u32, y: u32) -> u32 {x + y}
826fn bar() { foo(3,$0 ); }
827"#,
828            expect![[r#"
829                fn foo(x: u32, y: u32) -> u32
830                       ------  ^^^^^^
831            "#]],
832        );
833        check(
834            r#"
835//- minicore: sized, fn
836fn foo(x: u32, y: u32) -> u32 {x + y}
837fn bar() { foo(3, $0); }
838"#,
839            expect![[r#"
840                fn foo(x: u32, y: u32) -> u32
841                       ------  ^^^^^^
842            "#]],
843        );
844    }
845
846    #[test]
847    fn test_fn_signature_two_args_empty() {
848        check(
849            r#"
850//- minicore: sized, fn
851fn foo(x: u32, y: u32) -> u32 {x + y}
852fn bar() { foo($0); }
853"#,
854            expect![[r#"
855                fn foo(x: u32, y: u32) -> u32
856                       ^^^^^^  ------
857            "#]],
858        );
859    }
860
861    #[test]
862    fn test_fn_signature_two_args_first_generics() {
863        check(
864            r#"
865//- minicore: sized, fn
866fn foo<T, U: Copy + Display>(x: T, y: U) -> u32
867    where T: Copy + Display, U: Debug
868{ x + y }
869
870fn bar() { foo($03, ); }
871"#,
872            expect![[r#"
873                fn foo<T, U>(x: i32, y: U) -> u32
874                             ^^^^^^  ----
875            "#]],
876        );
877    }
878
879    #[test]
880    fn test_fn_signature_no_params() {
881        check(
882            r#"
883//- minicore: sized, fn
884fn foo<T>() -> T where T: Copy + Display {}
885fn bar() { foo($0); }
886"#,
887            expect![[r#"
888                fn foo<T>() -> T
889            "#]],
890        );
891    }
892
893    #[test]
894    fn test_fn_signature_for_impl() {
895        check(
896            r#"
897//- minicore: sized, fn
898struct F;
899impl F { pub fn new() { } }
900fn bar() {
901    let _ : F = F::new($0);
902}
903"#,
904            expect![[r#"
905                fn new()
906            "#]],
907        );
908    }
909
910    #[test]
911    fn test_fn_signature_for_method_self() {
912        check(
913            r#"
914//- minicore: sized, fn
915struct S;
916impl S { pub fn do_it(&self) {} }
917
918fn bar() {
919    let s: S = S;
920    s.do_it($0);
921}
922"#,
923            expect![[r#"
924                fn do_it(&self)
925            "#]],
926        );
927    }
928
929    #[test]
930    fn test_fn_signature_for_method_with_arg() {
931        check(
932            r#"
933//- minicore: sized, fn
934struct S;
935impl S {
936    fn foo(&self, x: i32) {}
937}
938
939fn main() { S.foo($0); }
940"#,
941            expect![[r#"
942                fn foo(&self, x: i32)
943                              ^^^^^^
944            "#]],
945        );
946    }
947
948    #[test]
949    fn test_fn_signature_for_generic_method() {
950        check(
951            r#"
952//- minicore: sized, fn
953struct S<T>(T);
954impl<T> S<T> {
955    fn foo(&self, x: T) {}
956}
957
958fn main() { S(1u32).foo($0); }
959"#,
960            expect![[r#"
961                fn foo(&self, x: u32)
962                              ^^^^^^
963            "#]],
964        );
965    }
966
967    #[test]
968    fn test_fn_signature_for_method_with_arg_as_assoc_fn() {
969        check(
970            r#"
971//- minicore: sized, fn
972struct S;
973impl S {
974    fn foo(&self, x: i32) {}
975}
976
977fn main() { S::foo($0); }
978"#,
979            expect![[r#"
980                fn foo(self: &S, x: i32)
981                       ^^^^^^^^  ------
982            "#]],
983        );
984    }
985
986    #[test]
987    fn test_fn_signature_with_docs_simple() {
988        check(
989            r#"
990//- minicore: sized, fn
991/// test
992// non-doc-comment
993fn foo(j: u32) -> u32 {
994    j
995}
996
997fn bar() {
998    let _ = foo($0);
999}
1000"#,
1001            expect![[r#"
1002                test
1003                ------
1004                fn foo(j: u32) -> u32
1005                       ^^^^^^
1006            "#]],
1007        );
1008    }
1009
1010    #[test]
1011    fn test_fn_signature_with_docs() {
1012        check(
1013            r#"
1014//- minicore: sized, fn
1015/// Adds one to the number given.
1016///
1017/// # Examples
1018///
1019/// ```
1020/// let five = 5;
1021///
1022/// assert_eq!(6, my_crate::add_one(5));
1023/// ```
1024pub fn add_one(x: i32) -> i32 {
1025    x + 1
1026}
1027
1028pub fn r#do() {
1029    add_one($0
1030}"#,
1031            expect![[r##"
1032                Adds one to the number given.
1033
1034                # Examples
1035
1036                ```
1037                let five = 5;
1038
1039                assert_eq!(6, my_crate::add_one(5));
1040                ```
1041                ------
1042                fn add_one(x: i32) -> i32
1043                           ^^^^^^
1044            "##]],
1045        );
1046    }
1047
1048    #[test]
1049    fn test_fn_signature_with_docs_impl() {
1050        check(
1051            r#"
1052//- minicore: sized, fn
1053struct addr;
1054impl addr {
1055    /// Adds one to the number given.
1056    ///
1057    /// # Examples
1058    ///
1059    /// ```
1060    /// let five = 5;
1061    ///
1062    /// assert_eq!(6, my_crate::add_one(5));
1063    /// ```
1064    pub fn add_one(x: i32) -> i32 {
1065        x + 1
1066    }
1067}
1068
1069pub fn do_it() {
1070    addr {};
1071    addr::add_one($0);
1072}
1073"#,
1074            expect![[r##"
1075                Adds one to the number given.
1076
1077                # Examples
1078
1079                ```
1080                let five = 5;
1081
1082                assert_eq!(6, my_crate::add_one(5));
1083                ```
1084                ------
1085                fn add_one(x: i32) -> i32
1086                           ^^^^^^
1087            "##]],
1088        );
1089    }
1090
1091    #[test]
1092    fn test_fn_signature_with_docs_from_actix() {
1093        check(
1094            r#"
1095//- minicore: sized, fn
1096trait Actor {
1097    /// Actor execution context type
1098    type Context;
1099}
1100trait WriteHandler<E>
1101where
1102    Self: Actor
1103{
1104    /// Method is called when writer finishes.
1105    ///
1106    /// By default this method stops actor's `Context`.
1107    fn finished(&mut self, ctx: &mut Self::Context) {}
1108}
1109
1110fn foo(mut r: impl WriteHandler<()>) {
1111    r.finished($0);
1112}
1113"#,
1114            expect![[r#"
1115                Method is called when writer finishes.
1116
1117                By default this method stops actor's `Context`.
1118                ------
1119                fn finished(&mut self, ctx: &mut <impl WriteHandler<()> as Actor>::Context)
1120                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1121            "#]],
1122        );
1123    }
1124
1125    #[test]
1126    fn call_info_bad_offset() {
1127        check(
1128            r#"
1129//- minicore: sized, fn
1130fn foo(x: u32, y: u32) -> u32 {x + y}
1131fn bar() { foo $0 (3, ); }
1132"#,
1133            expect![[""]],
1134        );
1135    }
1136
1137    #[test]
1138    fn outside_of_arg_list() {
1139        check(
1140            r#"
1141//- minicore: sized, fn
1142fn foo(a: u8) {}
1143fn f() {
1144    foo(123)$0
1145}
1146"#,
1147            expect![[]],
1148        );
1149        check(
1150            r#"
1151//- minicore: sized, fn
1152fn foo<T>(a: u8) {}
1153fn f() {
1154    foo::<u32>$0()
1155}
1156"#,
1157            expect![[]],
1158        );
1159        check(
1160            r#"
1161//- minicore: sized, fn
1162fn foo(a: u8) -> u8 {a}
1163fn bar(a: u8) -> u8 {a}
1164fn f() {
1165    foo(bar(123)$0)
1166}
1167"#,
1168            expect![[r#"
1169                fn foo(a: u8) -> u8
1170                       ^^^^^
1171            "#]],
1172        );
1173        check(
1174            r#"
1175//- minicore: sized, fn
1176struct Vec<T>(T);
1177struct Vec2<T>(T);
1178fn f() {
1179    let _: Vec2<Vec<u8>$0>
1180}
1181"#,
1182            expect![[r#"
1183                struct Vec2<T>
1184                            ^
1185            "#]],
1186        );
1187    }
1188
1189    #[test]
1190    fn test_nested_method_in_lambda() {
1191        check(
1192            r#"
1193//- minicore: sized, fn
1194struct Foo;
1195impl Foo { fn bar(&self, _: u32) { } }
1196
1197fn bar(_: u32) { }
1198
1199fn main() {
1200    let foo = Foo;
1201    std::thread::spawn(move || foo.bar($0));
1202}
1203"#,
1204            expect![[r#"
1205                fn bar(&self, _: u32)
1206                              ^^^^^^
1207            "#]],
1208        );
1209    }
1210
1211    #[test]
1212    fn works_for_tuple_structs() {
1213        check(
1214            r#"
1215//- minicore: sized, fn
1216/// A cool tuple struct
1217struct S(u32, i32);
1218fn main() {
1219    let s = S(0, $0);
1220}
1221"#,
1222            expect![[r#"
1223                A cool tuple struct
1224                ------
1225                struct S(u32, i32)
1226                         ---  ^^^
1227            "#]],
1228        );
1229    }
1230
1231    #[test]
1232    fn tuple_struct_pat() {
1233        check(
1234            r#"
1235//- minicore: sized, fn
1236/// A cool tuple struct
1237struct S(u32, i32);
1238fn main() {
1239    let S(0, $0);
1240}
1241"#,
1242            expect![[r#"
1243                A cool tuple struct
1244                ------
1245                struct S (u32, i32)
1246                          ---  ^^^
1247            "#]],
1248        );
1249    }
1250
1251    #[test]
1252    fn tuple_struct_pat_rest() {
1253        check(
1254            r#"
1255//- minicore: sized, fn
1256/// A cool tuple struct
1257struct S(u32, i32, f32, u16);
1258fn main() {
1259    let S(0, .., $0);
1260}
1261"#,
1262            expect![[r#"
1263                A cool tuple struct
1264                ------
1265                struct S (u32, i32, f32, u16)
1266                          ---  ---  ---  ^^^
1267            "#]],
1268        );
1269        check(
1270            r#"
1271//- minicore: sized, fn
1272/// A cool tuple struct
1273struct S(u32, i32, f32, u16, u8);
1274fn main() {
1275    let S(0, .., $0, 0);
1276}
1277"#,
1278            expect![[r#"
1279                A cool tuple struct
1280                ------
1281                struct S (u32, i32, f32, u16, u8)
1282                          ---  ---  ---  ^^^  --
1283            "#]],
1284        );
1285        check(
1286            r#"
1287//- minicore: sized, fn
1288/// A cool tuple struct
1289struct S(u32, i32, f32, u16);
1290fn main() {
1291    let S($0, .., 1);
1292}
1293"#,
1294            expect![[r#"
1295                A cool tuple struct
1296                ------
1297                struct S (u32, i32, f32, u16)
1298                          ^^^  ---  ---  ---
1299            "#]],
1300        );
1301        check(
1302            r#"
1303//- minicore: sized, fn
1304/// A cool tuple struct
1305struct S(u32, i32, f32, u16, u8);
1306fn main() {
1307    let S(1, .., 1, $0, 2);
1308}
1309"#,
1310            expect![[r#"
1311                A cool tuple struct
1312                ------
1313                struct S (u32, i32, f32, u16, u8)
1314                          ---  ---  ---  ^^^  --
1315            "#]],
1316        );
1317        check(
1318            r#"
1319//- minicore: sized, fn
1320/// A cool tuple struct
1321struct S(u32, i32, f32, u16);
1322fn main() {
1323    let S(1, $0.., 1);
1324}
1325"#,
1326            expect![[r#"
1327                A cool tuple struct
1328                ------
1329                struct S (u32, i32, f32, u16)
1330                          ---  ^^^  ---  ---
1331            "#]],
1332        );
1333        check(
1334            r#"
1335//- minicore: sized, fn
1336/// A cool tuple struct
1337struct S(u32, i32, f32, u16);
1338fn main() {
1339    let S(1, ..$0, 1);
1340}
1341"#,
1342            expect![[r#"
1343                A cool tuple struct
1344                ------
1345                struct S (u32, i32, f32, u16)
1346                          ---  ^^^  ---  ---
1347            "#]],
1348        );
1349    }
1350
1351    #[test]
1352    fn generic_struct() {
1353        check(
1354            r#"
1355//- minicore: sized, fn
1356struct S<T>(T);
1357fn main() {
1358    let s = S($0);
1359}
1360"#,
1361            expect![[r#"
1362                struct S<T>({unknown})
1363                            ^^^^^^^^^
1364            "#]],
1365        );
1366    }
1367
1368    #[test]
1369    fn works_for_enum_variants() {
1370        check(
1371            r#"
1372//- minicore: sized, fn
1373enum E {
1374    /// A Variant
1375    A(i32),
1376    /// Another
1377    B,
1378    /// And C
1379    C { a: i32, b: i32 }
1380}
1381
1382fn main() {
1383    let a = E::A($0);
1384}
1385"#,
1386            expect![[r#"
1387                A Variant
1388                ------
1389                enum E::A(i32)
1390                          ^^^
1391            "#]],
1392        );
1393    }
1394
1395    #[test]
1396    fn cant_call_struct_record() {
1397        check(
1398            r#"
1399//- minicore: sized, fn
1400struct S { x: u32, y: i32 }
1401fn main() {
1402    let s = S($0);
1403}
1404"#,
1405            expect![[""]],
1406        );
1407    }
1408
1409    #[test]
1410    fn cant_call_enum_record() {
1411        check(
1412            r#"
1413//- minicore: sized, fn
1414enum E {
1415    /// A Variant
1416    A(i32),
1417    /// Another
1418    B,
1419    /// And C
1420    C { a: i32, b: i32 }
1421}
1422
1423fn main() {
1424    let a = E::C($0);
1425}
1426"#,
1427            expect![[""]],
1428        );
1429    }
1430
1431    #[test]
1432    fn fn_signature_for_call_in_macro() {
1433        check(
1434            r#"
1435//- minicore: sized, fn
1436macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
1437fn foo() { }
1438id! {
1439    fn bar() { foo($0); }
1440}
1441"#,
1442            expect![[r#"
1443                fn foo()
1444            "#]],
1445        );
1446    }
1447
1448    #[test]
1449    fn fn_signature_for_method_call_defined_in_macro() {
1450        check(
1451            r#"
1452//- minicore: sized, fn
1453macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
1454struct S;
1455id! {
1456    impl S {
1457        fn foo<'a>(&'a mut self) {}
1458    }
1459}
1460fn test() { S.foo($0); }
1461"#,
1462            expect![[r#"
1463                fn foo<'a>(&'a mut self)
1464            "#]],
1465        );
1466    }
1467
1468    #[test]
1469    fn call_info_for_lambdas() {
1470        check(
1471            r#"
1472//- minicore: sized, fn
1473struct S;
1474fn foo(s: S) -> i32 { 92 }
1475fn main() {
1476    let _move = S;
1477    (|s| {{_move}; foo(s)})($0)
1478}
1479        "#,
1480            expect![[r#"
1481                impl FnOnce(s: S) -> i32
1482                            ^^^^
1483            "#]],
1484        );
1485        check(
1486            r#"
1487//- minicore: sized, fn
1488struct S;
1489fn foo(s: S) -> i32 { 92 }
1490fn main() {
1491    (|s| foo(s))($0)
1492}
1493        "#,
1494            expect![[r#"
1495                impl Fn(s: S) -> i32
1496                        ^^^^
1497            "#]],
1498        );
1499        check(
1500            r#"
1501//- minicore: sized, fn
1502struct S;
1503fn foo(s: S) -> i32 { 92 }
1504fn main() {
1505    let mut mutate = 0;
1506    (|s| { mutate = 1; foo(s) })($0)
1507}
1508        "#,
1509            expect![[r#"
1510                impl FnMut(s: S) -> i32
1511                           ^^^^
1512            "#]],
1513        );
1514    }
1515
1516    #[test]
1517    fn call_info_for_fn_def_over_reference() {
1518        check(
1519            r#"
1520//- minicore: sized, fn
1521struct S;
1522fn foo(s: S) -> i32 { 92 }
1523fn main() {
1524    let bar = &&&&&foo;
1525    bar($0);
1526}
1527        "#,
1528            expect![[r#"
1529                fn foo(s: S) -> i32
1530                       ^^^^
1531            "#]],
1532        )
1533    }
1534
1535    #[test]
1536    fn call_info_for_fn_ptr() {
1537        check(
1538            r#"
1539//- minicore: sized, fn
1540fn main(f: fn(i32, f64) -> char) {
1541    f(0, $0)
1542}
1543        "#,
1544            expect![[r#"
1545                fn(i32, f64) -> char
1546                   ---  ^^^
1547            "#]],
1548        )
1549    }
1550
1551    #[test]
1552    fn call_info_for_fn_impl() {
1553        check(
1554            r#"
1555//- minicore: sized, fn
1556struct S;
1557impl core::ops::FnOnce<(i32, f64)> for S {
1558    type Output = char;
1559}
1560impl core::ops::FnMut<(i32, f64)> for S {}
1561impl core::ops::Fn<(i32, f64)> for S {}
1562fn main() {
1563    S($0);
1564}
1565        "#,
1566            expect![[r#"
1567                <S as Fn>::call(i32, f64) -> char
1568                                ^^^  ---
1569            "#]],
1570        );
1571        check(
1572            r#"
1573//- minicore: sized, fn
1574struct S;
1575impl core::ops::FnOnce<(i32, f64)> for S {
1576    type Output = char;
1577}
1578impl core::ops::FnMut<(i32, f64)> for S {}
1579impl core::ops::Fn<(i32, f64)> for S {}
1580fn main() {
1581    S(1, $0);
1582}
1583        "#,
1584            expect![[r#"
1585                <S as Fn>::call(i32, f64) -> char
1586                                ---  ^^^
1587            "#]],
1588        );
1589        check(
1590            r#"
1591//- minicore: sized, fn
1592struct S;
1593impl core::ops::FnOnce<(i32, f64)> for S {
1594    type Output = char;
1595}
1596impl core::ops::FnOnce<(char, char)> for S {
1597    type Output = f64;
1598}
1599fn main() {
1600    S($0);
1601}
1602        "#,
1603            expect![""],
1604        );
1605        check(
1606            r#"
1607//- minicore: sized, fn
1608struct S;
1609impl core::ops::FnOnce<(i32, f64)> for S {
1610    type Output = char;
1611}
1612impl core::ops::FnOnce<(char, char)> for S {
1613    type Output = f64;
1614}
1615fn main() {
1616    // FIXME: The ide layer loses the calling info here so we get an ambiguous trait solve result
1617    S(0i32, $0);
1618}
1619        "#,
1620            expect![""],
1621        );
1622    }
1623
1624    #[test]
1625    fn call_info_for_unclosed_call() {
1626        check(
1627            r#"
1628//- minicore: sized, fn
1629fn foo(foo: u32, bar: u32) {}
1630fn main() {
1631    foo($0
1632}"#,
1633            expect![[r#"
1634                fn foo(foo: u32, bar: u32)
1635                       ^^^^^^^^  --------
1636            "#]],
1637        );
1638        // check with surrounding space
1639        check(
1640            r#"
1641//- minicore: sized, fn
1642fn foo(foo: u32, bar: u32) {}
1643fn main() {
1644    foo( $0
1645}"#,
1646            expect![[r#"
1647                fn foo(foo: u32, bar: u32)
1648                       ^^^^^^^^  --------
1649            "#]],
1650        )
1651    }
1652
1653    #[test]
1654    fn test_multiline_argument() {
1655        check(
1656            r#"
1657//- minicore: sized, fn
1658fn callee(a: u8, b: u8) {}
1659fn main() {
1660    callee(match 0 {
1661        0 => 1,$0
1662    })
1663}"#,
1664            expect![[r#""#]],
1665        );
1666        check(
1667            r#"
1668//- minicore: sized, fn
1669fn callee(a: u8, b: u8) {}
1670fn main() {
1671    callee(match 0 {
1672        0 => 1,
1673    },$0)
1674}"#,
1675            expect![[r#"
1676                fn callee(a: u8, b: u8)
1677                          -----  ^^^^^
1678            "#]],
1679        );
1680        check(
1681            r#"
1682//- minicore: sized, fn
1683fn callee(a: u8, b: u8) {}
1684fn main() {
1685    callee($0match 0 {
1686        0 => 1,
1687    })
1688}"#,
1689            expect![[r#"
1690                fn callee(a: u8, b: u8)
1691                          ^^^^^  -----
1692            "#]],
1693        );
1694    }
1695
1696    #[test]
1697    fn test_generics_simple() {
1698        check(
1699            r#"
1700//- minicore: sized, fn
1701/// Option docs.
1702enum Option<T> {
1703    Some(T),
1704    None,
1705}
1706
1707fn f() {
1708    let opt: Option<$0
1709}
1710        "#,
1711            expect![[r#"
1712                Option docs.
1713                ------
1714                enum Option<T>
1715                            ^
1716            "#]],
1717        );
1718    }
1719
1720    #[test]
1721    fn test_generics_on_variant() {
1722        check(
1723            r#"
1724//- minicore: sized, fn
1725/// Option docs.
1726enum Option<T> {
1727    /// Some docs.
1728    Some(T),
1729    /// None docs.
1730    None,
1731}
1732
1733use Option::*;
1734
1735fn f() {
1736    None::<$0
1737}
1738        "#,
1739            expect![[r#"
1740                None docs.
1741                ------
1742                enum Option<T>
1743                            ^
1744            "#]],
1745        );
1746    }
1747
1748    #[test]
1749    fn test_lots_of_generics() {
1750        check(
1751            r#"
1752//- minicore: sized, fn
1753trait Tr<T> {}
1754
1755struct S<T>(T);
1756
1757impl<T> S<T> {
1758    fn f<G, H>(g: G, h: impl Tr<G>) where G: Tr<()> {}
1759}
1760
1761fn f() {
1762    S::<u8>::f::<(), $0
1763}
1764        "#,
1765            expect![[r#"
1766                fn f<G: Tr<()>, H>
1767                     ---------  ^
1768            "#]],
1769        );
1770    }
1771
1772    #[test]
1773    fn test_generics_in_trait_ufcs() {
1774        check(
1775            r#"
1776//- minicore: sized, fn
1777trait Tr {
1778    fn f<T: Tr, U>() {}
1779}
1780
1781struct S;
1782
1783impl Tr for S {}
1784
1785fn f() {
1786    <S as Tr>::f::<$0
1787}
1788        "#,
1789            expect![[r#"
1790                fn f<T: Tr, U>
1791                     ^^^^^  -
1792            "#]],
1793        );
1794    }
1795
1796    #[test]
1797    fn test_generics_in_method_call() {
1798        check(
1799            r#"
1800//- minicore: sized, fn
1801struct S;
1802
1803impl S {
1804    fn f<T>(&self) {}
1805}
1806
1807fn f() {
1808    S.f::<$0
1809}
1810        "#,
1811            expect![[r#"
1812                fn f<T>
1813                     ^
1814            "#]],
1815        );
1816    }
1817
1818    #[test]
1819    fn test_generic_param_in_method_call() {
1820        check(
1821            r#"
1822//- minicore: sized, fn
1823struct Foo;
1824impl Foo {
1825    fn test<V>(&mut self, val: V) {}
1826}
1827fn sup() {
1828    Foo.test($0)
1829}
1830"#,
1831            expect![[r#"
1832                fn test<V>(&mut self, val: V)
1833                                      ^^^^^^
1834            "#]],
1835        );
1836    }
1837
1838    #[test]
1839    fn test_generic_kinds() {
1840        check(
1841            r#"
1842//- minicore: sized, fn
1843fn callee<'a, const A: u8, T, const C: u8>() {}
1844
1845fn f() {
1846    callee::<'static, $0
1847}
1848        "#,
1849            expect![[r#"
1850                fn callee<'a, const A: u8, T, const C: u8>
1851                          --  ^^^^^^^^^^^  -  -----------
1852            "#]],
1853        );
1854        check(
1855            r#"
1856//- minicore: sized, fn
1857fn callee<'a, const A: u8, T, const C: u8>() {}
1858
1859fn f() {
1860    callee::<NON_LIFETIME$0
1861}
1862        "#,
1863            expect![[r#"
1864                fn callee<'a, const A: u8, T, const C: u8>
1865                          --  ^^^^^^^^^^^  -  -----------
1866            "#]],
1867        );
1868    }
1869
1870    #[test]
1871    fn test_trait_assoc_types() {
1872        check(
1873            r#"
1874//- minicore: sized, fn
1875trait Trait<'a, T> {
1876    type Assoc;
1877}
1878fn f() -> impl Trait<(), $0
1879            "#,
1880            expect![[r#"
1881                trait Trait<'a, T, Assoc = …>
1882                            --  -  ^^^^^^^^^
1883            "#]],
1884        );
1885        check(
1886            r#"
1887//- minicore: sized, fn
1888trait Iterator {
1889    type Item;
1890}
1891fn f() -> impl Iterator<$0
1892            "#,
1893            expect![[r#"
1894                trait Iterator<Item = …>
1895                               ^^^^^^^^
1896            "#]],
1897        );
1898        check(
1899            r#"
1900//- minicore: sized, fn
1901trait Iterator {
1902    type Item;
1903}
1904fn f() -> impl Iterator<Item = $0
1905            "#,
1906            expect![[r#"
1907                trait Iterator<Item = …>
1908                               ^^^^^^^^
1909            "#]],
1910        );
1911        check(
1912            r#"
1913//- minicore: sized, fn
1914trait Tr {
1915    type A;
1916    type B;
1917}
1918fn f() -> impl Tr<$0
1919            "#,
1920            expect![[r#"
1921                trait Tr<A = …, B = …>
1922                         ^^^^^  -----
1923            "#]],
1924        );
1925        check(
1926            r#"
1927//- minicore: sized, fn
1928trait Tr {
1929    type A;
1930    type B;
1931}
1932fn f() -> impl Tr<B$0
1933            "#,
1934            expect![[r#"
1935                trait Tr<A = …, B = …>
1936                         ^^^^^  -----
1937            "#]],
1938        );
1939        check(
1940            r#"
1941//- minicore: sized, fn
1942trait Tr {
1943    type A;
1944    type B;
1945}
1946fn f() -> impl Tr<B = $0
1947            "#,
1948            expect![[r#"
1949                trait Tr<B = …, A = …>
1950                         ^^^^^  -----
1951            "#]],
1952        );
1953        check(
1954            r#"
1955//- minicore: sized, fn
1956trait Tr {
1957    type A;
1958    type B;
1959}
1960fn f() -> impl Tr<B = (), $0
1961            "#,
1962            expect![[r#"
1963                trait Tr<B = …, A = …>
1964                         -----  ^^^^^
1965            "#]],
1966        );
1967    }
1968
1969    #[test]
1970    fn test_supertrait_assoc() {
1971        check(
1972            r#"
1973//- minicore: sized, fn
1974trait Super {
1975    type SuperTy;
1976}
1977trait Sub: Super + Super {
1978    type SubTy;
1979}
1980fn f() -> impl Sub<$0
1981            "#,
1982            expect![[r#"
1983                trait Sub<SubTy = …, SuperTy = …>
1984                          ^^^^^^^^^  -----------
1985            "#]],
1986        );
1987    }
1988
1989    #[test]
1990    fn no_assoc_types_outside_type_bounds() {
1991        check(
1992            r#"
1993//- minicore: sized, fn
1994trait Tr<T> {
1995    type Assoc;
1996}
1997
1998impl Tr<$0
1999        "#,
2000            expect![[r#"
2001            trait Tr<T>
2002                     ^
2003        "#]],
2004        );
2005    }
2006
2007    #[test]
2008    fn impl_trait() {
2009        // FIXME: Substitute type vars in impl trait (`U` -> `i8`)
2010        check(
2011            r#"
2012//- minicore: sized, fn
2013trait Trait<T> {}
2014struct Wrap<T>(T);
2015fn foo<U>(x: Wrap<impl Trait<U>>) {}
2016fn f() {
2017    foo::<i8>($0)
2018}
2019"#,
2020            expect![[r#"
2021                fn foo<U>(x: Wrap<impl Trait<U>>)
2022                          ^^^^^^^^^^^^^^^^^^^^^^
2023            "#]],
2024        );
2025    }
2026
2027    #[test]
2028    fn fully_qualified_syntax() {
2029        check(
2030            r#"
2031//- minicore: sized, fn
2032fn f() {
2033    trait A { fn foo(&self, other: Self); }
2034    A::foo(&self$0, other);
2035}
2036"#,
2037            expect![[r#"
2038                fn foo(self: &Self, other: Self)
2039                       ^^^^^^^^^^^  -----------
2040            "#]],
2041        );
2042    }
2043
2044    #[test]
2045    fn help_for_generic_call() {
2046        check(
2047            r#"
2048//- minicore: sized, fn
2049fn f<F: FnOnce(u8, u16) -> i32>(f: F) {
2050    f($0)
2051}
2052"#,
2053            expect![[r#"
2054                impl FnOnce(u8, u16) -> i32
2055                            ^^  ---
2056            "#]],
2057        );
2058        check(
2059            r#"
2060//- minicore: sized, fn
2061fn f<T, F: FnMut(&T, u16) -> &T>(f: F) {
2062    f($0)
2063}
2064"#,
2065            expect![[r#"
2066                impl FnMut(&T, u16) -> &T
2067                           ^^  ---
2068            "#]],
2069        );
2070    }
2071
2072    #[test]
2073    fn regression_13579() {
2074        // FIXME(next-solver): There should be signature help available here.
2075        // The reason it is not is because of a trait solver bug. Since `Error` is not provided
2076        // nor it can be inferred, it becomes an error type. The bug is that the solver ignores
2077        // predicates on error types, and they do not guide infer vars, not allowing us to infer
2078        // that `take`'s return type is callable.
2079        // https://github.com/rust-lang/rust/pull/146602 should fix the solver bug.
2080        check(
2081            r#"
2082//- minicore: sized, fn
2083fn f() {
2084    take(2)($0);
2085}
2086
2087fn take<C, Error>(
2088    count: C
2089) -> impl Fn() -> C  {
2090    move || count
2091}
2092"#,
2093            expect![""],
2094        );
2095    }
2096
2097    #[test]
2098    fn record_literal() {
2099        check(
2100            r#"
2101//- minicore: sized, fn
2102struct Strukt<T, U = ()> {
2103    t: T,
2104    u: U,
2105    unit: (),
2106}
2107fn f() {
2108    Strukt {
2109        u: 0,
2110        $0
2111    }
2112}
2113"#,
2114            expect![[r#"
2115                struct Strukt { u: i32, t: T, unit: () }
2116                                ------  ^^^^  --------
2117            "#]],
2118        );
2119    }
2120
2121    #[test]
2122    fn record_literal_nonexistent_field() {
2123        check(
2124            r#"
2125//- minicore: sized, fn
2126struct Strukt {
2127    a: u8,
2128}
2129fn f() {
2130    Strukt {
2131        b: 8,
2132        $0
2133    }
2134}
2135"#,
2136            expect![[r#"
2137                struct Strukt { a: u8 }
2138                                -----
2139            "#]],
2140        );
2141    }
2142
2143    #[test]
2144    fn tuple_variant_record_literal() {
2145        check(
2146            r#"
2147//- minicore: sized, fn
2148enum Opt {
2149    Some(u8),
2150}
2151fn f() {
2152    Opt::Some {$0}
2153}
2154"#,
2155            expect![[r#"
2156                enum Opt::Some { 0: u8 }
2157                                 ^^^^^
2158            "#]],
2159        );
2160        check(
2161            r#"
2162//- minicore: sized, fn
2163enum Opt {
2164    Some(u8),
2165}
2166fn f() {
2167    Opt::Some {0:0,$0}
2168}
2169"#,
2170            expect![[r#"
2171                enum Opt::Some { 0: u8 }
2172                                 -----
2173            "#]],
2174        );
2175    }
2176
2177    #[test]
2178    fn record_literal_self() {
2179        check(
2180            r#"
2181//- minicore: sized, fn
2182struct S { t: u8 }
2183impl S {
2184    fn new() -> Self {
2185        Self { $0 }
2186    }
2187}
2188        "#,
2189            expect![[r#"
2190                struct S { t: u8 }
2191                           ^^^^^
2192            "#]],
2193        );
2194    }
2195
2196    #[test]
2197    fn record_pat() {
2198        check(
2199            r#"
2200//- minicore: sized, fn
2201struct Strukt<T, U = ()> {
2202    t: T,
2203    u: U,
2204    unit: (),
2205}
2206fn f() {
2207    let Strukt {
2208        u: 0,
2209        $0
2210    }
2211}
2212"#,
2213            expect![[r#"
2214                struct Strukt { u: i32, t: T, unit: () }
2215                                ------  ^^^^  --------
2216            "#]],
2217        );
2218    }
2219
2220    #[test]
2221    fn test_enum_in_nested_method_in_lambda() {
2222        check(
2223            r#"
2224//- minicore: sized, fn
2225enum A {
2226    A,
2227    B
2228}
2229
2230fn bar(_: A) { }
2231
2232fn main() {
2233    let foo = Foo;
2234    std::thread::spawn(move || { bar(A:$0) } );
2235}
2236"#,
2237            expect![[r#"
2238                fn bar(_: A)
2239                       ^^^^
2240            "#]],
2241        );
2242    }
2243
2244    #[test]
2245    fn test_tuple_expr_free() {
2246        check(
2247            r#"
2248//- minicore: sized, fn
2249fn main() {
2250    (0$0, 1, 3);
2251}
2252"#,
2253            expect![[r#"
2254                (i32, i32, i32)
2255                 ^^^  ---  ---
2256            "#]],
2257        );
2258        check(
2259            r#"
2260//- minicore: sized, fn
2261fn main() {
2262    ($0 1, 3);
2263}
2264"#,
2265            expect![[r#"
2266                (i32, i32)
2267                 ^^^  ---
2268            "#]],
2269        );
2270        check(
2271            r#"
2272//- minicore: sized, fn
2273fn main() {
2274    (1, 3 $0);
2275}
2276"#,
2277            expect![[r#"
2278                (i32, i32)
2279                 ---  ^^^
2280            "#]],
2281        );
2282        check(
2283            r#"
2284//- minicore: sized, fn
2285fn main() {
2286    (1, 3 $0,);
2287}
2288"#,
2289            expect![[r#"
2290                (i32, i32)
2291                 ---  ^^^
2292            "#]],
2293        );
2294    }
2295
2296    #[test]
2297    fn test_tuple_expr_expected() {
2298        check(
2299            r#"
2300//- minicore: sized, fn
2301fn main() {
2302    let _: (&str, u32, u32)= ($0, 1, 3);
2303}
2304"#,
2305            expect![[r#"
2306                (&str, u32, u32)
2307                 ^^^^  ---  ---
2308            "#]],
2309        );
2310        // FIXME: Should typeck report a 4-ary tuple for the expression here?
2311        check(
2312            r#"
2313//- minicore: sized, fn
2314fn main() {
2315    let _: (&str, u32, u32, u32) = ($0, 1, 3);
2316}
2317"#,
2318            expect![[r#"
2319                (&str, u32, u32)
2320                 ^^^^  ---  ---
2321            "#]],
2322        );
2323        check(
2324            r#"
2325//- minicore: sized, fn
2326fn main() {
2327    let _: (&str, u32, u32)= ($0, 1, 3, 5);
2328}
2329"#,
2330            expect![[r#"
2331                (&str, u32, u32, i32)
2332                 ^^^^  ---  ---  ---
2333            "#]],
2334        );
2335    }
2336
2337    #[test]
2338    fn test_tuple_pat_free() {
2339        check(
2340            r#"
2341//- minicore: sized, fn
2342fn main() {
2343    let ($0, 1, 3);
2344}
2345"#,
2346            expect![[r#"
2347                ({unknown}, i32, i32)
2348                 ^^^^^^^^^  ---  ---
2349            "#]],
2350        );
2351        check(
2352            r#"
2353//- minicore: sized, fn
2354fn main() {
2355    let (0$0, 1, 3);
2356}
2357"#,
2358            expect![[r#"
2359                (i32, i32, i32)
2360                 ^^^  ---  ---
2361            "#]],
2362        );
2363        check(
2364            r#"
2365//- minicore: sized, fn
2366fn main() {
2367    let ($0 1, 3);
2368}
2369"#,
2370            expect![[r#"
2371                (i32, i32)
2372                 ^^^  ---
2373            "#]],
2374        );
2375        check(
2376            r#"
2377//- minicore: sized, fn
2378fn main() {
2379    let (1, 3 $0);
2380}
2381"#,
2382            expect![[r#"
2383                (i32, i32)
2384                 ---  ^^^
2385            "#]],
2386        );
2387        check(
2388            r#"
2389//- minicore: sized, fn
2390fn main() {
2391    let (1, 3 $0,);
2392}
2393"#,
2394            expect![[r#"
2395                (i32, i32)
2396                 ---  ^^^
2397            "#]],
2398        );
2399        check(
2400            r#"
2401//- minicore: sized, fn
2402fn main() {
2403    let (1, 3 $0, ..);
2404}
2405"#,
2406            expect![[r#"
2407                (i32, i32)
2408                 ---  ^^^
2409            "#]],
2410        );
2411        check(
2412            r#"
2413//- minicore: sized, fn
2414fn main() {
2415    let (1, 3, .., $0);
2416}
2417"#,
2418            // FIXME: This is wrong, this should not mark the last as active
2419            expect![[r#"
2420                (i32, i32)
2421                 ---  ^^^
2422            "#]],
2423        );
2424    }
2425
2426    #[test]
2427    fn test_tuple_pat_expected() {
2428        check(
2429            r#"
2430//- minicore: sized, fn
2431fn main() {
2432    let (0$0, 1, 3): (i32, i32, i32);
2433}
2434"#,
2435            expect![[r#"
2436                (i32, i32, i32)
2437                 ^^^  ---  ---
2438            "#]],
2439        );
2440        check(
2441            r#"
2442//- minicore: sized, fn
2443fn main() {
2444    let ($0, 1, 3): (i32, i32, i32);
2445}
2446"#,
2447            expect![[r#"
2448                (i32, i32, i32)
2449                 ^^^  ---  ---
2450            "#]],
2451        );
2452        check(
2453            r#"
2454//- minicore: sized, fn
2455fn main() {
2456    let (1, 3 $0): (i32,);
2457}
2458"#,
2459            expect![[r#"
2460                (i32, i32)
2461                 ---  ^^^
2462            "#]],
2463        );
2464        check(
2465            r#"
2466//- minicore: sized, fn
2467fn main() {
2468    let (1, 3 $0, ..): (i32, i32, i32, i32);
2469}
2470"#,
2471            expect![[r#"
2472                (i32, i32, i32, i32)
2473                 ---  ^^^  ---  ---
2474            "#]],
2475        );
2476        check(
2477            r#"
2478//- minicore: sized, fn
2479fn main() {
2480    let (1, 3, .., $0): (i32, i32, i32);
2481}
2482"#,
2483            expect![[r#"
2484                (i32, i32, i32)
2485                 ---  ---  ^^^
2486            "#]],
2487        );
2488    }
2489    #[test]
2490    fn test_tuple_pat_expected_inferred() {
2491        check(
2492            r#"
2493//- minicore: sized, fn
2494fn main() {
2495    let (0$0, 1, 3) = (1, 2 ,3);
2496}
2497"#,
2498            expect![[r#"
2499                (i32, i32, i32)
2500                 ^^^  ---  ---
2501            "#]],
2502        );
2503        check(
2504            r#"
2505//- minicore: sized, fn
2506fn main() {
2507    let ($0 1, 3) = (1, 2, 3);
2508}
2509"#,
2510            // FIXME: Should typeck report a 3-ary tuple for the pattern here?
2511            expect![[r#"
2512                (i32, i32)
2513                 ^^^  ---
2514            "#]],
2515        );
2516        check(
2517            r#"
2518//- minicore: sized, fn
2519fn main() {
2520    let (1, 3 $0) = (1,);
2521}
2522"#,
2523            expect![[r#"
2524                (i32, i32)
2525                 ---  ^^^
2526            "#]],
2527        );
2528        check(
2529            r#"
2530//- minicore: sized, fn
2531fn main() {
2532    let (1, 3 $0, ..) = (1, 2, 3, 4);
2533}
2534"#,
2535            expect![[r#"
2536                (i32, i32, i32, i32)
2537                 ---  ^^^  ---  ---
2538            "#]],
2539        );
2540        check(
2541            r#"
2542//- minicore: sized, fn
2543fn main() {
2544    let (1, 3, .., $0) = (1, 2, 3);
2545}
2546"#,
2547            expect![[r#"
2548                (i32, i32, i32)
2549                 ---  ---  ^^^
2550            "#]],
2551        );
2552    }
2553
2554    #[test]
2555    fn test_tuple_generic_param() {
2556        check(
2557            r#"
2558//- minicore: sized, fn
2559struct S<T>(T);
2560
2561fn main() {
2562    let s: S<$0
2563}
2564            "#,
2565            expect![[r#"
2566                struct S<T>
2567                         ^
2568            "#]],
2569        );
2570    }
2571
2572    #[test]
2573    fn test_enum_generic_param() {
2574        check(
2575            r#"
2576//- minicore: sized, fn
2577enum Option<T> {
2578    Some(T),
2579    None,
2580}
2581
2582fn main() {
2583    let opt: Option<$0
2584}
2585            "#,
2586            expect![[r#"
2587                enum Option<T>
2588                            ^
2589            "#]],
2590        );
2591    }
2592
2593    #[test]
2594    fn test_enum_variant_generic_param() {
2595        check(
2596            r#"
2597//- minicore: sized, fn
2598enum Option<T> {
2599    Some(T),
2600    None,
2601}
2602
2603fn main() {
2604    let opt = Option::Some($0);
2605}
2606            "#,
2607            expect![[r#"
2608                enum Option<T>::Some({unknown})
2609                                     ^^^^^^^^^
2610            "#]],
2611        );
2612    }
2613
2614    #[test]
2615    fn test_generic_arg_with_default() {
2616        check(
2617            r#"
2618//- minicore: sized, fn
2619struct S<T = u8> {
2620    field: T,
2621}
2622
2623fn main() {
2624    let s: S<$0
2625}
2626            "#,
2627            expect![[r#"
2628                struct S<T = u8>
2629                         ^^^^^^
2630            "#]],
2631        );
2632
2633        check(
2634            r#"
2635//- minicore: sized, fn
2636struct S<const C: u8 = 5> {
2637    field: C,
2638}
2639
2640fn main() {
2641    let s: S<$0
2642}
2643            "#,
2644            expect![[r#"
2645                struct S<const C: u8 = 5>
2646                         ^^^^^^^^^^^^^^^
2647            "#]],
2648        );
2649    }
2650
2651    #[test]
2652    fn test_async_function() {
2653        check(
2654            r#"
2655//- minicore: sized, fn, future, result
2656pub async fn conn_mut<F, T>(f: F) -> Result<T, i32>
2657where
2658    F: FnOnce() -> T,
2659{
2660    Ok(f())
2661}
2662
2663fn main() {
2664    conn_mut($0)
2665}
2666            "#,
2667            expect![[r#"
2668                async fn conn_mut<F: FnOnce() -> T, T>(f: F) -> Result<T, i32>
2669                                                       ^^^^
2670            "#]],
2671        );
2672    }
2673
2674    #[test]
2675    fn test_const_function() {
2676        check(
2677            r#"
2678//- minicore: sized, fn
2679pub const fn foo(x: u32, y: u32) -> u32 { x + y }
2680
2681fn main() {
2682    foo($0)
2683}
2684            "#,
2685            expect![[r#"
2686                const fn foo(x: u32, y: u32) -> u32
2687                             ^^^^^^  ------
2688            "#]],
2689        );
2690    }
2691
2692    #[test]
2693    fn test_unsafe_function() {
2694        check(
2695            r#"
2696//- minicore: sized, fn
2697pub unsafe fn foo(x: u32, y: u32) -> u32 { x + y }
2698
2699fn main() {
2700    unsafe { foo($0) }
2701}
2702            "#,
2703            expect![[r#"
2704                unsafe fn foo(x: u32, y: u32) -> u32
2705                              ^^^^^^  ------
2706            "#]],
2707        );
2708    }
2709
2710    #[test]
2711    fn test_const_unsafe_function() {
2712        check(
2713            r#"
2714//- minicore: sized, fn
2715pub const unsafe fn foo(x: u32, y: u32) -> u32 { x + y }
2716
2717fn main() {
2718    unsafe { foo($0) }
2719}
2720            "#,
2721            expect![[r#"
2722                const unsafe fn foo(x: u32, y: u32) -> u32
2723                                    ^^^^^^  ------
2724            "#]],
2725        );
2726    }
2727
2728    #[test]
2729    fn test_async_unsafe_function() {
2730        check(
2731            r#"
2732//- minicore: sized, fn, future
2733pub async unsafe fn foo(x: u32, y: u32) -> u32 { x + y }
2734
2735fn main() {
2736    unsafe { foo($0) }
2737}
2738            "#,
2739            expect![[r#"
2740                async unsafe fn foo(x: u32, y: u32) -> u32
2741                                    ^^^^^^  ------
2742            "#]],
2743        );
2744    }
2745}