22//! propagating default levels lexically from parent to children ast nodes.
33
44use std:: num:: NonZero ;
5+ use std:: ops:: ControlFlow ;
56
67use rustc_ast:: NodeId ;
8+ use rustc_data_structures:: fx:: FxHashSet ;
79use rustc_errors:: { Applicability , Diag , EmissionGuarantee , LintBuffer } ;
810use rustc_feature:: GateIssue ;
911use rustc_hir:: attrs:: { DeprecatedSince , Deprecation } ;
12+ use rustc_hir:: def:: { CtorOf , DefKind } ;
1013use rustc_hir:: def_id:: { DefId , LocalDefId } ;
1114use rustc_hir:: { self as hir, ConstStability , DefaultBodyStability , HirId , Stability } ;
1215use rustc_macros:: { Decodable , Encodable , HashStable , Subdiagnostic } ;
@@ -191,6 +194,33 @@ pub fn early_report_macro_deprecation(
191194 } ;
192195 lint_buffer. buffer_lint ( deprecation_lint ( is_in_effect) , node_id, span, diag) ;
193196}
197+ /// supress duplicate warning when importing unit or tuple structs
198+ /// (which have resolutions in multiple namespaces)
199+ fn check_already_linted (
200+ tcx : TyCtxt < ' _ > ,
201+ hir_id : HirId ,
202+ def_id : DefId ,
203+ already_linted_paths : Option < & mut FxHashSet < ( HirId , DefId ) > > ,
204+ ) -> ControlFlow < ( ) > {
205+ let Some ( already_linted_paths) = already_linted_paths else {
206+ return ControlFlow :: Continue ( ( ) ) ;
207+ } ;
208+
209+ let def_id = match tcx. def_kind ( def_id) {
210+ // parent so the defid matches that of the struct
211+ DefKind :: Ctor ( CtorOf :: Struct , _) => tcx. parent ( def_id) ,
212+ // just the defid of the struct
213+ DefKind :: Struct => def_id,
214+ // otherwise, we don't care
215+ _ => return ControlFlow :: Continue ( ( ) ) ,
216+ } ;
217+
218+ if already_linted_paths. insert ( ( hir_id, def_id) ) {
219+ return ControlFlow :: Continue ( ( ) ) ;
220+ }
221+
222+ ControlFlow :: Break ( ( ) )
223+ }
194224
195225fn late_report_deprecation (
196226 tcx : TyCtxt < ' _ > ,
@@ -199,6 +229,7 @@ fn late_report_deprecation(
199229 method_span : Option < Span > ,
200230 hir_id : HirId ,
201231 def_id : DefId ,
232+ already_linted_paths : Option < & mut FxHashSet < ( HirId , DefId ) > > ,
202233) {
203234 if span. in_derive_expansion ( ) {
204235 return ;
@@ -214,6 +245,10 @@ fn late_report_deprecation(
214245 return ;
215246 }
216247
248+ if check_already_linted ( tcx, hir_id, def_id, already_linted_paths) . is_break ( ) {
249+ return ;
250+ }
251+
217252 let def_path = with_no_trimmed_paths ! ( tcx. def_path_str( def_id) ) ;
218253 let def_kind = tcx. def_descr ( def_id) ;
219254
@@ -303,7 +338,7 @@ impl<'tcx> TyCtxt<'tcx> {
303338 span : Span ,
304339 method_span : Option < Span > ,
305340 ) -> EvalResult {
306- self . eval_stability_allow_unstable ( def_id, id, span, method_span, AllowUnstable :: No )
341+ self . eval_stability_allow_unstable ( def_id, id, span, method_span, AllowUnstable :: No , None )
307342 }
308343
309344 /// Evaluates the stability of an item.
@@ -324,6 +359,7 @@ impl<'tcx> TyCtxt<'tcx> {
324359 span : Span ,
325360 method_span : Option < Span > ,
326361 allow_unstable : AllowUnstable ,
362+ already_linted_paths : Option < & mut FxHashSet < ( HirId , DefId ) > > ,
327363 ) -> EvalResult {
328364 // Deprecated attributes apply in-crate and cross-crate.
329365 if let Some ( id) = id {
@@ -341,7 +377,15 @@ impl<'tcx> TyCtxt<'tcx> {
341377 // hierarchy.
342378 let depr_attr = & depr_entry. attr ;
343379 if !skip || depr_attr. is_since_rustc_version ( ) {
344- late_report_deprecation ( self , depr_attr, span, method_span, id, def_id) ;
380+ late_report_deprecation (
381+ self ,
382+ depr_attr,
383+ span,
384+ method_span,
385+ id,
386+ def_id,
387+ already_linted_paths,
388+ ) ;
345389 }
346390 } ;
347391 }
@@ -492,7 +536,7 @@ impl<'tcx> TyCtxt<'tcx> {
492536 span : Span ,
493537 method_span : Option < Span > ,
494538 ) -> bool {
495- self . check_stability_allow_unstable ( def_id, id, span, method_span, AllowUnstable :: No )
539+ self . check_stability_allow_unstable ( def_id, id, span, method_span, AllowUnstable :: No , None )
496540 }
497541
498542 /// Checks if an item is stable or error out.
@@ -513,6 +557,7 @@ impl<'tcx> TyCtxt<'tcx> {
513557 span : Span ,
514558 method_span : Option < Span > ,
515559 allow_unstable : AllowUnstable ,
560+ already_linted_paths : Option < & mut FxHashSet < ( HirId , DefId ) > > ,
516561 ) -> bool {
517562 self . check_optional_stability (
518563 def_id,
@@ -525,6 +570,7 @@ impl<'tcx> TyCtxt<'tcx> {
525570 // was referenced.
526571 self . dcx ( ) . span_delayed_bug ( span, format ! ( "encountered unmarked API: {def_id:?}" ) ) ;
527572 } ,
573+ already_linted_paths,
528574 )
529575 }
530576
@@ -542,14 +588,21 @@ impl<'tcx> TyCtxt<'tcx> {
542588 method_span : Option < Span > ,
543589 allow_unstable : AllowUnstable ,
544590 unmarked : impl FnOnce ( Span , DefId ) ,
591+ already_linted_paths : Option < & mut FxHashSet < ( HirId , DefId ) > > ,
545592 ) -> bool {
546593 let soft_handler = |lint, span, msg : String | {
547594 self . node_span_lint ( lint, id. unwrap_or ( hir:: CRATE_HIR_ID ) , span, |lint| {
548595 lint. primary_message ( msg) ;
549596 } )
550597 } ;
551- let eval_result =
552- self . eval_stability_allow_unstable ( def_id, id, span, method_span, allow_unstable) ;
598+ let eval_result = self . eval_stability_allow_unstable (
599+ def_id,
600+ id,
601+ span,
602+ method_span,
603+ allow_unstable,
604+ already_linted_paths,
605+ ) ;
553606 let is_allowed = matches ! ( eval_result, EvalResult :: Allow ) ;
554607 match eval_result {
555608 EvalResult :: Allow => { }
0 commit comments