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