From 2ec0e85305e69d7f6e1bc0c704a6566ad38232a4 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 22 Jan 2019 18:51:54 +0530 Subject: [PATCH 1/5] Print a slightly clearer message when failing to spawn a thread --- src/libstd/thread/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index a55b32c08a303..eb8e0c1c8ac66 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -607,7 +607,7 @@ impl Builder { pub fn spawn(f: F) -> JoinHandle where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static { - Builder::new().spawn(f).unwrap() + Builder::new().spawn(f).expect("failed to spawn thread") } /// Gets a handle to the thread that invokes it. From 0cf97042d1317630e619b13a1b416f3b7794fb2a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 23 Jan 2019 12:05:00 +0100 Subject: [PATCH 2/5] Fix invalid background color --- src/librustdoc/html/static/themes/dark.css | 4 ---- src/librustdoc/html/static/themes/light.css | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 2cd1a8580890c..61392f1ce0f31 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -419,10 +419,6 @@ kbd { color: #ccc; } -.impl-items code { - background-color: rgba(0, 0, 0, 0); -} - #sidebar-toggle { background-color: #565656; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 4cf35f64d19a4..de6d847a30c77 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -414,10 +414,6 @@ kbd { color: #999; } -.impl-items code { - background-color: rgba(0, 0, 0, 0); -} - #sidebar-toggle { background-color: #F1F1F1; } From c375333362bd1b5f006f6d627ff129c2c54d620c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 26 Jan 2019 16:29:34 +0300 Subject: [PATCH 3/5] Pretty print `$crate` as `crate` or `crate_name` in more cases --- src/librustc_resolve/macros.rs | 10 +++++----- src/librustc_resolve/resolve_imports.rs | 5 +---- src/libsyntax/ext/base.rs | 16 ++-------------- src/libsyntax/ext/expand.rs | 7 +++---- src/test/pretty/dollar-crate.pp | 18 ++++++++++++++++++ src/test/pretty/dollar-crate.rs | 7 +++++++ 6 files changed, 36 insertions(+), 27 deletions(-) create mode 100644 src/test/pretty/dollar-crate.pp create mode 100644 src/test/pretty/dollar-crate.rs diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 286f9a758830b..e552795260465 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -15,7 +15,7 @@ use syntax::ast::{self, Ident}; use syntax::attr; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Determinacy}; -use syntax::ext::base::{Annotatable, MacroKind, SyntaxExtension}; +use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; use syntax::ext::hygiene::{self, Mark}; use syntax::ext::tt::macro_rules; @@ -127,9 +127,9 @@ impl<'a> base::Resolver for Resolver<'a> { mark } - fn resolve_dollar_crates(&mut self, annotatable: &Annotatable) { - pub struct ResolveDollarCrates<'a, 'b: 'a> { - pub resolver: &'a mut Resolver<'b>, + fn resolve_dollar_crates(&mut self, fragment: &AstFragment) { + struct ResolveDollarCrates<'a, 'b: 'a> { + resolver: &'a mut Resolver<'b> } impl<'a> Visitor<'a> for ResolveDollarCrates<'a, '_> { fn visit_ident(&mut self, ident: Ident) { @@ -144,7 +144,7 @@ impl<'a> base::Resolver for Resolver<'a> { fn visit_mac(&mut self, _: &ast::Mac) {} } - annotatable.visit_with(&mut ResolveDollarCrates { resolver: self }); + fragment.visit_with(&mut ResolveDollarCrates { resolver: self }); } fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment, diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index fd55897522bf7..9a04c9d60b868 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -537,11 +537,8 @@ impl<'a> Resolver<'a> { primary_binding: &'a NameBinding<'a>, secondary_binding: &'a NameBinding<'a>) -> &'a NameBinding<'a> { self.arenas.alloc_name_binding(NameBinding { - kind: primary_binding.kind.clone(), ambiguity: Some((secondary_binding, kind)), - vis: primary_binding.vis, - span: primary_binding.span, - expansion: primary_binding.expansion, + ..primary_binding.clone() }) } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 2793754e1033a..09e7e57f78cfa 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -14,7 +14,6 @@ use parse::token; use ptr::P; use smallvec::SmallVec; use symbol::{keywords, Ident, Symbol}; -use visit::Visitor; use ThinVec; use rustc_data_structures::fx::FxHashMap; @@ -136,17 +135,6 @@ impl Annotatable { _ => false, } } - - pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { - match self { - Annotatable::Item(item) => visitor.visit_item(item), - Annotatable::TraitItem(trait_item) => visitor.visit_trait_item(trait_item), - Annotatable::ImplItem(impl_item) => visitor.visit_impl_item(impl_item), - Annotatable::ForeignItem(foreign_item) => visitor.visit_foreign_item(foreign_item), - Annotatable::Stmt(stmt) => visitor.visit_stmt(stmt), - Annotatable::Expr(expr) => visitor.visit_expr(expr), - } - } } // A more flexible ItemDecorator. @@ -742,7 +730,7 @@ pub trait Resolver { fn next_node_id(&mut self) -> ast::NodeId; fn get_module_scope(&mut self, id: ast::NodeId) -> Mark; - fn resolve_dollar_crates(&mut self, annotatable: &Annotatable); + fn resolve_dollar_crates(&mut self, fragment: &AstFragment); fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment, derives: &[Mark]); fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc); @@ -776,7 +764,7 @@ impl Resolver for DummyResolver { fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID } fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() } - fn resolve_dollar_crates(&mut self, _annotatable: &Annotatable) {} + fn resolve_dollar_crates(&mut self, _fragment: &AstFragment) {} fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment, _derives: &[Mark]) {} fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc) {} diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 9369e66cf83da..6e327c6a9dade 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -443,6 +443,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { /// prepares data for resolving paths of macro invocations. fn collect_invocations(&mut self, fragment: AstFragment, derives: &[Mark]) -> (AstFragment, Vec) { + // Resolve `$crate`s in the fragment for pretty-printing. + self.cx.resolver.resolve_dollar_crates(&fragment); + let (fragment_with_placeholders, invocations) = { let mut collector = InvocationCollector { cfg: StripUnconfigured { @@ -574,8 +577,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Some(invoc.fragment_kind.expect_from_annotatables(items)) } AttrProcMacro(ref mac, ..) => { - // Resolve `$crate`s in case we have to go though stringification. - self.cx.resolver.resolve_dollar_crates(&item); self.gate_proc_macro_attr_item(attr.span, &item); let item_tok = TokenTree::Token(DUMMY_SP, Token::interpolated(match item { Annotatable::Item(item) => token::NtItem(item), @@ -917,8 +918,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { match *ext { ProcMacroDerive(ref ext, ..) => { - // Resolve `$crate`s in case we have to go though stringification. - self.cx.resolver.resolve_dollar_crates(&item); invoc.expansion_data.mark.set_expn_info(expn_info); let span = span.with_ctxt(self.cx.backtrace()); let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this diff --git a/src/test/pretty/dollar-crate.pp b/src/test/pretty/dollar-crate.pp new file mode 100644 index 0000000000000..3d2d949be2b2e --- /dev/null +++ b/src/test/pretty/dollar-crate.pp @@ -0,0 +1,18 @@ +#![feature(prelude_import)] +#![no_std] +#[prelude_import] +use ::std::prelude::v1::*; +#[macro_use] +extern crate std; +// pretty-compare-only +// pretty-mode:expanded +// pp-exact:dollar-crate.pp + +fn main() { + { + ::std::io::_print(::std::fmt::Arguments::new_v1(&["rust\n"], + &match () { + () => [], + })); + }; +} diff --git a/src/test/pretty/dollar-crate.rs b/src/test/pretty/dollar-crate.rs new file mode 100644 index 0000000000000..e46bc7f4859a7 --- /dev/null +++ b/src/test/pretty/dollar-crate.rs @@ -0,0 +1,7 @@ +// pretty-compare-only +// pretty-mode:expanded +// pp-exact:dollar-crate.pp + +fn main() { + println!("rust"); +} From 5e6702117223b61057957ca2593f03e3f45ccd8a Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Fri, 25 Jan 2019 14:29:47 -0500 Subject: [PATCH 4/5] add typo suggestion to unknown attribute error --- src/librustc_resolve/macros.rs | 70 +++++++++++++++++-- src/test/ui/issues/issue-49074.stderr | 2 +- .../ui/macros/macro-reexport-removed.stderr | 2 +- .../ui/proc-macro/derive-still-gated.stderr | 2 +- src/test/ui/suggestions/attribute-typos.rs | 13 ++++ .../ui/suggestions/attribute-typos.stderr | 27 +++++++ 6 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/suggestions/attribute-typos.rs create mode 100644 src/test/ui/suggestions/attribute-typos.stderr diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index fb5b6c97689d0..78b5518203084 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -19,7 +19,9 @@ use syntax::ext::base::{Annotatable, MacroKind, SyntaxExtension}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; use syntax::ext::hygiene::{self, Mark}; use syntax::ext::tt::macro_rules; -use syntax::feature_gate::{feature_err, is_builtin_attr_name, GateIssue}; +use syntax::feature_gate::{ + feature_err, is_builtin_attr_name, AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES, +}; use syntax::symbol::{Symbol, keywords}; use syntax::visit::Visitor; use syntax::util::lev_distance::find_best_match_for_name; @@ -310,15 +312,18 @@ impl<'a> Resolver<'a> { if !features.rustc_attrs { let msg = "unless otherwise specified, attributes with the prefix \ `rustc_` are reserved for internal compiler diagnostics"; - feature_err(&self.session.parse_sess, "rustc_attrs", path.span, - GateIssue::Language, &msg).emit(); + self.report_unknown_attribute(path.span, &name, msg, "rustc_attrs"); } } else if !features.custom_attribute { let msg = format!("The attribute `{}` is currently unknown to the \ compiler and may have meaning added to it in the \ future", path); - feature_err(&self.session.parse_sess, "custom_attribute", path.span, - GateIssue::Language, &msg).emit(); + self.report_unknown_attribute( + path.span, + &name, + &msg, + "custom_attribute", + ); } } } else { @@ -339,6 +344,61 @@ impl<'a> Resolver<'a> { Ok((def, self.get_macro(def))) } + fn report_unknown_attribute(&self, span: Span, name: &str, msg: &str, feature: &str) { + let mut err = feature_err( + &self.session.parse_sess, + feature, + span, + GateIssue::Language, + &msg, + ); + + let features = self.session.features_untracked(); + + let attr_candidates = BUILTIN_ATTRIBUTES + .iter() + .filter_map(|(name, _, _, gate)| { + if name.starts_with("rustc_") && !features.rustc_attrs { + return None; + } + + match gate { + AttributeGate::Gated(Stability::Unstable, ..) + if self.session.opts.unstable_features.is_nightly_build() => + { + Some(name) + } + AttributeGate::Gated(Stability::Deprecated(..), ..) => Some(name), + AttributeGate::Ungated => Some(name), + _ => None, + } + }) + .map(|name| Symbol::intern(name)) + .chain( + // Add built-in macro attributes as well. + self.builtin_macros.iter().filter_map(|(name, binding)| { + match binding.macro_kind() { + Some(MacroKind::Attr) => Some(*name), + _ => None, + } + }), + ) + .collect::>(); + + let lev_suggestion = find_best_match_for_name(attr_candidates.iter(), &name, None); + + if let Some(suggestion) = lev_suggestion { + err.span_suggestion( + span, + "a built-in attribute with a similar name exists", + suggestion.to_string(), + Applicability::MaybeIncorrect, + ); + } + + err.emit(); + } + pub fn resolve_macro_to_def_inner( &mut self, path: &ast::Path, diff --git a/src/test/ui/issues/issue-49074.stderr b/src/test/ui/issues/issue-49074.stderr index d4648270f2d30..a25d8ee352686 100644 --- a/src/test/ui/issues/issue-49074.stderr +++ b/src/test/ui/issues/issue-49074.stderr @@ -2,7 +2,7 @@ error[E0658]: The attribute `marco_use` is currently unknown to the compiler and --> $DIR/issue-49074.rs:3:3 | LL | #[marco_use] // typo - | ^^^^^^^^^ + | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use` | = help: add #![feature(custom_attribute)] to the crate attributes to enable diff --git a/src/test/ui/macros/macro-reexport-removed.stderr b/src/test/ui/macros/macro-reexport-removed.stderr index 7c3555a92ed8b..6cfec3ee762dd 100644 --- a/src/test/ui/macros/macro-reexport-removed.stderr +++ b/src/test/ui/macros/macro-reexport-removed.stderr @@ -14,7 +14,7 @@ error[E0658]: The attribute `macro_reexport` is currently unknown to the compile --> $DIR/macro-reexport-removed.rs:5:3 | LL | #[macro_reexport(macro_one)] //~ ERROR attribute `macro_reexport` is currently unknown - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_export` | = help: add #![feature(custom_attribute)] to the crate attributes to enable diff --git a/src/test/ui/proc-macro/derive-still-gated.stderr b/src/test/ui/proc-macro/derive-still-gated.stderr index d54a593f78311..ece1b6212914d 100644 --- a/src/test/ui/proc-macro/derive-still-gated.stderr +++ b/src/test/ui/proc-macro/derive-still-gated.stderr @@ -2,7 +2,7 @@ error[E0658]: The attribute `derive_A` is currently unknown to the compiler and --> $DIR/derive-still-gated.rs:8:3 | LL | #[derive_A] //~ ERROR attribute `derive_A` is currently unknown - | ^^^^^^^^ + | ^^^^^^^^ help: a built-in attribute with a similar name exists: `derive` | = help: add #![feature(custom_attribute)] to the crate attributes to enable diff --git a/src/test/ui/suggestions/attribute-typos.rs b/src/test/ui/suggestions/attribute-typos.rs new file mode 100644 index 0000000000000..13c6308b97e85 --- /dev/null +++ b/src/test/ui/suggestions/attribute-typos.rs @@ -0,0 +1,13 @@ +#[deprcated] //~ ERROR E0658 +fn foo() {} //~| HELP a built-in attribute with a similar name exists + //~| SUGGESTION deprecated + //~| HELP add #![feature(custom_attribute)] to the crate attributes to enable + +#[tests] //~ ERROR E0658 +fn bar() {} //~| HELP a built-in attribute with a similar name exists + //~| SUGGESTION test + //~| HELP add #![feature(custom_attribute)] to the crate attributes to enable + +#[rustc_err] //~ ERROR E0658 +fn main() {} //~| HELP add #![feature(rustc_attrs)] to the crate attributes to enable + // don't suggest rustc attributes diff --git a/src/test/ui/suggestions/attribute-typos.stderr b/src/test/ui/suggestions/attribute-typos.stderr new file mode 100644 index 0000000000000..e40da787e96ca --- /dev/null +++ b/src/test/ui/suggestions/attribute-typos.stderr @@ -0,0 +1,27 @@ +error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642) + --> $DIR/attribute-typos.rs:11:3 + | +LL | #[rustc_err] //~ ERROR E0658 + | ^^^^^^^^^ + | + = help: add #![feature(rustc_attrs)] to the crate attributes to enable + +error[E0658]: The attribute `tests` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/attribute-typos.rs:6:3 + | +LL | #[tests] //~ ERROR E0658 + | ^^^^^ help: a built-in attribute with a similar name exists: `test` + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error[E0658]: The attribute `deprcated` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/attribute-typos.rs:1:3 + | +LL | #[deprcated] //~ ERROR E0658 + | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `deprecated` + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. From ad22de402c8a7ce9c866ec3f8eee61264ad3922f Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 26 Jan 2019 20:30:52 +0100 Subject: [PATCH 5/5] Update visibility of intermediate use items. Currently, the target of a use statement will be updated with the visibility of the use statement itself (if the use statement was visible). This commit ensures that if the path to the target item is via another use statement then that intermediate use statement will also have the visibility updated like the target. This silences incorrect `unreachable_pub` lints with inactionable suggestions. --- src/libcore/iter/adapters/mod.rs | 1 + src/libcore/iter/traits/mod.rs | 2 ++ src/librustc/hir/def.rs | 10 ++++++ src/librustc/middle/privacy.rs | 19 +++++++----- src/librustc_privacy/lib.rs | 47 +++++++++++++++++++++++++++-- src/libstd/sys/mod.rs | 1 + src/test/ui/issues/issue-57410-1.rs | 18 +++++++++++ src/test/ui/issues/issue-57410.rs | 17 +++++++++++ 8 files changed, 106 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/issues/issue-57410-1.rs create mode 100644 src/test/ui/issues/issue-57410.rs diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index f8d6bedeace25..bca1b76dbb975 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -11,6 +11,7 @@ mod flatten; mod zip; pub use self::chain::Chain; +#[stable(feature = "rust1", since = "1.0.0")] pub use self::flatten::{FlatMap, Flatten}; pub use self::zip::Zip; pub(crate) use self::zip::TrustedRandomAccess; diff --git a/src/libcore/iter/traits/mod.rs b/src/libcore/iter/traits/mod.rs index 000b9fad70b94..cf3013f423c94 100644 --- a/src/libcore/iter/traits/mod.rs +++ b/src/libcore/iter/traits/mod.rs @@ -5,9 +5,11 @@ mod collect; mod accum; mod marker; +#[stable(feature = "rust1", since = "1.0.0")] pub use self::iterator::Iterator; pub use self::double_ended::DoubleEndedIterator; pub use self::exact_size::ExactSizeIterator; pub use self::collect::{FromIterator, IntoIterator, Extend}; pub use self::accum::{Sum, Product}; +#[stable(feature = "rust1", since = "1.0.0")] pub use self::marker::{FusedIterator, TrustedLen}; diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 8a74c51d3f723..f8f27992b3ea8 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -252,12 +252,14 @@ impl NonMacroAttrKind { } impl Def { + /// Return the `DefId` of this `Def` if it has an id, else panic. pub fn def_id(&self) -> DefId { self.opt_def_id().unwrap_or_else(|| { bug!("attempted .def_id() on invalid def: {:?}", self) }) } + /// Return `Some(..)` with the `DefId` of this `Def` if it has a id, else `None`. pub fn opt_def_id(&self) -> Option { match *self { Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) | @@ -284,6 +286,14 @@ impl Def { } } + /// Return the `DefId` of this `Def` if it represents a module. + pub fn mod_def_id(&self) -> Option { + match *self { + Def::Mod(id) => Some(id), + _ => None, + } + } + /// A human readable name for the def kind ("function", "module", etc.). pub fn kind_name(&self) -> &'static str { match *self { diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 7736d5e795ea0..3baf0f0ea39ff 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -11,16 +11,16 @@ 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. + /// Superset of `AccessLevel::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 - // even if the type itself is not nameable. + /// 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 + /// even if the type itself is not nameable. Reachable, - // Public items + items accessible to other crates with help of `pub use` re-exports + /// Public items + items accessible to other crates with help of `pub use` re-exports Exported, - // Items accessible to other crates directly, without help of re-exports + /// Items accessible to other crates directly, without help of re-exports Public, } @@ -31,12 +31,17 @@ pub struct AccessLevels { } impl AccessLevels { + /// See `AccessLevel::Reachable`. pub fn is_reachable(&self, id: Id) -> bool { self.map.get(&id) >= Some(&AccessLevel::Reachable) } + + /// See `AccessLevel::Exported`. pub fn is_exported(&self, id: Id) -> bool { self.map.get(&id) >= Some(&AccessLevel::Exported) } + + /// See `AccessLevel::Public`. pub fn is_public(&self, id: Id) -> bool { self.map.get(&id) >= Some(&AccessLevel::Public) } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index dcbb9ff4a7576..62730bff6533c 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -436,6 +436,43 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { ev: self, } } + + + /// Given the path segments of a `ItemKind::Use`, then we need + /// to update the visibility of the intermediate use so that it isn't linted + /// by `unreachable_pub`. + /// + /// This isn't trivial as `path.def` has the `DefId` of the eventual target + /// of the use statement not of the next intermediate use statement. + /// + /// To do this, consider the last two segments of the path to our intermediate + /// use statement. We expect the penultimate segment to be a module and the + /// last segment to be the name of the item we are exporting. We can then + /// look at the items contained in the module for the use statement with that + /// name and update that item's visibility. + /// + /// FIXME: This solution won't work with glob imports and doesn't respect + /// namespaces. See . + fn update_visibility_of_intermediate_use_statements(&mut self, segments: &[hir::PathSegment]) { + if let Some([module, segment]) = segments.rchunks_exact(2).next() { + if let Some(item) = module.def + .and_then(|def| def.mod_def_id()) + .and_then(|def_id| self.tcx.hir().as_local_node_id(def_id)) + .map(|module_node_id| self.tcx.hir().expect_item(module_node_id)) + { + if let hir::ItemKind::Mod(m) = &item.node { + for item_id in m.item_ids.as_ref() { + let item = self.tcx.hir().expect_item(item_id.id); + let def_id = self.tcx.hir().local_def_id(item_id.id); + if !self.tcx.hygienic_eq(segment.ident, item.ident, def_id) { continue; } + if let hir::ItemKind::Use(..) = item.node { + self.update(item.id, Some(AccessLevel::Exported)); + } + } + } + } + } + } } impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { @@ -522,8 +559,14 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::ExternCrate(..) => {} // All nested items are checked by `visit_item`. hir::ItemKind::Mod(..) => {} - // Re-exports are handled in `visit_mod`. - hir::ItemKind::Use(..) => {} + // Re-exports are handled in `visit_mod`. However, in order to avoid looping over + // all of the items of a mod in `visit_mod` looking for use statements, we handle + // making sure that intermediate use statements have their visibilities updated here. + hir::ItemKind::Use(ref path, _) => { + if item_level.is_some() { + self.update_visibility_of_intermediate_use_statements(path.segments.as_ref()); + } + } // The interface is empty. hir::ItemKind::GlobalAsm(..) => {} hir::ItemKind::Existential(..) => { diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index f398a2a6225ce..2961328b16096 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -54,6 +54,7 @@ cfg_if! { cfg_if! { if #[cfg(any(unix, target_os = "redox"))] { // On unix we'll document what's already available + #[stable(feature = "rust1", since = "1.0.0")] pub use self::ext as unix_ext; } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32", diff --git a/src/test/ui/issues/issue-57410-1.rs b/src/test/ui/issues/issue-57410-1.rs new file mode 100644 index 0000000000000..dab77bd660ca0 --- /dev/null +++ b/src/test/ui/issues/issue-57410-1.rs @@ -0,0 +1,18 @@ +// compile-pass + +// Originally from #53925. +// Tests that the `unreachable_pub` lint doesn't fire for `pub self::bar::Bar`. + +#![deny(unreachable_pub)] + +mod foo { + mod bar { + pub struct Bar; + } + + pub use self::bar::Bar; +} + +pub use foo::Bar; + +fn main() {} diff --git a/src/test/ui/issues/issue-57410.rs b/src/test/ui/issues/issue-57410.rs new file mode 100644 index 0000000000000..0d697e5619d24 --- /dev/null +++ b/src/test/ui/issues/issue-57410.rs @@ -0,0 +1,17 @@ +// compile-pass + +// Tests that the `unreachable_pub` lint doesn't fire for `pub self::imp::f`. + +#![deny(unreachable_pub)] + +mod m { + mod imp { + pub fn f() {} + } + + pub use self::imp::f; +} + +pub use self::m::f; + +fn main() {}