@@ -15,7 +15,6 @@ use errors::{
1515 ItemIsPrivate , PrivateInterfacesOrBoundsLint , ReportEffectiveVisibility , UnnameableTypesLint ,
1616 UnnamedItemIsPrivate ,
1717} ;
18- use rustc_ast:: MacroDef ;
1918use rustc_ast:: visit:: { VisitorResult , try_visit} ;
2019use rustc_data_structures:: fx:: FxHashSet ;
2120use rustc_data_structures:: intern:: Interned ;
@@ -34,7 +33,6 @@ use rustc_middle::ty::{
3433} ;
3534use rustc_middle:: { bug, span_bug} ;
3635use rustc_session:: lint;
37- use rustc_span:: hygiene:: Transparency ;
3836use rustc_span:: { Ident , Span , Symbol , sym} ;
3937use tracing:: debug;
4038
@@ -419,22 +417,8 @@ impl VisibilityLike for EffectiveVisibility {
419417/// The embargo visitor, used to determine the exports of the AST.
420418struct EmbargoVisitor < ' tcx > {
421419 tcx : TyCtxt < ' tcx > ,
422-
423420 /// Effective visibilities for reachable nodes.
424421 effective_visibilities : EffectiveVisibilities ,
425- /// A set of pairs corresponding to modules, where the first module is
426- /// reachable via a macro that's defined in the second module. This cannot
427- /// be represented as reachable because it can't handle the following case:
428- ///
429- /// pub mod n { // Should be `Public`
430- /// pub(crate) mod p { // Should *not* be accessible
431- /// pub fn f() -> i32 { 12 } // Must be `Reachable`
432- /// }
433- /// }
434- /// pub macro m() {
435- /// n::p::f()
436- /// }
437- macro_reachable : FxHashSet < ( LocalModDefId , LocalModDefId ) > ,
438422 /// Has something changed in the level map?
439423 changed : bool ,
440424}
@@ -509,161 +493,6 @@ impl<'tcx> EmbargoVisitor<'tcx> {
509493 level : Level :: ReachableThroughImplTrait ,
510494 }
511495 }
512-
513- // We have to make sure that the items that macros might reference
514- // are reachable, since they might be exported transitively.
515- fn update_reachability_from_macro (
516- & mut self ,
517- local_def_id : LocalDefId ,
518- md : & MacroDef ,
519- macro_ev : EffectiveVisibility ,
520- ) {
521- // Non-opaque macros cannot make other items more accessible than they already are.
522- let hir_id = self . tcx . local_def_id_to_hir_id ( local_def_id) ;
523- let attrs = self . tcx . hir_attrs ( hir_id) ;
524-
525- if find_attr ! ( attrs, RustcMacroTransparency ( x) => * x)
526- . unwrap_or ( Transparency :: fallback ( md. macro_rules ) )
527- != Transparency :: Opaque
528- {
529- return ;
530- }
531-
532- let macro_module_def_id = self . tcx . local_parent ( local_def_id) ;
533- if self . tcx . def_kind ( macro_module_def_id) != DefKind :: Mod {
534- // The macro's parent doesn't correspond to a `mod`, return early (#63164, #65252).
535- return ;
536- }
537- // FIXME(typed_def_id): Introduce checked constructors that check def_kind.
538- let macro_module_def_id = LocalModDefId :: new_unchecked ( macro_module_def_id) ;
539-
540- if self . effective_visibilities . public_at_level ( local_def_id) . is_none ( ) {
541- return ;
542- }
543-
544- // Since we are starting from an externally visible module,
545- // all the parents in the loop below are also guaranteed to be modules.
546- let mut module_def_id = macro_module_def_id;
547- loop {
548- let changed_reachability =
549- self . update_macro_reachable ( module_def_id, macro_module_def_id, macro_ev) ;
550- if changed_reachability || module_def_id == LocalModDefId :: CRATE_DEF_ID {
551- break ;
552- }
553- module_def_id = LocalModDefId :: new_unchecked ( self . tcx . local_parent ( module_def_id) ) ;
554- }
555- }
556-
557- /// Updates the item as being reachable through a macro defined in the given
558- /// module. Returns `true` if the level has changed.
559- fn update_macro_reachable (
560- & mut self ,
561- module_def_id : LocalModDefId ,
562- defining_mod : LocalModDefId ,
563- macro_ev : EffectiveVisibility ,
564- ) -> bool {
565- if self . macro_reachable . insert ( ( module_def_id, defining_mod) ) {
566- for child in self . tcx . module_children_local ( module_def_id. to_local_def_id ( ) ) {
567- if let Res :: Def ( def_kind, def_id) = child. res
568- && let Some ( def_id) = def_id. as_local ( )
569- && child. vis . is_accessible_from ( defining_mod, self . tcx )
570- {
571- let vis = self . tcx . local_visibility ( def_id) ;
572- self . update_macro_reachable_def ( def_id, def_kind, vis, defining_mod, macro_ev) ;
573- }
574- }
575- true
576- } else {
577- false
578- }
579- }
580-
581- fn update_macro_reachable_def (
582- & mut self ,
583- def_id : LocalDefId ,
584- def_kind : DefKind ,
585- vis : ty:: Visibility ,
586- module : LocalModDefId ,
587- macro_ev : EffectiveVisibility ,
588- ) {
589- self . update ( def_id, macro_ev, Level :: Reachable ) ;
590- match def_kind {
591- // No type privacy, so can be directly marked as reachable.
592- DefKind :: Const { .. }
593- | DefKind :: Static { .. }
594- | DefKind :: TraitAlias
595- | DefKind :: TyAlias => {
596- if vis. is_accessible_from ( module, self . tcx ) {
597- self . update ( def_id, macro_ev, Level :: Reachable ) ;
598- }
599- }
600-
601- // Hygiene isn't really implemented for `macro_rules!` macros at the
602- // moment. Accordingly, marking them as reachable is unwise. `macro` macros
603- // have normal hygiene, so we can treat them like other items without type
604- // privacy and mark them reachable.
605- DefKind :: Macro ( _) => {
606- let item = self . tcx . hir_expect_item ( def_id) ;
607- if let hir:: ItemKind :: Macro ( _, MacroDef { macro_rules : false , .. } , _) = item. kind {
608- if vis. is_accessible_from ( module, self . tcx ) {
609- self . update ( def_id, macro_ev, Level :: Reachable ) ;
610- }
611- }
612- }
613-
614- // We can't use a module name as the final segment of a path, except
615- // in use statements. Since re-export checking doesn't consider
616- // hygiene these don't need to be marked reachable. The contents of
617- // the module, however may be reachable.
618- DefKind :: Mod => {
619- if vis. is_accessible_from ( module, self . tcx ) {
620- self . update_macro_reachable (
621- LocalModDefId :: new_unchecked ( def_id) ,
622- module,
623- macro_ev,
624- ) ;
625- }
626- }
627-
628- DefKind :: Struct | DefKind :: Union => {
629- // While structs and unions have type privacy, their fields do not.
630- let struct_def = self . tcx . adt_def ( def_id) ;
631- for field in & struct_def. non_enum_variant ( ) . fields {
632- let def_id = field. did . expect_local ( ) ;
633- let field_vis = self . tcx . local_visibility ( def_id) ;
634- if field_vis. is_accessible_from ( module, self . tcx ) {
635- self . reach ( def_id, macro_ev) . ty ( ) ;
636- }
637- }
638- }
639-
640- // These have type privacy, so are not reachable unless they're
641- // public, or are not namespaced at all.
642- DefKind :: AssocConst { .. }
643- | DefKind :: AssocTy
644- | DefKind :: ConstParam
645- | DefKind :: Ctor ( _, _)
646- | DefKind :: Enum
647- | DefKind :: ForeignTy
648- | DefKind :: Fn
649- | DefKind :: OpaqueTy
650- | DefKind :: AssocFn
651- | DefKind :: Trait
652- | DefKind :: TyParam
653- | DefKind :: Variant
654- | DefKind :: LifetimeParam
655- | DefKind :: ExternCrate
656- | DefKind :: Use
657- | DefKind :: ForeignMod
658- | DefKind :: AnonConst
659- | DefKind :: InlineConst
660- | DefKind :: Field
661- | DefKind :: GlobalAsm
662- | DefKind :: Impl { .. }
663- | DefKind :: Closure
664- | DefKind :: SyntheticCoroutineBody => ( ) ,
665- }
666- }
667496}
668497
669498impl < ' tcx > EmbargoVisitor < ' tcx > {
@@ -689,13 +518,8 @@ impl<'tcx> EmbargoVisitor<'tcx> {
689518 DefKind :: Use | DefKind :: ExternCrate | DefKind :: GlobalAsm => { }
690519 // The interface is empty, and all nested items are processed by `check_def_id`.
691520 DefKind :: Mod => { }
692- DefKind :: Macro { .. } => {
693- if let Some ( item_ev) = item_ev {
694- let ( _, macro_def, _) =
695- self . tcx . hir_expect_item ( owner_id. def_id ) . expect_macro ( ) ;
696- self . update_reachability_from_macro ( owner_id. def_id , macro_def, item_ev) ;
697- }
698- }
521+ // Effective visibilities for macros are processed earlier.
522+ DefKind :: Macro { .. } => { }
699523 DefKind :: ForeignTy
700524 | DefKind :: Const { .. }
701525 | DefKind :: Static { .. }
@@ -1815,7 +1639,6 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
18151639 let mut visitor = EmbargoVisitor {
18161640 tcx,
18171641 effective_visibilities : tcx. resolutions ( ( ) ) . effective_visibilities . clone ( ) ,
1818- macro_reachable : Default :: default ( ) ,
18191642 changed : false ,
18201643 } ;
18211644
@@ -1872,6 +1695,26 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
18721695 visitor. changed = false ;
18731696 }
18741697
1698+ // FIXME: remove this once proper support for defs reachability from macros is implemented.
1699+ // See `ResolverGlobalCtxt::macro_reachable_adts` comment.
1700+ for ( & adt_def_id, macro_mods) in & tcx. resolutions ( ( ) ) . macro_reachable_adts {
1701+ let struct_def = tcx. adt_def ( adt_def_id) ;
1702+ let Some ( struct_ev) = visitor. effective_visibilities . effective_vis ( adt_def_id) . copied ( )
1703+ else {
1704+ continue ;
1705+ } ;
1706+ for field in & struct_def. non_enum_variant ( ) . fields {
1707+ let def_id = field. did . expect_local ( ) ;
1708+ let field_vis = tcx. local_visibility ( def_id) ;
1709+
1710+ for & macro_mod in macro_mods {
1711+ if field_vis. is_accessible_from ( macro_mod, tcx) {
1712+ visitor. reach ( def_id, struct_ev) . ty ( ) ;
1713+ }
1714+ }
1715+ }
1716+ }
1717+
18751718 let crate_items = tcx. hir_crate_items ( ( ) ) ;
18761719 loop {
18771720 for id in crate_items. free_items ( ) {
0 commit comments