Change:
<!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --I tried this code: I expected to see no output from the compiler. Instead, this happened: searched nightlies: from nightly-2022-09-22 to nightly-2022-09-27 regressed nightly: nightly-2022-09-25 searched commit range: regressed commit: This is a roll-up, seems the most likely culprit. cc <details<summarybisected with <a href=''cargo-bisect-rustc</av0.6.4</summaryHost triple: aarch64-apple-darwin Reproduce with: </details modify labels: +regression-from-stable-to-nightly -regression-untriaged
WG-prioritization assigning priority, probably a P-high since the lint malfunction is blocking valid code (iiuc) label -I-prioritize P-high T-compiler
any ideas how to address this or should I start digging in to it
In HIR desugars into two items (import in type namespace and import in value namespace). One of them is externally reachable and another is not (before both of them were incorrectly marked as externally reachable). Code in should somehow account for this desugaring and not report the as unnecessary if at least one of the imports is reachable.
I have been unable to fix this or apply a revert. can you look at implementing this before the beta cutoff?
Reverted in

Discussion:
<del> use crate::NameBindingKind; use crate::Resolver; </del> <ins> use crate::{ImportKind, NameBindingKind, Resolver}; </ins> use rustc_ast::ast; use rustc_ast::visit; use rustc_ast::visit::Visitor;

let module = self.r.get_module(module_id.to_def_id()).unwrap(); let resolutions = self.r.resolutions(module); <del> for (key, name_resolution) in resolutions.borrow().iter() { </del> <ins> for (_, name_resolution) in resolutions.borrow().iter() { </ins> if let Some(mut binding) = name_resolution.borrow().binding() && !binding.is_ambiguity() { // Set the given binding access level to `AccessLevel::Public` and // sets the rest of the `use` chain to `AccessLevel::Exported` until // we hit the actual exported item. <del> // FIXME: tag and is_public() condition must be deleted, // but assertion fail occurs in import_id_for_ns </del> <ins> // FIXME: tag and is_public() condition should be removed, but assertions occur. </ins> let tag = if binding.is_import() { AccessLevel::Exported } else { AccessLevel::Public }; if binding.vis.is_public() { let mut prev_parent_id = module_id;

while let NameBindingKind::Import { binding: nested_binding, import, .. } = binding.kind { <del> let id = self.r.local_def_id(self.r.import_id_for_ns(import, key.ns)); self.update( id, </del> <ins> let mut update = |node_id| self.update( self.r.local_def_id(node_id), </ins> binding.vis.expect_local(), prev_parent_id, level, ); <ins> // In theory all the import IDs have individual visibilities and effective // visibilities, but in practice these IDs go straigth to HIR where all // their few uses assume that their (effective) visibility applies to the // whole syntactic `use` item. So we update them all to the maximum value // among the potential individual effective visibilities. Maybe HIR for // imports shouldn't use three IDs at all. update(import.id); if let ImportKind::Single { additional_ids, .. } = import.kind { update(additional_ids.0); update(additional_ids.1); } </ins> level = AccessLevel::Exported; <del> prev_parent_id = id; </del> <ins> prev_parent_id = self.r.local_def_id(import.id); </ins> binding = nested_binding; } }

use crate::diagnostics::{import_candidates, Suggestion}; use crate::Determinacy::{self, *}; <del> use crate::Namespace::{self, *}; </del> <ins> use crate::Namespace::*; </ins> use crate::{module_to_string, names_to_string, ImportSuggestion}; use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment}; use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet};

self.used_imports.insert(import.id); } } <del> /// Take primary and additional node IDs from an import and select one that corresponds to the /// given namespace. The logic must match the corresponding logic from `fn lower_use_tree` that /// assigns resolutons to IDs. pub(crate) fn import_id_for_ns(&self, import: &Import<'_>, ns: Namespace) -> NodeId { if let ImportKind::Single { additional_ids: (id1, id2), .. } = import.kind { if let Some(resolutions) = self.import_res_map.get(&import.id) { assert!(resolutions[ns].is_some(), "incorrectly finalized import"); return match ns { TypeNS => import.id, ValueNS => match resolutions.type_ns { Some(_) => id1, None => import.id, }, MacroNS => match (resolutions.type_ns, resolutions.value_ns) { (Some(_), Some(_)) => id2, (Some(_), None) | (None, Some(_)) => id1, (None, None) => import.id, }, }; } } import.id } </del> } /// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved

#[rustc_effective_visibility] pub use half_public_import::HalfPublicImport; //~ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub <ins> //~^ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub </ins> fn main() {}

LL | pub use half_public_import::HalfPublicImport; |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <ins> error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub --> $DIR/access_levels.rs:72:9 | LL | pub use half_public_import::HalfPublicImport; |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ </ins> error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub --> $DIR/access_levels.rs:14:13 |

LL |             type B; |             ^^^^^^ <del> error: aborting due to 21 previous errors </del> <ins> error: aborting due to 22 previous errors </ins>