1
1
use crate :: database:: DatabaseExt ;
2
2
use crate :: query:: QueryMacroInput ;
3
3
use either:: Either ;
4
- use proc_macro2:: TokenStream ;
5
- use quote:: { format_ident, quote, quote_spanned} ;
4
+ use proc_macro2:: { Ident , TokenStream } ;
5
+ use quote:: { format_ident, quote, quote_spanned, ToTokens } ;
6
6
use sqlx_core:: describe:: Describe ;
7
7
use syn:: spanned:: Spanned ;
8
8
use syn:: { Expr , ExprCast , ExprGroup , ExprType , Type } ;
@@ -32,6 +32,8 @@ pub fn quote_args<DB: DatabaseExt>(
32
32
#( let #arg_name = & ( #arg_expr) ; ) *
33
33
} ;
34
34
35
+ let mut args_warnings: Vec < TokenStream > = vec ! [ ] ;
36
+
35
37
let args_check = match info. parameters ( ) {
36
38
None | Some ( Either :: Right ( _) ) => {
37
39
// all we can do is check arity which we did
@@ -52,7 +54,12 @@ pub fn quote_args<DB: DatabaseExt>(
52
54
let param_ty = match get_type_override ( expr) {
53
55
// cast or type ascription will fail to compile if the type does not match
54
56
// and we strip casts to wildcard
55
- Some ( _) => return Ok ( quote ! ( ) ) ,
57
+ Some ( ( _, false ) ) => return Ok ( quote ! ( ) ) ,
58
+ Some ( ( ty, true ) ) => {
59
+ let warning = create_warning ( name. clone ( ) , ty. clone ( ) , expr. clone ( ) ) ;
60
+ args_warnings. push ( warning) ;
61
+ return Ok ( quote ! ( ) )
62
+ } ,
56
63
None => {
57
64
DB :: param_type_for_id ( & param_ty)
58
65
. ok_or_else ( || {
@@ -101,6 +108,8 @@ pub fn quote_args<DB: DatabaseExt>(
101
108
let args_count = input. arg_exprs . len ( ) ;
102
109
103
110
Ok ( quote ! {
111
+ #( #args_warnings) *
112
+
104
113
#arg_bindings
105
114
106
115
#args_check
@@ -114,11 +123,37 @@ pub fn quote_args<DB: DatabaseExt>(
114
123
} )
115
124
}
116
125
117
- fn get_type_override ( expr : & Expr ) -> Option < & Type > {
126
+ fn create_warning ( name : Ident , ty : Type , expr : Expr ) -> TokenStream {
127
+ let span = expr. span ( ) ;
128
+ let stripped = strip_wildcard ( expr) . to_token_stream ( ) ;
129
+ let current = quote ! ( #stripped: #ty) . to_string ( ) ;
130
+ let fix = quote ! ( #stripped as #ty) . to_string ( ) ;
131
+
132
+ let message = format ! (
133
+ "
134
+ \t \t Type ascription pattern is deprecated, prefer casting
135
+ \t \t Try changing from
136
+ \t \t \t `{current}`
137
+ \t \t to
138
+ \t \t \t `{fix}`
139
+
140
+ \t \t See <https://github.com/rust-lang/rfcs/pull/3307> for more information
141
+ "
142
+ ) ;
143
+ let name = Ident :: new ( & format ! ( "warning_{name}" ) , span) ;
144
+ quote_spanned ! ( span =>
145
+ #[ deprecated( note = #message) ]
146
+ #[ allow( non_upper_case_globals) ]
147
+ const #name: ( ) = ( ) ;
148
+ let _ = #name;
149
+ )
150
+ }
151
+
152
+ fn get_type_override ( expr : & Expr ) -> Option < ( & Type , bool ) > {
118
153
match expr {
119
154
Expr :: Group ( group) => get_type_override ( & group. expr ) ,
120
- Expr :: Cast ( cast) => Some ( & cast. ty ) ,
121
- Expr :: Type ( ascription) => Some ( & ascription. ty ) ,
155
+ Expr :: Cast ( cast) => Some ( ( & cast. ty , false ) ) ,
156
+ Expr :: Type ( ascription) => Some ( ( & ascription. ty , true ) ) ,
122
157
_ => None ,
123
158
}
124
159
}
0 commit comments