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