@@ -9,15 +9,15 @@ use rustc_attr::{
9
9
self as attr, ConstStability , DefaultBodyStability , DeprecatedSince , Deprecation , Stability ,
10
10
} ;
11
11
use rustc_data_structures:: unord:: UnordMap ;
12
- use rustc_errors:: { Applicability , Diag } ;
12
+ use rustc_errors:: { Applicability , Diag , EmissionGuarantee } ;
13
13
use rustc_feature:: GateIssue ;
14
14
use rustc_hir:: def:: DefKind ;
15
15
use rustc_hir:: def_id:: { DefId , LocalDefId , LocalDefIdMap } ;
16
16
use rustc_hir:: { self as hir, HirId } ;
17
- use rustc_macros:: { Decodable , Encodable , HashStable } ;
17
+ use rustc_macros:: { Decodable , Encodable , HashStable , Subdiagnostic } ;
18
18
use rustc_middle:: ty:: print:: with_no_trimmed_paths;
19
19
use rustc_session:: lint:: builtin:: { DEPRECATED , DEPRECATED_IN_FUTURE , SOFT_UNSTABLE } ;
20
- use rustc_session:: lint:: { BuiltinLintDiag , Level , Lint , LintBuffer } ;
20
+ use rustc_session:: lint:: { BuiltinLintDiag , DeprecatedSinceKind , Level , Lint , LintBuffer } ;
21
21
use rustc_session:: parse:: feature_err_issue;
22
22
use rustc_session:: Session ;
23
23
use rustc_span:: symbol:: { sym, Symbol } ;
@@ -125,90 +125,114 @@ pub fn report_unstable(
125
125
}
126
126
}
127
127
128
- pub fn deprecation_suggestion (
129
- diag : & mut Diag < ' _ , ( ) > ,
130
- kind : & str ,
131
- suggestion : Option < Symbol > ,
132
- span : Span ,
133
- ) {
134
- if let Some ( suggestion) = suggestion {
135
- diag. span_suggestion_verbose (
136
- span,
137
- format ! ( "replace the use of the deprecated {kind}" ) ,
138
- suggestion,
139
- Applicability :: MachineApplicable ,
140
- ) ;
128
+ fn deprecation_lint ( is_in_effect : bool ) -> & ' static Lint {
129
+ if is_in_effect { DEPRECATED } else { DEPRECATED_IN_FUTURE }
130
+ }
131
+
132
+ #[ derive( Subdiagnostic ) ]
133
+ #[ suggestion(
134
+ middle_deprecated_suggestion,
135
+ code = "{suggestion}" ,
136
+ style = "verbose" ,
137
+ applicability = "machine-applicable"
138
+ ) ]
139
+ pub struct DeprecationSuggestion {
140
+ #[ primary_span]
141
+ pub span : Span ,
142
+
143
+ pub kind : String ,
144
+ pub suggestion : Symbol ,
145
+ }
146
+
147
+ pub struct Deprecated {
148
+ pub sub : Option < DeprecationSuggestion > ,
149
+
150
+ // FIXME: make this translatable
151
+ pub kind : String ,
152
+ pub path : String ,
153
+ pub note : Option < Symbol > ,
154
+ pub since_kind : DeprecatedSinceKind ,
155
+ }
156
+
157
+ impl Deprecated {
158
+ // FIXME: remove
159
+ pub fn msg_for_since_kind ( since_kind : & DeprecatedSinceKind ) -> rustc_errors:: DiagMessage {
160
+ match since_kind {
161
+ DeprecatedSinceKind :: InEffect => crate :: fluent_generated:: middle_deprecated,
162
+ DeprecatedSinceKind :: InFuture => crate :: fluent_generated:: middle_deprecated_in_future,
163
+ DeprecatedSinceKind :: InVersion ( _) => {
164
+ crate :: fluent_generated:: middle_deprecated_in_version
165
+ }
166
+ }
141
167
}
142
168
}
143
169
144
- fn deprecation_lint ( is_in_effect : bool ) -> & ' static Lint {
145
- if is_in_effect { DEPRECATED } else { DEPRECATED_IN_FUTURE }
170
+ impl < ' a , G : EmissionGuarantee > rustc_errors:: LintDiagnostic < ' a , G > for Deprecated {
171
+ fn decorate_lint < ' b > ( self , diag : & ' b mut Diag < ' a , G > ) {
172
+ diag. arg ( "kind" , self . kind ) ;
173
+ diag. arg ( "path" , self . path ) ;
174
+ if let DeprecatedSinceKind :: InVersion ( version) = self . since_kind {
175
+ diag. arg ( "version" , version) ;
176
+ }
177
+ if let Some ( note) = self . note {
178
+ diag. arg ( "has_note" , true ) ;
179
+ diag. arg ( "note" , note) ;
180
+ } else {
181
+ diag. arg ( "has_note" , false ) ;
182
+ }
183
+ if let Some ( sub) = self . sub {
184
+ diag. subdiagnostic ( diag. dcx , sub) ;
185
+ }
186
+ }
187
+
188
+ fn msg ( & self ) -> rustc_errors:: DiagMessage {
189
+ Self :: msg_for_since_kind ( & self . since_kind )
190
+ }
146
191
}
147
192
148
- fn deprecation_message (
149
- is_in_effect : bool ,
150
- since : DeprecatedSince ,
151
- note : Option < Symbol > ,
152
- kind : & str ,
153
- path : & str ,
154
- ) -> String {
155
- let message = if is_in_effect {
156
- format ! ( "use of deprecated {kind} `{path}`" )
193
+ fn deprecated_since_kind ( is_in_effect : bool , since : DeprecatedSince ) -> DeprecatedSinceKind {
194
+ if is_in_effect {
195
+ DeprecatedSinceKind :: InEffect
157
196
} else {
158
197
match since {
159
- DeprecatedSince :: RustcVersion ( version) => format ! (
160
- "use of {kind} `{path}` that will be deprecated in future version {version}"
161
- ) ,
162
- DeprecatedSince :: Future => {
163
- format ! ( "use of {kind} `{path}` that will be deprecated in a future Rust version" )
198
+ DeprecatedSince :: RustcVersion ( version) => {
199
+ DeprecatedSinceKind :: InVersion ( version. to_string ( ) )
164
200
}
201
+ DeprecatedSince :: Future => DeprecatedSinceKind :: InFuture ,
165
202
DeprecatedSince :: NonStandard ( _)
166
203
| DeprecatedSince :: Unspecified
167
204
| DeprecatedSince :: Err => {
168
205
unreachable ! ( "this deprecation is always in effect; {since:?}" )
169
206
}
170
207
}
171
- } ;
172
-
173
- match note {
174
- Some ( reason) => format ! ( "{message}: {reason}" ) ,
175
- None => message,
176
208
}
177
209
}
178
210
179
- pub fn deprecation_message_and_lint (
180
- depr : & Deprecation ,
181
- kind : & str ,
182
- path : & str ,
183
- ) -> ( String , & ' static Lint ) {
184
- let is_in_effect = depr. is_in_effect ( ) ;
185
- (
186
- deprecation_message ( is_in_effect, depr. since , depr. note , kind, path) ,
187
- deprecation_lint ( is_in_effect) ,
188
- )
189
- }
190
-
191
- pub fn early_report_deprecation (
211
+ pub fn early_report_macro_deprecation (
192
212
lint_buffer : & mut LintBuffer ,
193
- message : String ,
194
- suggestion : Option < Symbol > ,
195
- lint : & ' static Lint ,
213
+ depr : & Deprecation ,
196
214
span : Span ,
197
215
node_id : NodeId ,
216
+ path : String ,
198
217
) {
199
218
if span. in_derive_expansion ( ) {
200
219
return ;
201
220
}
202
221
203
- let diag = BuiltinLintDiag :: DeprecatedMacro { suggestion, span, message } ;
204
- lint_buffer. buffer_lint_with_diagnostic ( lint, node_id, span, diag) ;
222
+ let is_in_effect = depr. is_in_effect ( ) ;
223
+ let diag = BuiltinLintDiag :: DeprecatedMacro {
224
+ suggestion : depr. suggestion ,
225
+ suggestion_span : span,
226
+ note : depr. note ,
227
+ path,
228
+ since_kind : deprecated_since_kind ( is_in_effect, depr. since . clone ( ) ) ,
229
+ } ;
230
+ lint_buffer. buffer_lint_with_diagnostic ( deprecation_lint ( is_in_effect) , node_id, span, diag) ;
205
231
}
206
232
207
233
fn late_report_deprecation (
208
234
tcx : TyCtxt < ' _ > ,
209
- message : String ,
210
- suggestion : Option < Symbol > ,
211
- lint : & ' static Lint ,
235
+ depr : & Deprecation ,
212
236
span : Span ,
213
237
method_span : Option < Span > ,
214
238
hir_id : HirId ,
@@ -217,13 +241,26 @@ fn late_report_deprecation(
217
241
if span. in_derive_expansion ( ) {
218
242
return ;
219
243
}
244
+
245
+ let def_path = with_no_trimmed_paths ! ( tcx. def_path_str( def_id) ) ;
246
+ let def_kind = tcx. def_descr ( def_id) ;
247
+ let is_in_effect = depr. is_in_effect ( ) ;
248
+
220
249
let method_span = method_span. unwrap_or ( span) ;
221
- tcx. node_span_lint ( lint, hir_id, method_span, message, |diag| {
222
- if let hir:: Node :: Expr ( _) = tcx. hir_node ( hir_id) {
223
- let kind = tcx. def_descr ( def_id) ;
224
- deprecation_suggestion ( diag, kind, suggestion, method_span) ;
225
- }
226
- } ) ;
250
+ let suggestion =
251
+ if let hir:: Node :: Expr ( _) = tcx. hir_node ( hir_id) { depr. suggestion } else { None } ;
252
+ let diag = Deprecated {
253
+ sub : suggestion. map ( |suggestion| DeprecationSuggestion {
254
+ span : method_span,
255
+ kind : def_kind. to_owned ( ) ,
256
+ suggestion,
257
+ } ) ,
258
+ kind : def_kind. to_owned ( ) ,
259
+ path : def_path,
260
+ note : depr. note ,
261
+ since_kind : deprecated_since_kind ( is_in_effect, depr. since ) ,
262
+ } ;
263
+ tcx. emit_node_span_lint ( deprecation_lint ( is_in_effect) , hir_id, method_span, diag) ;
227
264
}
228
265
229
266
/// Result of `TyCtxt::eval_stability`.
@@ -352,28 +389,9 @@ impl<'tcx> TyCtxt<'tcx> {
352
389
// Calculating message for lint involves calling `self.def_path_str`.
353
390
// Which by default to calculate visible path will invoke expensive `visible_parent_map` query.
354
391
// So we skip message calculation altogether, if lint is allowed.
355
- let is_in_effect = depr_attr. is_in_effect ( ) ;
356
- let lint = deprecation_lint ( is_in_effect) ;
392
+ let lint = deprecation_lint ( depr_attr. is_in_effect ( ) ) ;
357
393
if self . lint_level_at_node ( lint, id) . 0 != Level :: Allow {
358
- let def_path = with_no_trimmed_paths ! ( self . def_path_str( def_id) ) ;
359
- let def_kind = self . def_descr ( def_id) ;
360
-
361
- late_report_deprecation (
362
- self ,
363
- deprecation_message (
364
- is_in_effect,
365
- depr_attr. since ,
366
- depr_attr. note ,
367
- def_kind,
368
- & def_path,
369
- ) ,
370
- depr_attr. suggestion ,
371
- lint,
372
- span,
373
- method_span,
374
- id,
375
- def_id,
376
- ) ;
394
+ late_report_deprecation ( self , depr_attr, span, method_span, id, def_id) ;
377
395
}
378
396
}
379
397
} ;
0 commit comments