summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-05-14 02:53:52 +0000
committerbors <bors@rust-lang.org>2023-05-14 02:53:52 +0000
commitad6ab11234ae885913229f6de2c4465bdc0d76f3 (patch)
treedf2d714cb3a3e3298d560a88335d38d2d4cefe1a
parent2e18605af29ccf875cdcb539a522f11f5ac44113 (diff)
parent670f5b134e5dcb43e88d5c59f716058d320a2265 (diff)
downloadrust-ad6ab11234ae885913229f6de2c4465bdc0d76f3.tar.gz
Auto merge of #111425 - Bryanskiy:privacy_ef, r=petrochenkov
Populate effective visibilities in `rustc_privacy` (take 2) Same as https://github.com/rust-lang/rust/pull/110907 + regressions fixes. Fixes https://github.com/rust-lang/rust/issues/111359. r? `@petrochenkov`
-rw-r--r--compiler/rustc_lint/src/builtin.rs8
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs45
-rw-r--r--compiler/rustc_privacy/src/lib.rs274
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs4
-rw-r--r--library/core/src/iter/adapters/flatten.rs6
-rw-r--r--tests/ui/lint/issue-111359.rs27
-rw-r--r--tests/ui/lint/issue-111359.stderr26
7 files changed, 243 insertions, 147 deletions
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index b1c45eaf601..9b74d108546 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -647,7 +647,9 @@ declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS])
impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
- if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
+ if !(cx.effective_visibilities.is_reachable(item.owner_id.def_id)
+ && cx.tcx.local_visibility(item.owner_id.def_id).is_public())
+ {
return;
}
let (def, ty) = match item.kind {
@@ -766,7 +768,9 @@ impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);
impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
- if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
+ if !(cx.effective_visibilities.is_reachable(item.owner_id.def_id)
+ && cx.tcx.local_visibility(item.owner_id.def_id).is_public())
+ {
return;
}
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index 967fed687b6..aeb6a1601fc 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -64,7 +64,7 @@ impl EffectiveVisibility {
self.at_level(level).is_public()
}
- pub fn from_vis(vis: Visibility) -> EffectiveVisibility {
+ pub const fn from_vis(vis: Visibility) -> EffectiveVisibility {
EffectiveVisibility {
direct: vis,
reexported: vis,
@@ -72,6 +72,18 @@ impl EffectiveVisibility {
reachable_through_impl_trait: vis,
}
}
+
+ #[must_use]
+ pub fn min(mut self, lhs: EffectiveVisibility, tcx: TyCtxt<'_>) -> Self {
+ for l in Level::all_levels() {
+ let rhs_vis = self.at_level_mut(l);
+ let lhs_vis = *lhs.at_level(l);
+ if rhs_vis.is_at_least(lhs_vis, tcx) {
+ *rhs_vis = lhs_vis;
+ };
+ }
+ self
+ }
}
/// Holds a map of effective visibilities for reachable HIR nodes.
@@ -137,24 +149,6 @@ impl EffectiveVisibilities {
};
}
- pub fn set_public_at_level(
- &mut self,
- id: LocalDefId,
- lazy_private_vis: impl FnOnce() -> Visibility,
- level: Level,
- ) {
- let mut effective_vis = self
- .effective_vis(id)
- .copied()
- .unwrap_or_else(|| EffectiveVisibility::from_vis(lazy_private_vis()));
- for l in Level::all_levels() {
- if l <= level {
- *effective_vis.at_level_mut(l) = Visibility::Public;
- }
- }
- self.map.insert(id, effective_vis);
- }
-
pub fn check_invariants(&self, tcx: TyCtxt<'_>, early: bool) {
if !cfg!(debug_assertions) {
return;
@@ -219,7 +213,7 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
pub fn update(
&mut self,
id: Id,
- nominal_vis: Visibility,
+ nominal_vis: Option<Visibility>,
lazy_private_vis: impl FnOnce() -> Visibility,
inherited_effective_vis: EffectiveVisibility,
level: Level,
@@ -243,12 +237,11 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level
&& level != l)
{
- calculated_effective_vis =
- if nominal_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
- inherited_effective_vis_at_level
- } else {
- nominal_vis
- };
+ calculated_effective_vis = if let Some(nominal_vis) = nominal_vis && !nominal_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
+ nominal_vis
+ } else {
+ inherited_effective_vis_at_level
+ }
}
// effective visibility can't be decreased at next update call for the
// same id
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index d6eb5463870..817f304e8ef 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -25,7 +25,7 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{AssocItemKind, HirIdSet, ItemId, Node, PatKind};
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::privacy::{EffectiveVisibilities, Level};
+use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
use rustc_middle::span_bug;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::InternalSubsts;
@@ -38,7 +38,7 @@ use rustc_span::Span;
use std::marker::PhantomData;
use std::ops::ControlFlow;
-use std::{cmp, fmt, mem};
+use std::{fmt, mem};
use errors::{
FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface,
@@ -408,8 +408,9 @@ impl VisibilityLike for ty::Visibility {
min(find.tcx.local_visibility(def_id), find.min, find.tcx)
}
}
-impl VisibilityLike for Option<Level> {
- const MAX: Self = Some(Level::Direct);
+
+impl VisibilityLike for Option<EffectiveVisibility> {
+ const MAX: Self = Some(EffectiveVisibility::from_vis(ty::Visibility::Public));
// Type inference is very smart sometimes.
// It can make an impl reachable even some components of its type or trait are unreachable.
// E.g. methods of `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
@@ -421,7 +422,13 @@ impl VisibilityLike for Option<Level> {
// (which require reaching the `DefId`s in them).
const SHALLOW: bool = true;
fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self {
- cmp::min(find.effective_visibilities.public_at_level(def_id), find.min)
+ if let Some(min) = find.min {
+ return find
+ .effective_visibilities
+ .effective_vis(def_id)
+ .map(|eff_vis| min.min(*eff_vis, find.tcx));
+ }
+ None
}
}
@@ -447,49 +454,79 @@ struct EmbargoVisitor<'tcx> {
/// n::p::f()
/// }
macro_reachable: FxHashSet<(LocalDefId, LocalDefId)>,
- /// Previous visibility level; `None` means unreachable.
- prev_level: Option<Level>,
/// Has something changed in the level map?
changed: bool,
}
struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> {
- level: Option<Level>,
+ effective_vis: Option<EffectiveVisibility>,
item_def_id: LocalDefId,
ev: &'a mut EmbargoVisitor<'tcx>,
+ level: Level,
}
impl<'tcx> EmbargoVisitor<'tcx> {
- fn get(&self, def_id: LocalDefId) -> Option<Level> {
- self.effective_visibilities.public_at_level(def_id)
- }
-
- /// Updates node level and returns the updated level.
- fn update(&mut self, def_id: LocalDefId, level: Option<Level>) -> Option<Level> {
- let old_level = self.get(def_id);
- // Visibility levels can only grow.
- if level > old_level {
- self.effective_visibilities.set_public_at_level(
- def_id,
- || ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id)),
- level.unwrap(),
- );
- self.changed = true;
- level
- } else {
- old_level
+ fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> {
+ self.effective_visibilities.effective_vis(def_id).copied()
+ }
+
+ // Updates node effective visibility.
+ fn update(
+ &mut self,
+ def_id: LocalDefId,
+ inherited_effective_vis: Option<EffectiveVisibility>,
+ level: Level,
+ ) {
+ let nominal_vis = self.tcx.local_visibility(def_id);
+ self.update_eff_vis(def_id, inherited_effective_vis, Some(nominal_vis), level);
+ }
+
+ fn update_eff_vis(
+ &mut self,
+ def_id: LocalDefId,
+ inherited_effective_vis: Option<EffectiveVisibility>,
+ nominal_vis: Option<ty::Visibility>,
+ level: Level,
+ ) {
+ if let Some(inherited_effective_vis) = inherited_effective_vis {
+ let private_vis =
+ ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id));
+ if Some(private_vis) != nominal_vis {
+ self.changed |= self.effective_visibilities.update(
+ def_id,
+ nominal_vis,
+ || private_vis,
+ inherited_effective_vis,
+ level,
+ self.tcx,
+ );
+ }
}
}
fn reach(
&mut self,
def_id: LocalDefId,
- level: Option<Level>,
+ effective_vis: Option<EffectiveVisibility>,
) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
ReachEverythingInTheInterfaceVisitor {
- level: cmp::min(level, Some(Level::Reachable)),
+ effective_vis,
item_def_id: def_id,
ev: self,
+ level: Level::Reachable,
+ }
+ }
+
+ fn reach_through_impl_trait(
+ &mut self,
+ def_id: LocalDefId,
+ effective_vis: Option<EffectiveVisibility>,
+ ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
+ ReachEverythingInTheInterfaceVisitor {
+ effective_vis,
+ item_def_id: def_id,
+ ev: self,
+ level: Level::ReachableThroughImplTrait,
}
}
@@ -510,16 +547,18 @@ impl<'tcx> EmbargoVisitor<'tcx> {
return;
}
- if self.get(local_def_id).is_none() {
+ if self.effective_visibilities.public_at_level(local_def_id).is_none() {
return;
}
// Since we are starting from an externally visible module,
// all the parents in the loop below are also guaranteed to be modules.
let mut module_def_id = macro_module_def_id;
+ let macro_ev = self.get(local_def_id);
+ assert!(macro_ev.is_some());
loop {
let changed_reachability =
- self.update_macro_reachable(module_def_id, macro_module_def_id);
+ self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev);
if changed_reachability || module_def_id == CRATE_DEF_ID {
break;
}
@@ -533,21 +572,33 @@ impl<'tcx> EmbargoVisitor<'tcx> {
&mut self,
module_def_id: LocalDefId,
defining_mod: LocalDefId,
+ macro_ev: Option<EffectiveVisibility>,
) -> bool {
if self.macro_reachable.insert((module_def_id, defining_mod)) {
- self.update_macro_reachable_mod(module_def_id, defining_mod);
+ self.update_macro_reachable_mod(module_def_id, defining_mod, macro_ev);
true
} else {
false
}
}
- fn update_macro_reachable_mod(&mut self, module_def_id: LocalDefId, defining_mod: LocalDefId) {
+ fn update_macro_reachable_mod(
+ &mut self,
+ module_def_id: LocalDefId,
+ defining_mod: LocalDefId,
+ macro_ev: Option<EffectiveVisibility>,
+ ) {
let module = self.tcx.hir().get_module(module_def_id).0;
for item_id in module.item_ids {
let def_kind = self.tcx.def_kind(item_id.owner_id);
let vis = self.tcx.local_visibility(item_id.owner_id.def_id);
- self.update_macro_reachable_def(item_id.owner_id.def_id, def_kind, vis, defining_mod);
+ self.update_macro_reachable_def(
+ item_id.owner_id.def_id,
+ def_kind,
+ vis,
+ defining_mod,
+ macro_ev,
+ );
}
for child in self.tcx.module_children_local(module_def_id) {
// FIXME: Use module children for the logic above too.
@@ -556,7 +607,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
&& let Res::Def(def_kind, def_id) = child.res
&& let Some(def_id) = def_id.as_local() {
let vis = self.tcx.local_visibility(def_id);
- self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod);
+ self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod, macro_ev);
}
}
}
@@ -567,16 +618,14 @@ impl<'tcx> EmbargoVisitor<'tcx> {
def_kind: DefKind,
vis: ty::Visibility,
module: LocalDefId,
+ macro_ev: Option<EffectiveVisibility>,
) {
- let level = Some(Level::Reachable);
- if vis.is_public() {
- self.update(def_id, level);
- }
+ self.update(def_id, macro_ev, Level::Reachable);
match def_kind {
// No type privacy, so can be directly marked as reachable.
DefKind::Const | DefKind::Static(_) | DefKind::TraitAlias | DefKind::TyAlias => {
if vis.is_accessible_from(module, self.tcx) {
- self.update(def_id, level);
+ self.update(def_id, macro_ev, Level::Reachable);
}
}
@@ -588,7 +637,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
let item = self.tcx.hir().expect_item(def_id);
if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }, _) = item.kind {
if vis.is_accessible_from(module, self.tcx) {
- self.update(def_id, level);
+ self.update(def_id, macro_ev, Level::Reachable);
}
}
}
@@ -599,26 +648,24 @@ impl<'tcx> EmbargoVisitor<'tcx> {
// the module, however may be reachable.
DefKind::Mod => {
if vis.is_accessible_from(module, self.tcx) {
- self.update_macro_reachable(def_id, module);
+ self.update_macro_reachable(def_id, module, macro_ev);
}
}
DefKind::Struct | DefKind::Union => {
// While structs and unions have type privacy, their fields do not.
- if vis.is_public() {
- let item = self.tcx.hir().expect_item(def_id);
- if let hir::ItemKind::Struct(ref struct_def, _)
- | hir::ItemKind::Union(ref struct_def, _) = item.kind
- {
- for field in struct_def.fields() {
- let field_vis = self.tcx.local_visibility(field.def_id);
- if field_vis.is_accessible_from(module, self.tcx) {
- self.reach(field.def_id, level).ty();
- }
+ let item = self.tcx.hir().expect_item(def_id);
+ if let hir::ItemKind::Struct(ref struct_def, _)
+ | hir::ItemKind::Union(ref struct_def, _) = item.kind
+ {
+ for field in struct_def.fields() {
+ let field_vis = self.tcx.local_visibility(field.def_id);
+ if field_vis.is_accessible_from(module, self.tcx) {
+ self.reach(field.def_id, macro_ev).ty();
}
- } else {
- bug!("item {:?} with DefKind {:?}", item, def_kind);
}
+ } else {
+ bug!("item {:?} with DefKind {:?}", item, def_kind);
}
}
@@ -662,14 +709,16 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
}
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
- let item_level = match item.kind {
+ let item_ev = match item.kind {
hir::ItemKind::Impl { .. } => {
- let impl_level = Option::<Level>::of_impl(
+ let impl_ev = Option::<EffectiveVisibility>::of_impl(
item.owner_id.def_id,
self.tcx,
&self.effective_visibilities,
);
- self.update(item.owner_id.def_id, impl_level)
+
+ self.update_eff_vis(item.owner_id.def_id, impl_ev, None, Level::Direct);
+ impl_ev
}
_ => self.get(item.owner_id.def_id),
};
@@ -678,38 +727,35 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
match item.kind {
hir::ItemKind::Enum(ref def, _) => {
for variant in def.variants {
- let variant_level = self.update(variant.def_id, item_level);
+ self.update(variant.def_id, item_ev, Level::Reachable);
+ let variant_ev = self.get(variant.def_id);
if let Some(ctor_def_id) = variant.data.ctor_def_id() {
- self.update(ctor_def_id, item_level);
+ self.update(ctor_def_id, variant_ev, Level::Reachable);
}
for field in variant.data.fields() {
- self.update(field.def_id, variant_level);
+ self.update(field.def_id, variant_ev, Level::Reachable);
}
}
}
hir::ItemKind::Impl(ref impl_) => {
for impl_item_ref in impl_.items {
- if impl_.of_trait.is_some()
- || self.tcx.visibility(impl_item_ref.id.owner_id).is_public()
- {
- self.update(impl_item_ref.id.owner_id.def_id, item_level);
- }
+ let def_id = impl_item_ref.id.owner_id.def_id;
+ let nominal_vis =
+ impl_.of_trait.is_none().then(|| self.tcx.local_visibility(def_id));
+ self.update_eff_vis(def_id, item_ev, nominal_vis, Level::Direct);
}
}
hir::ItemKind::Trait(.., trait_item_refs) => {
for trait_item_ref in trait_item_refs {
- self.update(trait_item_ref.id.owner_id.def_id, item_level);
+ self.update(trait_item_ref.id.owner_id.def_id, item_ev, Level::Reachable);
}
}
hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
if let Some(ctor_def_id) = def.ctor_def_id() {
- self.update(ctor_def_id, item_level);
+ self.update(ctor_def_id, item_ev, Level::Reachable);
}
for field in def.fields() {
- let vis = self.tcx.visibility(field.def_id);
- if vis.is_public() {
- self.update(field.def_id, item_level);
- }
+ self.update(field.def_id, item_ev, Level::Reachable);
}
}
hir::ItemKind::Macro(ref macro_def, _) => {
@@ -717,9 +763,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
}
hir::ItemKind::ForeignMod { items, .. } => {
for foreign_item in items {
- if self.tcx.visibility(foreign_item.id.owner_id).is_public() {
- self.update(foreign_item.id.owner_id.def_id, item_level);
- }
+ self.update(foreign_item.id.owner_id.def_id, item_ev, Level::Reachable);
}
}
@@ -754,8 +798,11 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
// FIXME: This is some serious pessimization intended to workaround deficiencies
// in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
// reachable if they are returned via `impl Trait`, even from private functions.
- let exist_level = cmp::max(item_level, Some(Level::ReachableThroughImplTrait));
- self.reach(item.owner_id.def_id, exist_level).generics().predicates().ty();
+ let exist_ev = Some(EffectiveVisibility::from_vis(ty::Visibility::Public));
+ self.reach_through_impl_trait(item.owner_id.def_id, exist_ev)
+ .generics()
+ .predicates()
+ .ty();
}
}
// Visit everything.
@@ -763,17 +810,18 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
| hir::ItemKind::Static(..)
| hir::ItemKind::Fn(..)
| hir::ItemKind::TyAlias(..) => {
- if item_level.is_some() {
- self.reach(item.owner_id.def_id, item_level).generics().predicates().ty();
+ if item_ev.is_some() {
+ self.reach(item.owner_id.def_id, item_ev).generics().predicates().ty();
}
}
hir::ItemKind::Trait(.., trait_item_refs) => {
- if item_level.is_some() {
- self.reach(item.owner_id.def_id, item_level).generics().predicates();
+ if item_ev.is_some() {
+ self.reach(item.owner_id.def_id, item_ev).generics().predicates();
for trait_item_ref in trait_item_refs {
let tcx = self.tcx;
- let mut reach = self.reach(trait_item_ref.id.owner_id.def_id, item_level);
+ let mut reach = self.reach(trait_item_ref.id.owner_id.def_id, item_ev);
+
reach.generics().predicates();
if trait_item_ref.kind == AssocItemKind::Type
@@ -787,23 +835,24 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
}
}
hir::ItemKind::TraitAlias(..) => {
- if item_level.is_some() {
- self.reach(item.owner_id.def_id, item_level).generics().predicates();
+ if item_ev.is_some() {
+ self.reach(item.owner_id.def_id, item_ev).generics().predicates();
}
}
// Visit everything except for private impl items.
hir::ItemKind::Impl(ref impl_) => {
- if item_level.is_some() {
- self.reach(item.owner_id.def_id, item_level)
+ if item_ev.is_some() {
+ self.reach(item.owner_id.def_id, item_ev)
.generics()
.predicates()
.ty()
.trait_ref();
for impl_item_ref in impl_.items {
- let impl_item_level = self.get(impl_item_ref.id.owner_id.def_id);
- if impl_item_level.is_some() {
- self.reach(impl_item_ref.id.owner_id.def_id, impl_item_level)
+ let impl_item_ev = self.get(impl_item_ref.id.owner_id.def_id);
+
+ if impl_item_ev.is_some() {
+ self.reach(impl_item_ref.id.owner_id.def_id, impl_item_ev)
.generics()
.predicates()
.ty();
@@ -814,23 +863,23 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
// Visit everything, but enum variants have their own levels.
hir::ItemKind::Enum(ref def, _) => {
- if item_level.is_some() {
- self.reach(item.owner_id.def_id, item_level).generics().predicates();
+ if item_ev.is_some() {
+ self.reach(item.owner_id.def_id, item_ev).generics().predicates();
}
for variant in def.variants {
- let variant_level = self.get(variant.def_id);
- if variant_level.is_some() {
+ let variant_ev = self.get(variant.def_id);
+ if variant_ev.is_some() {
for field in variant.data.fields() {
- self.reach(field.def_id, variant_level).ty();
+ self.reach(field.def_id, variant_ev).ty();
}
// Corner case: if the variant is reachable, but its
// enum is not, make the enum reachable as well.
- self.reach(item.owner_id.def_id, variant_level).ty();
+ self.reach(item.owner_id.def_id, variant_ev).ty();
}
if let Some(ctor_def_id) = variant.data.ctor_def_id() {
- let ctor_level = self.get(ctor_def_id);
- if ctor_level.is_some() {
- self.reach(item.owner_id.def_id, ctor_level).ty();
+ let ctor_ev = self.get(ctor_def_id);
+ if ctor_ev.is_some() {
+ self.reach(item.owner_id.def_id, ctor_ev).ty();
}
}
}
@@ -838,9 +887,9 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
// Visit everything, but foreign items have their own levels.
hir::ItemKind::ForeignMod { items, .. } => {
for foreign_item in items {
- let foreign_item_level = self.get(foreign_item.id.owner_id.def_id);
- if foreign_item_level.is_some() {
- self.reach(foreign_item.id.owner_id.def_id, foreign_item_level)
+ let foreign_item_ev = self.get(foreign_item.id.owner_id.def_id);
+ if foreign_item_ev.is_some() {
+ self.reach(foreign_item.id.owner_id.def_id, foreign_item_ev)
.generics()
.predicates()
.ty();
@@ -849,36 +898,32 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
}
// Visit everything except for private fields.
hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
- if item_level.is_some() {
- self.reach(item.owner_id.def_id, item_level).generics().predicates();
+ if item_ev.is_some() {
+ self.reach(item.owner_id.def_id, item_ev).generics().predicates();
for field in struct_def.fields() {
- let field_level = self.get(field.def_id);
- if field_level.is_some() {
- self.reach(field.def_id, field_level).ty();
+ let field_ev = self.get(field.def_id);
+ if field_ev.is_some() {
+ self.reach(field.def_id, field_ev).ty();
}
}
}
if let Some(ctor_def_id) = struct_def.ctor_def_id() {
- let ctor_level = self.get(ctor_def_id);
- if ctor_level.is_some() {
- self.reach(item.owner_id.def_id, ctor_level).ty();
+ let ctor_ev = self.get(ctor_def_id);
+ if ctor_ev.is_some() {
+ self.reach(item.owner_id.def_id, ctor_ev).ty();
}
}
}
}
- let orig_level = mem::replace(&mut self.prev_level, item_level);
intravisit::walk_item(self, item);
- self.prev_level = orig_level;
}
fn visit_block(&mut self, b: &'tcx hir::Block<'tcx>) {
// Blocks can have public items, for example impls, but they always
// start as completely private regardless of publicity of a function,
// constant, type, field, etc., in which this block resides.
- let orig_level = mem::replace(&mut self.prev_level, None);
intravisit::walk_block(self, b);
- self.prev_level = orig_level;
}
}
@@ -932,11 +977,7 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx>
_descr: &dyn fmt::Display,
) -> ControlFlow<Self::BreakTy> {
if let Some(def_id) = def_id.as_local() {
- if let (ty::Visibility::Public, _) | (_, Some(Level::ReachableThroughImplTrait)) =
- (self.tcx().visibility(def_id.to_def_id()), self.level)
- {
- self.ev.update(def_id, self.level);
- }
+ self.ev.update_eff_vis(def_id, self.effective_vis, None, self.level);
}
ControlFlow::Continue(())
}
@@ -2164,7 +2205,6 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
tcx,
effective_visibilities: tcx.resolutions(()).effective_visibilities.clone(),
macro_reachable: Default::default(),
- prev_level: Some(Level::Direct),
changed: false,
};
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 87067189a77..7393bdb388a 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -199,7 +199,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
let tcx = self.r.tcx;
self.changed |= self.import_effective_visibilities.update(
binding,
- nominal_vis,
+ Some(nominal_vis),
|| cheap_private_vis.unwrap_or_else(|| self.r.private_vis_import(binding)),
inherited_eff_vis,
parent_id.level(),
@@ -213,7 +213,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
let tcx = self.r.tcx;
self.changed |= self.def_effective_visibilities.update(
def_id,
- nominal_vis,
+ Some(nominal_vis),
|| cheap_private_vis.unwrap_or_else(|| self.r.private_vis_def(def_id)),
inherited_eff_vis,
parent_id.level(),
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 520ec9abcf0..2568aaf34f3 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -310,6 +310,7 @@ where
/// Real logic of both `Flatten` and `FlatMap` which simply delegate to
/// this type.
#[derive(Clone, Debug)]
+#[unstable(feature = "trusted_len", issue = "37572")]
struct FlattenCompat<I, U> {
iter: Fuse<I>,
frontiter: Option<U>,
@@ -463,6 +464,7 @@ where
}
}
+#[unstable(feature = "trusted_len", issue = "37572")]
impl<I, U> Iterator for FlattenCompat<I, U>
where
I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
@@ -577,6 +579,7 @@ where
}
}
+#[unstable(feature = "trusted_len", issue = "37572")]
impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
where
I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
@@ -646,6 +649,7 @@ where
}
}
+#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<const N: usize, I, T> TrustedLen
for FlattenCompat<I, <[T; N] as IntoIterator>::IntoIter>
where
@@ -653,6 +657,7 @@ where
{
}
+#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<'a, const N: usize, I, T> TrustedLen
for FlattenCompat<I, <&'a [T; N] as IntoIterator>::IntoIter>
where
@@ -660,6 +665,7 @@ where
{
}
+#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<'a, const N: usize, I, T> TrustedLen
for FlattenCompat<I, <&'a mut [T; N] as IntoIterator>::IntoIter>
where
diff --git a/tests/ui/lint/issue-111359.rs b/tests/ui/lint/issue-111359.rs
new file mode 100644
index 00000000000..e390c3fc565
--- /dev/null
+++ b/tests/ui/lint/issue-111359.rs
@@ -0,0 +1,27 @@
+#[deny(missing_debug_implementations)]
+#[deny(missing_copy_implementations)]
+
+mod priv_mod {
+ use std::convert::TryFrom;
+
+ pub struct BarPub;
+ //~^ ERROR type does not implement `Debug`; consider adding `#[derive(Debug)]` or a manual implementation
+ //~| ERROR type could implement `Copy`; consider adding `impl Copy`
+ struct BarPriv;
+
+ impl<'a> TryFrom<BarPriv> for u8 {
+ type Error = ();
+ fn try_from(o: BarPriv) -> Result<Self, ()> {
+ unimplemented!()
+ }
+ }
+
+ impl<'a> TryFrom<BarPub> for u8 {
+ type Error = ();
+ fn try_from(o: BarPub) -> Result<Self, ()> {
+ unimplemented!()
+ }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/lint/issue-111359.stderr b/tests/ui/lint/issue-111359.stderr
new file mode 100644
index 00000000000..2296d8413d6
--- /dev/null
+++ b/tests/ui/lint/issue-111359.stderr
@@ -0,0 +1,26 @@
+error: type does not implement `Debug`; consider adding `#[derive(Debug)]` or a manual implementation
+ --> $DIR/issue-111359.rs:7:5
+ |
+LL | pub struct BarPub;
+ | ^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-111359.rs:1:8
+ |
+LL | #[deny(missing_debug_implementations)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type could implement `Copy`; consider adding `impl Copy`
+ --> $DIR/issue-111359.rs:7:5
+ |
+LL | pub struct BarPub;
+ | ^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-111359.rs:2:8
+ |
+LL | #[deny(missing_copy_implementations)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+