33
44pub use self :: StabilityLevel :: * ;
55
6- use crate :: ty:: { self , TyCtxt } ;
6+ use crate :: ty:: { self , DefIdTree , TyCtxt } ;
77use rustc_ast:: NodeId ;
88use rustc_attr:: { self as attr, ConstStability , Deprecation , Stability } ;
99use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
@@ -90,6 +90,7 @@ pub fn report_unstable(
9090 feature : Symbol ,
9191 reason : Option < Symbol > ,
9292 issue : Option < NonZeroU32 > ,
93+ suggestion : Option < ( Span , String , String , Applicability ) > ,
9394 is_soft : bool ,
9495 span : Span ,
9596 soft_handler : impl FnOnce ( & ' static Lint , Span , & str ) ,
@@ -116,8 +117,12 @@ pub fn report_unstable(
116117 if is_soft {
117118 soft_handler ( SOFT_UNSTABLE , span, & msg)
118119 } 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 ( ) ;
121126 }
122127 }
123128}
@@ -271,7 +276,13 @@ pub enum EvalResult {
271276 Allow ,
272277 /// We cannot use the item because it is unstable and we did not provide the
273278 /// 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+ } ,
275286 /// The item does not have the `#[stable]` or `#[unstable]` marker assigned.
276287 Unmarked ,
277288}
@@ -292,6 +303,32 @@ fn skip_stability_check_due_to_privacy(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
292303 }
293304}
294305
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+
295332impl < ' tcx > TyCtxt < ' tcx > {
296333 /// Evaluates the stability of an item.
297334 ///
@@ -406,7 +443,8 @@ impl<'tcx> TyCtxt<'tcx> {
406443 }
407444 }
408445
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 }
410448 }
411449 Some ( _) => {
412450 // Stable APIs are always ok to call and deprecated APIs are
@@ -457,9 +495,16 @@ impl<'tcx> TyCtxt<'tcx> {
457495 } ;
458496 match self . eval_stability ( def_id, id, span, method_span) {
459497 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+ ) ,
463508 EvalResult :: Unmarked => unmarked ( span, def_id) ,
464509 }
465510 }
0 commit comments