From 0603a731f40015849e82d4f00c90899bb01898ec Mon Sep 17 00:00:00 2001 From: Kyle Simpson Date: Fri, 20 Jul 2018 14:12:57 +0100 Subject: [PATCH 1/7] Add test case for #50865 regression. --- .../auxiliary/lib.rs | 24 +++++++++++++++++++ .../issue-50865-private-impl-trait/main.rs | 20 ++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/test/run-pass/issue-50865-private-impl-trait/auxiliary/lib.rs create mode 100644 src/test/run-pass/issue-50865-private-impl-trait/main.rs diff --git a/src/test/run-pass/issue-50865-private-impl-trait/auxiliary/lib.rs b/src/test/run-pass/issue-50865-private-impl-trait/auxiliary/lib.rs new file mode 100644 index 0000000000000..bf4f13360be16 --- /dev/null +++ b/src/test/run-pass/issue-50865-private-impl-trait/auxiliary/lib.rs @@ -0,0 +1,24 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "lib"] + +pub fn bar

( // Error won't happen if "bar" is not generic + _baz: P, +) { + hide_foo()(); +} + +fn hide_foo() -> impl Fn() { // Error won't happen if "iterate" hasn't impl Trait or has generics + foo +} + +fn foo() { // Error won't happen if "foo" isn't used in "iterate" or has generics +} diff --git a/src/test/run-pass/issue-50865-private-impl-trait/main.rs b/src/test/run-pass/issue-50865-private-impl-trait/main.rs new file mode 100644 index 0000000000000..7e92e1079812c --- /dev/null +++ b/src/test/run-pass/issue-50865-private-impl-trait/main.rs @@ -0,0 +1,20 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:lib.rs + +// Regression test for #50865. +// FIXME: explain. + +extern crate lib; + +fn main() { + lib::bar(()); // Error won't happen if bar is called from same crate +} From f285876b435e29e309659197790b82ad880650a0 Mon Sep 17 00:00:00 2001 From: Kyle Simpson Date: Fri, 10 Aug 2018 10:32:52 +0100 Subject: [PATCH 2/7] Logging for rustc_privacy. --- src/librustc_privacy/Cargo.toml | 1 + src/librustc_privacy/lib.rs | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/librustc_privacy/Cargo.toml b/src/librustc_privacy/Cargo.toml index 62eab40f3ec9a..b7af9ec809e54 100644 --- a/src/librustc_privacy/Cargo.toml +++ b/src/librustc_privacy/Cargo.toml @@ -9,6 +9,7 @@ path = "lib.rs" crate-type = ["dylib"] [dependencies] +log = { version = "0.4", features = ["release_max_level_info", "std"] } rustc = { path = "../librustc" } rustc_typeck = { path = "../librustc_typeck" } syntax = { path = "../libsyntax" } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index ab383287773a1..d2b6d0bb967cf 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -18,6 +18,7 @@ #![recursion_limit="256"] +#[macro_use] extern crate log; #[macro_use] extern crate rustc; #[macro_use] extern crate syntax; extern crate rustc_typeck; @@ -147,6 +148,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } fn visit_item(&mut self, item: &'tcx hir::Item) { + debug!("Walked item {:?}", item); let inherited_item_level = match item.node { // Impls inherit level from their types and traits hir::ItemKind::Impl(..) => { @@ -164,6 +166,9 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) | hir::ItemKind::Existential(..) | hir::ItemKind::Ty(..) | hir::ItemKind::Union(..) | hir::ItemKind::Use(..) => { + if let hir::ItemKind::Fn(ref _decl, ref _header, ref _generics, ref _body) = item.node { + debug!("Walked function"); + } if item.vis.node.is_pub() { self.prev_level } else { None } } }; @@ -171,6 +176,8 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { // Update level of the item itself let item_level = self.update(item.id, inherited_item_level); + debug!("believed to be: {:?}", item_level); + // Update levels of nested things match item.node { hir::ItemKind::Enum(ref def, _) => { @@ -1737,6 +1744,8 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } visitor.update(ast::CRATE_NODE_ID, Some(AccessLevel::Public)); + debug!("access levels after embargo: {:?}", &visitor.access_levels); + { let mut visitor = ObsoleteVisiblePrivateTypesVisitor { tcx, @@ -1766,6 +1775,8 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor)); } + debug!("final access levels: {:?}", &visitor.access_levels); + Lrc::new(visitor.access_levels) } From 00b260691fc85020c2b58d263665fe4808b72ac1 Mon Sep 17 00:00:00 2001 From: Kyle Simpson Date: Mon, 20 Aug 2018 22:39:47 +0100 Subject: [PATCH 3/7] Mark impl Trait Functions as reachable. (Fixes #50865) --- src/Cargo.lock | 1 + src/librustc/middle/privacy.rs | 2 ++ src/librustc/middle/reachable.rs | 2 ++ src/librustc_privacy/lib.rs | 16 +++++++++++----- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 8299dea1c4b0e..4b76080e500ab 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2237,6 +2237,7 @@ dependencies = [ name = "rustc_privacy" version = "0.0.0" dependencies = [ + "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_typeck 0.0.0", diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index e2de0b6bd013d..c7e093380fac3 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -21,6 +21,8 @@ use syntax::ast::NodeId; // Accessibility levels, sorted in ascending order #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum AccessLevel { + // Superset of Reachable used to mark impl Trait items. + // ReachableFromImplTrait, // Exported items + items participating in various kinds of public interfaces, // but not directly nameable. For example, if function `fn f() -> T {...}` is // public, then type `T` is reachable. Its values can be obtained by other crates diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index a504697008ef4..e05b4e79f2e81 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -446,6 +446,8 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> // Step 2: Mark all symbols that the symbols on the worklist touch. reachable_context.propagate(); + debug!("Inline reachability shows: {:?}", reachable_context.reachable_symbols); + // Return the set of reachable symbols. ReachableSet(Lrc::new(reachable_context.reachable_symbols)) } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index d2b6d0bb967cf..fea0e3a7435eb 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -159,16 +159,22 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::ForeignMod(..) => { self.prev_level } + // Impl trait return types mark their parent function. + // It (and its children) are revisited if the change applies. + hir::ItemKind::Existential(ref ty_data) => { + if let Some(impl_trait_fn) = ty_data.impl_trait_fn { + if let Some(node_id) = self.tcx.hir.as_local_node_id(impl_trait_fn) { + self.update(node_id, Some(AccessLevel::Reachable)); + } + } + if item.vis.node.is_pub() { self.prev_level } else { None } + } // Other `pub` items inherit levels from parents hir::ItemKind::Const(..) | hir::ItemKind::Enum(..) | hir::ItemKind::ExternCrate(..) | hir::ItemKind::GlobalAsm(..) | hir::ItemKind::Fn(..) | hir::ItemKind::Mod(..) | hir::ItemKind::Static(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) | - hir::ItemKind::Existential(..) | hir::ItemKind::Ty(..) | hir::ItemKind::Union(..) | hir::ItemKind::Use(..) => { - if let hir::ItemKind::Fn(ref _decl, ref _header, ref _generics, ref _body) = item.node { - debug!("Walked function"); - } if item.vis.node.is_pub() { self.prev_level } else { None } } }; @@ -176,7 +182,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { // Update level of the item itself let item_level = self.update(item.id, inherited_item_level); - debug!("believed to be: {:?}", item_level); + debug!("Its privacy is believed to be: {:?}", item_level); // Update levels of nested things match item.node { From 81684bf1aafa6e83e796c2581e4c7fe518a90fda Mon Sep 17 00:00:00 2001 From: Kyle Simpson Date: Tue, 21 Aug 2018 00:11:59 +0100 Subject: [PATCH 4/7] New AccessLevel and accompanying propagation. --- src/librustc/ich/impls_ty.rs | 1 + src/librustc/middle/privacy.rs | 5 +++-- src/librustc_privacy/lib.rs | 14 ++++++++------ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index a3600c0480017..365434062a303 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -1086,6 +1086,7 @@ impl_stable_hash_for!(enum traits::Reveal { }); impl_stable_hash_for!(enum ::middle::privacy::AccessLevel { + ReachableFromImplTrait, Reachable, Exported, Public diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index c7e093380fac3..39ddaca8925e0 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -22,7 +22,7 @@ use syntax::ast::NodeId; #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum AccessLevel { // Superset of Reachable used to mark impl Trait items. - // ReachableFromImplTrait, + ReachableFromImplTrait, // Exported items + items participating in various kinds of public interfaces, // but not directly nameable. For example, if function `fn f() -> T {...}` is // public, then type `T` is reachable. Its values can be obtained by other crates @@ -42,7 +42,8 @@ pub struct AccessLevels { impl AccessLevels { pub fn is_reachable(&self, id: Id) -> bool { - self.map.contains_key(&id) + // self.map.contains_key(&id) + self.map.get(&id) >= Some(&AccessLevel::Reachable) } pub fn is_exported(&self, id: Id) -> bool { self.map.get(&id) >= Some(&AccessLevel::Exported) diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index fea0e3a7435eb..b6b56cad83906 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -84,6 +84,7 @@ struct EmbargoVisitor<'a, 'tcx: 'a> { } struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> { + access_level: Option, item_def_id: DefId, ev: &'b mut EmbargoVisitor<'a, 'tcx>, } @@ -134,6 +135,7 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { fn reach<'b>(&'b mut self, item_id: ast::NodeId) -> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { ReachEverythingInTheInterfaceVisitor { + access_level: self.prev_level.map(|l| l.min(AccessLevel::Reachable)), item_def_id: self.tcx.hir.local_def_id(item_id), ev: self, } @@ -164,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::Existential(ref ty_data) => { if let Some(impl_trait_fn) = ty_data.impl_trait_fn { if let Some(node_id) = self.tcx.hir.as_local_node_id(impl_trait_fn) { - self.update(node_id, Some(AccessLevel::Reachable)); + self.update(node_id, Some(AccessLevel::ReachableFromImplTrait)); } } if item.vis.node.is_pub() { self.prev_level } else { None } @@ -240,6 +242,9 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::ExternCrate(..) => {} } + let orig_level = self.prev_level; + self.prev_level = item_level; + // Mark all items in interfaces of reachable items as reachable match item.node { // The interface is empty @@ -337,9 +342,6 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } - let orig_level = self.prev_level; - self.prev_level = item_level; - intravisit::walk_item(self, item); self.prev_level = orig_level; @@ -475,7 +477,7 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) { if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(trait_ref.def_id) { let item = self.ev.tcx.hir.expect_item(node_id); - self.ev.update(item.id, Some(AccessLevel::Reachable)); + self.ev.update(item.id, self.access_level); } } } @@ -496,7 +498,7 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b if let Some(def_id) = ty_def_id { if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(def_id) { - self.ev.update(node_id, Some(AccessLevel::Reachable)); + self.ev.update(node_id, self.access_level); } } From 54b096a79913ad23b320d1f878046ae31e460061 Mon Sep 17 00:00:00 2001 From: Kyle Simpson Date: Tue, 21 Aug 2018 01:16:29 +0100 Subject: [PATCH 5/7] Fixes for code review. --- src/librustc/middle/privacy.rs | 1 - .../issue-50865-private-impl-trait/auxiliary/lib.rs | 2 +- src/test/run-pass/issue-50865-private-impl-trait/main.rs | 9 +++++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 39ddaca8925e0..70fed9af92128 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -42,7 +42,6 @@ pub struct AccessLevels { impl AccessLevels { pub fn is_reachable(&self, id: Id) -> bool { - // self.map.contains_key(&id) self.map.get(&id) >= Some(&AccessLevel::Reachable) } pub fn is_exported(&self, id: Id) -> bool { diff --git a/src/test/run-pass/issue-50865-private-impl-trait/auxiliary/lib.rs b/src/test/run-pass/issue-50865-private-impl-trait/auxiliary/lib.rs index bf4f13360be16..306256d53d38c 100644 --- a/src/test/run-pass/issue-50865-private-impl-trait/auxiliary/lib.rs +++ b/src/test/run-pass/issue-50865-private-impl-trait/auxiliary/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/test/run-pass/issue-50865-private-impl-trait/main.rs b/src/test/run-pass/issue-50865-private-impl-trait/main.rs index 7e92e1079812c..c58e36c65425f 100644 --- a/src/test/run-pass/issue-50865-private-impl-trait/main.rs +++ b/src/test/run-pass/issue-50865-private-impl-trait/main.rs @@ -1,4 +1,4 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -11,7 +11,12 @@ // aux-build:lib.rs // Regression test for #50865. -// FIXME: explain. +// When using generics or specifying the type directly, this example +// codegens `foo` internally. However, when using a private `impl Trait` +// function which references another private item, `foo` (in this case) +// wouldn't be codegenned until main.rs used `bar`, as with impl Trait +// it is not cast to `fn()` automatically to satisfy e.g. +// `fn foo() -> fn() { ... }`. extern crate lib; From 3536359ad8b02933018a7b26f0ad6c3ed6f0c50e Mon Sep 17 00:00:00 2001 From: Kyle Simpson Date: Tue, 21 Aug 2018 01:50:20 +0100 Subject: [PATCH 6/7] Further fixes. --- src/librustc_privacy/lib.rs | 4 ++-- src/test/run-pass/issue-50865-private-impl-trait/main.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index b6b56cad83906..f6b843bbac52b 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -150,7 +150,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } fn visit_item(&mut self, item: &'tcx hir::Item) { - debug!("Walked item {:?}", item); + debug!("visit_item({:?})", item); let inherited_item_level = match item.node { // Impls inherit level from their types and traits hir::ItemKind::Impl(..) => { @@ -184,7 +184,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { // Update level of the item itself let item_level = self.update(item.id, inherited_item_level); - debug!("Its privacy is believed to be: {:?}", item_level); + debug!("item_level = {:?}", item_level); // Update levels of nested things match item.node { diff --git a/src/test/run-pass/issue-50865-private-impl-trait/main.rs b/src/test/run-pass/issue-50865-private-impl-trait/main.rs index c58e36c65425f..bc347edf8a765 100644 --- a/src/test/run-pass/issue-50865-private-impl-trait/main.rs +++ b/src/test/run-pass/issue-50865-private-impl-trait/main.rs @@ -16,7 +16,7 @@ // function which references another private item, `foo` (in this case) // wouldn't be codegenned until main.rs used `bar`, as with impl Trait // it is not cast to `fn()` automatically to satisfy e.g. -// `fn foo() -> fn() { ... }`. +// `fn foo() -> fn() { ... }`. extern crate lib; From 85a05d1815217584c096ebc9d64b3a547b667f48 Mon Sep 17 00:00:00 2001 From: Kyle Simpson Date: Thu, 23 Aug 2018 10:52:08 +0100 Subject: [PATCH 7/7] Light restructuring. --- src/Cargo.lock | 1 - src/librustc_privacy/Cargo.toml | 1 - src/librustc_privacy/lib.rs | 34 +++++++++++++-------------------- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 4b76080e500ab..8299dea1c4b0e 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2237,7 +2237,6 @@ dependencies = [ name = "rustc_privacy" version = "0.0.0" dependencies = [ - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_typeck 0.0.0", diff --git a/src/librustc_privacy/Cargo.toml b/src/librustc_privacy/Cargo.toml index b7af9ec809e54..62eab40f3ec9a 100644 --- a/src/librustc_privacy/Cargo.toml +++ b/src/librustc_privacy/Cargo.toml @@ -9,7 +9,6 @@ path = "lib.rs" crate-type = ["dylib"] [dependencies] -log = { version = "0.4", features = ["release_max_level_info", "std"] } rustc = { path = "../librustc" } rustc_typeck = { path = "../librustc_typeck" } syntax = { path = "../libsyntax" } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index f6b843bbac52b..6b19f4b779107 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -18,7 +18,6 @@ #![recursion_limit="256"] -#[macro_use] extern crate log; #[macro_use] extern crate rustc; #[macro_use] extern crate syntax; extern crate rustc_typeck; @@ -150,7 +149,6 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } fn visit_item(&mut self, item: &'tcx hir::Item) { - debug!("visit_item({:?})", item); let inherited_item_level = match item.node { // Impls inherit level from their types and traits hir::ItemKind::Impl(..) => { @@ -161,21 +159,12 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::ForeignMod(..) => { self.prev_level } - // Impl trait return types mark their parent function. - // It (and its children) are revisited if the change applies. - hir::ItemKind::Existential(ref ty_data) => { - if let Some(impl_trait_fn) = ty_data.impl_trait_fn { - if let Some(node_id) = self.tcx.hir.as_local_node_id(impl_trait_fn) { - self.update(node_id, Some(AccessLevel::ReachableFromImplTrait)); - } - } - if item.vis.node.is_pub() { self.prev_level } else { None } - } // Other `pub` items inherit levels from parents hir::ItemKind::Const(..) | hir::ItemKind::Enum(..) | hir::ItemKind::ExternCrate(..) | hir::ItemKind::GlobalAsm(..) | hir::ItemKind::Fn(..) | hir::ItemKind::Mod(..) | hir::ItemKind::Static(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) | + hir::ItemKind::Existential(..) | hir::ItemKind::Ty(..) | hir::ItemKind::Union(..) | hir::ItemKind::Use(..) => { if item.vis.node.is_pub() { self.prev_level } else { None } } @@ -184,8 +173,6 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { // Update level of the item itself let item_level = self.update(item.id, inherited_item_level); - debug!("item_level = {:?}", item_level); - // Update levels of nested things match item.node { hir::ItemKind::Enum(ref def, _) => { @@ -230,7 +217,15 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } } - hir::ItemKind::Existential(..) | + // Impl trait return types mark their parent function. + // It (and its children) are revisited if the change applies. + hir::ItemKind::Existential(ref ty_data) => { + if let Some(impl_trait_fn) = ty_data.impl_trait_fn { + if let Some(node_id) = self.tcx.hir.as_local_node_id(impl_trait_fn) { + self.update(node_id, Some(AccessLevel::ReachableFromImplTrait)); + } + } + } hir::ItemKind::Use(..) | hir::ItemKind::Static(..) | hir::ItemKind::Const(..) | @@ -242,8 +237,9 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::ExternCrate(..) => {} } - let orig_level = self.prev_level; - self.prev_level = item_level; + // Store this node's access level here to propagate the correct + // reachability level through interfaces and children. + let orig_level = replace(&mut self.prev_level, item_level); // Mark all items in interfaces of reachable items as reachable match item.node { @@ -1752,8 +1748,6 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } visitor.update(ast::CRATE_NODE_ID, Some(AccessLevel::Public)); - debug!("access levels after embargo: {:?}", &visitor.access_levels); - { let mut visitor = ObsoleteVisiblePrivateTypesVisitor { tcx, @@ -1783,8 +1777,6 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor)); } - debug!("final access levels: {:?}", &visitor.access_levels); - Lrc::new(visitor.access_levels) }