@@ -37,8 +37,9 @@ use crate::errors::{
3737use crate :: ref_mut:: CmCell ;
3838use crate :: {
3939 AmbiguityError , BindingKey , CmResolver , Decl , DeclData , DeclKind , Determinacy , Finalize ,
40- IdentKey , ImportSuggestion , LocalModule , ModuleOrUniformRoot , ParentScope , PathResult , PerNS ,
41- Res , ResolutionError , Resolver , ScopeSet , Segment , Used , module_to_string, names_to_string,
40+ IdentKey , ImportSuggestion , ImportSummary , LocalModule , ModuleOrUniformRoot , ParentScope ,
41+ PathResult , PerNS , Res , ResolutionError , Resolver , ScopeSet , Segment , Used , module_to_string,
42+ names_to_string,
4243} ;
4344
4445/// A potential import declaration in the process of being planted into a module.
@@ -267,6 +268,14 @@ impl<'ra> ImportData<'ra> {
267268 ImportKind :: MacroExport => Reexport :: MacroExport ,
268269 }
269270 }
271+
272+ fn summary ( & self ) -> ImportSummary {
273+ ImportSummary {
274+ vis : self . vis ,
275+ nearest_parent_mod : self . parent_scope . module . nearest_parent_mod ( ) . expect_local ( ) ,
276+ is_single : matches ! ( self . kind, ImportKind :: Single { .. } ) ,
277+ }
278+ }
270279}
271280
272281/// Records information about the resolution of a name in a namespace of a module.
@@ -327,9 +336,9 @@ struct UnresolvedImportError {
327336
328337// Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;`
329338// are permitted for backward-compatibility under a deprecation lint.
330- fn pub_use_of_private_extern_crate_hack ( import : Import < ' _ > , decl : Decl < ' _ > ) -> Option < NodeId > {
331- match ( & import. kind , & decl. kind ) {
332- ( ImportKind :: Single { .. } , DeclKind :: Import { import : decl_import, .. } )
339+ fn pub_use_of_private_extern_crate_hack ( import : ImportSummary , decl : Decl < ' _ > ) -> Option < NodeId > {
340+ match ( import. is_single , decl. kind ) {
341+ ( true , DeclKind :: Import { import : decl_import, .. } )
333342 if let ImportKind :: ExternCrate { id, .. } = decl_import. kind
334343 && import. vis . is_public ( ) =>
335344 {
@@ -361,31 +370,50 @@ fn remove_same_import<'ra>(d1: Decl<'ra>, d2: Decl<'ra>) -> (Decl<'ra>, Decl<'ra
361370}
362371
363372impl < ' ra , ' tcx > Resolver < ' ra , ' tcx > {
373+ pub ( crate ) fn import_decl_vis ( & self , decl : Decl < ' ra > , import : ImportSummary ) -> Visibility {
374+ assert ! ( import. vis. is_accessible_from( import. nearest_parent_mod, self . tcx) ) ;
375+ let decl_vis = decl. vis ( ) ;
376+ if decl_vis. is_at_least ( import. vis , self . tcx ) {
377+ // Ordered, import is less visible than the imported declaration, or the same,
378+ // use the import's visibility.
379+ import. vis
380+ } else if decl_vis. is_accessible_from ( import. nearest_parent_mod , self . tcx ) {
381+ // Ordered, imported declaration is less visible than the import, but is still visible
382+ // from the current module, use the declaration's visibility.
383+ assert ! ( import. vis. is_at_least( decl_vis, self . tcx) ) ;
384+ if pub_use_of_private_extern_crate_hack ( import, decl) . is_some ( ) {
385+ import. vis
386+ } else {
387+ decl_vis. expect_local ( )
388+ }
389+ } else {
390+ // Ordered or not, the imported declaration is too private for the current module.
391+ // It doesn't matter what visibility we choose here (except in the `PRIVATE_MACRO_USE`
392+ // case), because either some error will be reported, or the import declaration
393+ // will be thrown away (unfortunately cannot use delayed bug here for this reason).
394+ // Use import visibility to keep the all declaration visibilities in a module ordered.
395+ import. vis
396+ }
397+ }
398+
364399 /// Given an import and the declaration that it points to,
365400 /// create the corresponding import declaration.
366401 pub ( crate ) fn new_import_decl ( & self , decl : Decl < ' ra > , import : Import < ' ra > ) -> Decl < ' ra > {
367- let import_vis = import. vis . to_def_id ( ) ;
368- let vis = if decl. vis ( ) . is_at_least ( import_vis, self . tcx )
369- || pub_use_of_private_extern_crate_hack ( import, decl) . is_some ( )
370- {
371- import_vis
372- } else {
373- decl. vis ( )
374- } ;
402+ let vis = self . import_decl_vis ( decl, import. summary ( ) ) ;
375403
376404 if let ImportKind :: Glob { ref max_vis, .. } = import. kind
377- && ( vis == import_vis
405+ && ( vis == import . vis
378406 || max_vis. get ( ) . is_none_or ( |max_vis| vis. is_at_least ( max_vis, self . tcx ) ) )
379407 {
380- max_vis. set_unchecked ( Some ( vis. expect_local ( ) ) )
408+ max_vis. set_unchecked ( Some ( vis) )
381409 }
382410
383411 self . arenas . alloc_decl ( DeclData {
384412 kind : DeclKind :: Import { source_decl : decl, import } ,
385413 ambiguity : CmCell :: new ( None ) ,
386414 warn_ambiguity : CmCell :: new ( false ) ,
387415 span : import. span ,
388- vis : CmCell :: new ( vis) ,
416+ vis : CmCell :: new ( vis. to_def_id ( ) ) ,
389417 expansion : import. parent_scope . expansion ,
390418 parent_module : Some ( import. parent_scope . module ) ,
391419 } )
@@ -448,6 +476,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
448476 }
449477 } else if !old_glob_decl. vis ( ) . is_at_least ( glob_decl. vis ( ) , self . tcx ) {
450478 // We are glob-importing the same item but with greater visibility.
479+ // All visibilities here are ordered because all of them are ancestors of `module`.
451480 // FIXME: Update visibility in place, but without regressions
452481 // (#152004, #151124, #152347).
453482 glob_decl
@@ -471,7 +500,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
471500 decl : Decl < ' ra > ,
472501 warn_ambiguity : bool ,
473502 ) -> Result < ( ) , Decl < ' ra > > {
503+ assert ! ( !decl. warn_ambiguity. get( ) ) ;
504+ assert ! ( decl. ambiguity. get( ) . is_none( ) ) ;
474505 let module = decl. parent_module . unwrap ( ) . expect_local ( ) ;
506+ assert ! ( self . is_accessible_from( decl. vis( ) , module. to_module( ) ) ) ;
475507 let res = decl. res ( ) ;
476508 self . check_reserved_macro_name ( ident. name , orig_ident_span, res) ;
477509 // Even if underscore names cannot be looked up, we still need to add them to modules,
@@ -487,7 +519,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
487519 orig_ident_span,
488520 warn_ambiguity,
489521 |this, resolution| {
490- assert ! ( !decl. warn_ambiguity. get( ) ) ;
491522 if decl. is_glob_import ( ) {
492523 resolution. glob_decl = Some ( match resolution. glob_decl {
493524 Some ( old_decl) => this. select_glob_decl (
@@ -1261,7 +1292,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12611292 & import. parent_scope ,
12621293 Some ( Finalize {
12631294 report_private : false ,
1264- import_vis : Some ( import. vis ) ,
1295+ import : Some ( import. summary ( ) ) ,
12651296 ..finalize
12661297 } ) ,
12671298 bindings[ ns] . get ( ) . decl ( ) ,
@@ -1461,7 +1492,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
14611492 // All namespaces must be re-exported with extra visibility for an error to occur.
14621493 if !any_successful_reexport {
14631494 let ( ns, binding) = reexport_error. unwrap ( ) ;
1464- if let Some ( extern_crate_id) = pub_use_of_private_extern_crate_hack ( import, binding) {
1495+ if let Some ( extern_crate_id) =
1496+ pub_use_of_private_extern_crate_hack ( import. summary ( ) , binding)
1497+ {
14651498 let extern_crate_sp = self . tcx . source_span ( self . local_def_id ( extern_crate_id) ) ;
14661499 self . lint_buffer . buffer_lint (
14671500 PUB_USE_OF_PRIVATE_EXTERN_CRATE ,
0 commit comments