1+ use either:: Either ;
2+ use hir:: InFile ;
13use syntax:: {
24 ast:: { self , HasArgList } ,
3- AstNode , TextRange ,
5+ AstNode , SyntaxNodePtr , TextRange ,
46} ;
57
68use crate :: { adjusted_display_range, Diagnostic , DiagnosticCode , DiagnosticsContext } ;
79
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+
835// Diagnostic: mismatched-arg-count
936//
1037// 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(
1441) -> Diagnostic {
1542 let s = if d. expected == 1 { "" } else { "s" } ;
1643 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+ )
1849}
1950
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+ }
2584 _ => return None ,
2685 } ;
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) ;
3089 }
31- if let Some ( r_paren) = arg_list . r_paren_token ( ) {
90+ if let Some ( r_paren) = r_paren_token {
3291 return Some ( r_paren. text_range ( ) ) ;
3392 }
3493 }
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) ;
3897 }
39- let zip = arg_list . args ( ) . nth ( d . expected ) . zip ( arg_list . r_paren_token ( ) ) ;
98+ let zip = expected_arg . zip ( r_paren_token) ;
4099 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 ( ) ) ) ;
42101 }
43102 }
44103
@@ -331,4 +390,21 @@ fn g() {
331390 "# ,
332391 )
333392 }
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+ }
334410}
0 commit comments