1use 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#[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
72pub(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 .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 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 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 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 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 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 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 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 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(); 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(
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 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 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 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 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 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}