1
+ use either:: Either ;
2
+ use hir:: InFile ;
1
3
use syntax:: {
2
4
ast:: { self , HasArgList } ,
3
- AstNode , TextRange ,
5
+ AstNode , SyntaxNodePtr , TextRange ,
4
6
} ;
5
7
6
8
use crate :: { adjusted_display_range, Diagnostic , DiagnosticCode , DiagnosticsContext } ;
7
9
10
+ // Diagnostic: mismatched-tuple-struct-pat-arg-count
11
+ //
12
+ // This diagnostic is triggered if a function is invoked with an incorrect amount of arguments.
13
+ pub ( crate ) fn mismatched_tuple_struct_pat_arg_count (
14
+ ctx : & DiagnosticsContext < ' _ > ,
15
+ d : & hir:: MismatchedTupleStructPatArgCount ,
16
+ ) -> Diagnostic {
17
+ let s = if d. found == 1 { "" } else { "s" } ;
18
+ let s2 = if d. expected == 1 { "" } else { "s" } ;
19
+ let message = format ! (
20
+ "this pattern has {} field{s}, but the corresponding tuple struct has {} field{s2}" ,
21
+ d. found, d. expected
22
+ ) ;
23
+ Diagnostic :: new (
24
+ DiagnosticCode :: RustcHardError ( "E0023" ) ,
25
+ message,
26
+ invalid_args_range (
27
+ ctx,
28
+ d. expr_or_pat . clone ( ) . map ( |it| it. either ( Into :: into, Into :: into) ) ,
29
+ d. expected ,
30
+ d. found ,
31
+ ) ,
32
+ )
33
+ }
34
+
8
35
// Diagnostic: mismatched-arg-count
9
36
//
10
37
// This diagnostic is triggered if a function is invoked with an incorrect amount of arguments.
@@ -14,31 +41,63 @@ pub(crate) fn mismatched_arg_count(
14
41
) -> Diagnostic {
15
42
let s = if d. expected == 1 { "" } else { "s" } ;
16
43
let message = format ! ( "expected {} argument{s}, found {}" , d. expected, d. found) ;
17
- Diagnostic :: new ( DiagnosticCode :: RustcHardError ( "E0107" ) , message, invalid_args_range ( ctx, d) )
44
+ Diagnostic :: new (
45
+ DiagnosticCode :: RustcHardError ( "E0107" ) ,
46
+ message,
47
+ invalid_args_range ( ctx, d. call_expr . clone ( ) . map ( Into :: into) , d. expected , d. found ) ,
48
+ )
18
49
}
19
50
20
- fn invalid_args_range ( ctx : & DiagnosticsContext < ' _ > , d : & hir:: MismatchedArgCount ) -> TextRange {
21
- adjusted_display_range :: < ast:: Expr > ( ctx, d. call_expr . clone ( ) . map ( |it| it. into ( ) ) , & |expr| {
22
- let arg_list = match expr {
23
- ast:: Expr :: CallExpr ( call) => call. arg_list ( ) ?,
24
- ast:: Expr :: MethodCallExpr ( call) => call. arg_list ( ) ?,
51
+ fn invalid_args_range (
52
+ ctx : & DiagnosticsContext < ' _ > ,
53
+ source : InFile < SyntaxNodePtr > ,
54
+ expected : usize ,
55
+ found : usize ,
56
+ ) -> TextRange {
57
+ adjusted_display_range :: < Either < ast:: Expr , ast:: TupleStructPat > > ( ctx, source, & |expr| {
58
+ let ( text_range, r_paren_token, expected_arg) = match expr {
59
+ Either :: Left ( ast:: Expr :: CallExpr ( call) ) => {
60
+ let arg_list = call. arg_list ( ) ?;
61
+ (
62
+ arg_list. syntax ( ) . text_range ( ) ,
63
+ arg_list. r_paren_token ( ) ,
64
+ arg_list. args ( ) . nth ( expected) . map ( |it| it. syntax ( ) . text_range ( ) ) ,
65
+ )
66
+ }
67
+ Either :: Left ( ast:: Expr :: MethodCallExpr ( call) ) => {
68
+ let arg_list = call. arg_list ( ) ?;
69
+ (
70
+ arg_list. syntax ( ) . text_range ( ) ,
71
+ arg_list. r_paren_token ( ) ,
72
+ arg_list. args ( ) . nth ( expected) . map ( |it| it. syntax ( ) . text_range ( ) ) ,
73
+ )
74
+ }
75
+ Either :: Right ( pat) => {
76
+ let r_paren = pat. r_paren_token ( ) ?;
77
+ let l_paren = pat. l_paren_token ( ) ?;
78
+ (
79
+ l_paren. text_range ( ) . cover ( r_paren. text_range ( ) ) ,
80
+ Some ( r_paren) ,
81
+ pat. fields ( ) . nth ( expected) . map ( |it| it. syntax ( ) . text_range ( ) ) ,
82
+ )
83
+ }
25
84
_ => return None ,
26
85
} ;
27
- if d . found < d . expected {
28
- if d . found == 0 {
29
- return Some ( arg_list . syntax ( ) . text_range ( ) ) ;
86
+ if found < expected {
87
+ if found == 0 {
88
+ return Some ( text_range) ;
30
89
}
31
- if let Some ( r_paren) = arg_list . r_paren_token ( ) {
90
+ if let Some ( r_paren) = r_paren_token {
32
91
return Some ( r_paren. text_range ( ) ) ;
33
92
}
34
93
}
35
- if d . expected < d . found {
36
- if d . expected == 0 {
37
- return Some ( arg_list . syntax ( ) . text_range ( ) ) ;
94
+ if expected < found {
95
+ if expected == 0 {
96
+ return Some ( text_range) ;
38
97
}
39
- let zip = arg_list . args ( ) . nth ( d . expected ) . zip ( arg_list . r_paren_token ( ) ) ;
98
+ let zip = expected_arg . zip ( r_paren_token) ;
40
99
if let Some ( ( arg, r_paren) ) = zip {
41
- return Some ( arg. syntax ( ) . text_range ( ) . cover ( r_paren. text_range ( ) ) ) ;
100
+ return Some ( arg. cover ( r_paren. text_range ( ) ) ) ;
42
101
}
43
102
}
44
103
@@ -331,4 +390,21 @@ fn g() {
331
390
"# ,
332
391
)
333
392
}
393
+
394
+ #[ test]
395
+ fn tuple_struct_pat ( ) {
396
+ check_diagnostics (
397
+ r#"
398
+ struct S(u32, u32);
399
+ fn f(
400
+ S(a, b, c): S,
401
+ // ^^ error: this pattern has 3 fields, but the corresponding tuple struct has 2 fields
402
+ S(): S,
403
+ // ^^ error: this pattern has 0 fields, but the corresponding tuple struct has 2 fields
404
+ S(e, f, .., g, d): S
405
+ // ^^^^^^^^^ error: this pattern has 4 fields, but the corresponding tuple struct has 2 fields
406
+ ) {}
407
+ "# ,
408
+ )
409
+ }
334
410
}
0 commit comments