3
3
4
4
pub use self :: StabilityLevel :: * ;
5
5
6
- use crate :: ty:: { self , TyCtxt } ;
6
+ use crate :: ty:: { self , DefIdTree , TyCtxt } ;
7
7
use rustc_ast:: NodeId ;
8
8
use rustc_attr:: { self as attr, ConstStability , Deprecation , Stability } ;
9
9
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
@@ -90,6 +90,7 @@ pub fn report_unstable(
90
90
feature : Symbol ,
91
91
reason : Option < Symbol > ,
92
92
issue : Option < NonZeroU32 > ,
93
+ suggestion : Option < ( Span , String , String , Applicability ) > ,
93
94
is_soft : bool ,
94
95
span : Span ,
95
96
soft_handler : impl FnOnce ( & ' static Lint , Span , & str ) ,
@@ -116,8 +117,12 @@ pub fn report_unstable(
116
117
if is_soft {
117
118
soft_handler ( SOFT_UNSTABLE , span, & msg)
118
119
} else {
119
- feature_err_issue ( & sess. parse_sess , feature, span, GateIssue :: Library ( issue) , & msg)
120
- . emit ( ) ;
120
+ let mut err =
121
+ feature_err_issue ( & sess. parse_sess , feature, span, GateIssue :: Library ( issue) , & msg) ;
122
+ if let Some ( ( inner_types, ref msg, sugg, applicability) ) = suggestion {
123
+ err. span_suggestion ( inner_types, msg, sugg, applicability) ;
124
+ }
125
+ err. emit ( ) ;
121
126
}
122
127
}
123
128
}
@@ -271,7 +276,13 @@ pub enum EvalResult {
271
276
Allow ,
272
277
/// We cannot use the item because it is unstable and we did not provide the
273
278
/// corresponding feature gate.
274
- Deny { feature : Symbol , reason : Option < Symbol > , issue : Option < NonZeroU32 > , is_soft : bool } ,
279
+ Deny {
280
+ feature : Symbol ,
281
+ reason : Option < Symbol > ,
282
+ issue : Option < NonZeroU32 > ,
283
+ suggestion : Option < ( Span , String , String , Applicability ) > ,
284
+ is_soft : bool ,
285
+ } ,
275
286
/// The item does not have the `#[stable]` or `#[unstable]` marker assigned.
276
287
Unmarked ,
277
288
}
@@ -292,6 +303,32 @@ fn skip_stability_check_due_to_privacy(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
292
303
}
293
304
}
294
305
306
+ // See issue #83250.
307
+ fn suggestion_for_allocator_api (
308
+ tcx : TyCtxt < ' _ > ,
309
+ def_id : DefId ,
310
+ span : Span ,
311
+ feature : Symbol ,
312
+ ) -> Option < ( Span , String , String , Applicability ) > {
313
+ if feature == sym:: allocator_api {
314
+ if let Some ( trait_) = tcx. parent ( def_id) {
315
+ if tcx. is_diagnostic_item ( sym:: Vec , trait_) {
316
+ let sm = tcx. sess . parse_sess . source_map ( ) ;
317
+ let inner_types = sm. span_extend_to_prev_char ( span, '<' , true ) ;
318
+ if let Ok ( snippet) = sm. span_to_snippet ( inner_types) {
319
+ return Some ( (
320
+ inner_types,
321
+ "consider wrapping the inner types in tuple" . to_string ( ) ,
322
+ format ! ( "({})" , snippet) ,
323
+ Applicability :: MaybeIncorrect ,
324
+ ) ) ;
325
+ }
326
+ }
327
+ }
328
+ }
329
+ None
330
+ }
331
+
295
332
impl < ' tcx > TyCtxt < ' tcx > {
296
333
/// Evaluates the stability of an item.
297
334
///
@@ -406,7 +443,8 @@ impl<'tcx> TyCtxt<'tcx> {
406
443
}
407
444
}
408
445
409
- EvalResult :: Deny { feature, reason, issue, is_soft }
446
+ let suggestion = suggestion_for_allocator_api ( self , def_id, span, feature) ;
447
+ EvalResult :: Deny { feature, reason, issue, suggestion, is_soft }
410
448
}
411
449
Some ( _) => {
412
450
// Stable APIs are always ok to call and deprecated APIs are
@@ -457,9 +495,16 @@ impl<'tcx> TyCtxt<'tcx> {
457
495
} ;
458
496
match self . eval_stability ( def_id, id, span, method_span) {
459
497
EvalResult :: Allow => { }
460
- EvalResult :: Deny { feature, reason, issue, is_soft } => {
461
- report_unstable ( self . sess , feature, reason, issue, is_soft, span, soft_handler)
462
- }
498
+ EvalResult :: Deny { feature, reason, issue, suggestion, is_soft } => report_unstable (
499
+ self . sess ,
500
+ feature,
501
+ reason,
502
+ issue,
503
+ suggestion,
504
+ is_soft,
505
+ span,
506
+ soft_handler,
507
+ ) ,
463
508
EvalResult :: Unmarked => unmarked ( span, def_id) ,
464
509
}
465
510
}
0 commit comments