提交 8aeb15ac 编写于 作者: B bors 提交者: GitHub

Auto merge of #35894 - jseyfried:new_import_semantics, r=nrc

Implement RFC 1560 behind `#![feature(item_like_imports)]`

This implements https://github.com/rust-lang/rfcs/pull/1560 (cc #35120) behind the `item_like_imports` feature gate.

The [RFC text](https://github.com/rust-lang/rfcs/blob/master/text/1560-name-resolution.md#changes-to-name-resolution-rules) describes the changes to name resolution enabled by `#![feature(item_like_imports)` in detail. To summarize,
 - Items and named imports shadow glob imports.
 - Multiple globs can import the same name if the name is unused or the imports are shadowed.
 - Multiple globs can import the same name if the imports are of the same item (following re-exports).
  - The visibility of such a name is the maximum visibility of the imports.
  - Equivalently, adding a glob import will never reduce the visibility of a name, nor will removing one increase it.
 - Non-prelude private imports can be used wherever we currently allow private items to be used.
  - Prelude-imported names are unaffected, i.e. they continue to be usable only in lexical scopes.
 - Globs import all visible names, not just public names.
  - Equivalently, glob importing from an ancestor module imports all of the ancestor's names, and glob importing from other modules is unchanged.

r? @nrc
......@@ -26,6 +26,8 @@
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::ty::{self, VariantKind};
use std::cell::Cell;
use syntax::ast::Name;
use syntax::attr;
use syntax::parse::token;
......@@ -81,7 +83,6 @@ fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
/// Constructs the reduced graph for one item.
fn build_reduced_graph_for_item(&mut self, item: &Item) {
let parent = self.current_module;
let parent_vis = self.current_vis;
let name = item.ident.name;
let sp = item.span;
let vis = self.resolve_visibility(&item.vis);
......@@ -177,7 +178,10 @@ fn build_reduced_graph_for_item(&mut self, item: &Item) {
}
}
ViewPathGlob(_) => {
let subclass = GlobImport { is_prelude: is_prelude };
let subclass = GlobImport {
is_prelude: is_prelude,
max_vis: Cell::new(ty::Visibility::PrivateExternal),
};
let span = view_path.span;
self.add_import_directive(module_path, subclass, span, item.id, vis);
}
......@@ -204,7 +208,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item) {
ItemKind::Mod(..) => {
let parent_link = ModuleParentLink(parent, name);
let def = Def::Mod(self.definitions.local_def_id(item.id));
let module = self.new_module(parent_link, Some(def), false);
let module = self.new_module(parent_link, Some(def), Some(item.id));
module.no_implicit_prelude.set({
parent.no_implicit_prelude.get() ||
attr::contains_name(&item.attrs, "no_implicit_prelude")
......@@ -214,7 +218,6 @@ fn build_reduced_graph_for_item(&mut self, item: &Item) {
// Descend into the module.
self.current_module = module;
self.current_vis = ty::Visibility::Restricted(item.id);
}
ItemKind::ForeignMod(..) => {}
......@@ -243,7 +246,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item) {
ItemKind::Enum(ref enum_definition, _) => {
let parent_link = ModuleParentLink(parent, name);
let def = Def::Enum(self.definitions.local_def_id(item.id));
let module = self.new_module(parent_link, Some(def), false);
let module = self.new_module(parent_link, Some(def), parent.normal_ancestor_id);
self.define(parent, name, TypeNS, (module, sp, vis));
for variant in &(*enum_definition).variants {
......@@ -285,7 +288,8 @@ fn build_reduced_graph_for_item(&mut self, item: &Item) {
// Add all the items within to a new module.
let parent_link = ModuleParentLink(parent, name);
let def = Def::Trait(def_id);
let module_parent = self.new_module(parent_link, Some(def), false);
let module_parent =
self.new_module(parent_link, Some(def), parent.normal_ancestor_id);
self.define(parent, name, TypeNS, (module_parent, sp, vis));
// Add the names of all the items to the trait info.
......@@ -312,7 +316,6 @@ fn build_reduced_graph_for_item(&mut self, item: &Item) {
visit::walk_item(&mut BuildReducedGraphVisitor { resolver: self }, item);
self.current_module = parent;
self.current_vis = parent_vis;
}
// Constructs the reduced graph for one variant. Variants exist in the
......@@ -363,7 +366,7 @@ fn build_reduced_graph_for_block(&mut self, block: &Block) {
block_id);
let parent_link = BlockParentLink(parent, block_id);
let new_module = self.new_module(parent_link, None, false);
let new_module = self.new_module(parent_link, None, parent.normal_ancestor_id);
self.module_map.insert(block_id, new_module);
self.current_module = new_module; // Descend into the block.
}
......@@ -395,7 +398,7 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, xcd
debug!("(building reduced graph for external crate) building module {} {:?}",
name, vis);
let parent_link = ModuleParentLink(parent, name);
let module = self.new_module(parent_link, Some(def), true);
let module = self.new_module(parent_link, Some(def), None);
let _ = self.try_define(parent, name, TypeNS, (module, DUMMY_SP, vis));
}
Def::Variant(_, variant_id) => {
......@@ -437,7 +440,7 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, xcd
}
let parent_link = ModuleParentLink(parent, name);
let module = self.new_module(parent_link, Some(def), true);
let module = self.new_module(parent_link, Some(def), None);
let _ = self.try_define(parent, name, TypeNS, (module, DUMMY_SP, vis));
}
Def::TyAlias(..) | Def::AssociatedTy(..) => {
......
此差异已折叠。
......@@ -27,7 +27,7 @@
use syntax::ast::{NodeId, Name};
use syntax::util::lev_distance::find_best_match_for_name;
use syntax_pos::{Span, DUMMY_SP};
use syntax_pos::Span;
use std::cell::{Cell, RefCell};
......@@ -52,7 +52,11 @@ pub enum ImportDirectiveSubclass<'a> {
value_result: Cell<Result<&'a NameBinding<'a>, Determinacy>>,
type_result: Cell<Result<&'a NameBinding<'a>, Determinacy>>,
},
GlobImport { is_prelude: bool },
GlobImport {
is_prelude: bool,
max_vis: Cell<ty::Visibility>, // The visibility of the greatest reexport.
// n.b. `max_vis` is only used in `finalize_import` to check for reexport errors.
},
}
impl<'a> ImportDirectiveSubclass<'a> {
......@@ -167,8 +171,10 @@ pub fn resolve_name_in_module(&mut self,
_ => return Failed(None), // This happens when there is a cycle of imports
};
let new_import_semantics = self.new_import_semantics;
let is_disallowed_private_import = |binding: &NameBinding| {
!allow_private_imports && !binding.is_pseudo_public() && binding.is_import()
!new_import_semantics && !allow_private_imports && // disallowed
binding.vis != ty::Visibility::Public && binding.is_import() // non-`pub` import
};
if let Some(span) = record_used {
......@@ -176,7 +182,9 @@ pub fn resolve_name_in_module(&mut self,
if is_disallowed_private_import(binding) {
return Failed(None);
}
self.record_use(name, ns, binding);
if self.record_use(name, ns, binding, span) {
return Success(self.dummy_binding);
}
if !self.is_accessible(binding.vis) {
self.privacy_errors.push(PrivacyError(span, name, binding));
}
......@@ -274,7 +282,7 @@ pub fn add_import_directive(&mut self,
}
// We don't add prelude imports to the globs since they only affect lexical scopes,
// which are not relevant to import resolution.
GlobImport { is_prelude: true } => {}
GlobImport { is_prelude: true, .. } => {}
GlobImport { .. } => self.current_module.globs.borrow_mut().push(directive),
}
}
......@@ -283,13 +291,26 @@ pub fn add_import_directive(&mut self,
// return the corresponding binding defined by the import directive.
fn import(&mut self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
-> NameBinding<'a> {
let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) ||
!directive.is_glob() && binding.is_extern_crate() { // c.f. `PRIVATE_IN_PUBLIC`
directive.vis.get()
} else {
binding.pseudo_vis()
};
if let GlobImport { ref max_vis, .. } = directive.subclass {
if vis == directive.vis.get() || vis.is_at_least(max_vis.get(), self) {
max_vis.set(vis)
}
}
NameBinding {
kind: NameBindingKind::Import {
binding: binding,
directive: directive,
},
span: directive.span,
vis: directive.vis.get(),
vis: vis,
}
}
......@@ -299,10 +320,28 @@ pub fn try_define<T>(&mut self, module: Module<'a>, name: Name, ns: Namespace, b
where T: ToNameBinding<'a>
{
let binding = self.arenas.alloc_name_binding(binding.to_name_binding());
self.update_resolution(module, name, ns, |_, resolution| {
self.update_resolution(module, name, ns, |this, resolution| {
if let Some(old_binding) = resolution.binding {
if binding.is_glob_import() {
resolution.duplicate_globs.push(binding);
if !this.new_import_semantics || !old_binding.is_glob_import() {
resolution.duplicate_globs.push(binding);
} else if binding.def() != old_binding.def() {
resolution.binding = Some(this.arenas.alloc_name_binding(NameBinding {
kind: NameBindingKind::Ambiguity {
b1: old_binding,
b2: binding,
},
vis: if old_binding.vis.is_at_least(binding.vis, this) {
old_binding.vis
} else {
binding.vis
},
span: old_binding.span,
}));
} else if !old_binding.vis.is_at_least(binding.vis, this) {
// We are glob-importing the same item but with greater visibility.
resolution.binding = Some(binding);
}
} else if old_binding.is_glob_import() {
resolution.duplicate_globs.push(old_binding);
resolution.binding = Some(binding);
......@@ -324,23 +363,29 @@ fn update_resolution<T, F>(&mut self, module: Module<'a>, name: Name, ns: Namesp
{
// Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
// during which the resolution might end up getting re-defined via a glob cycle.
let (new_binding, t) = {
let (binding, t) = {
let mut resolution = &mut *self.resolution(module, name, ns).borrow_mut();
let was_known = resolution.binding().is_some();
let old_binding = resolution.binding();
let t = f(self, resolution);
if was_known { return t; }
match resolution.binding() {
Some(binding) => (binding, t),
_ if !self.new_import_semantics && old_binding.is_some() => return t,
None => return t,
Some(binding) => match old_binding {
Some(old_binding) if old_binding as *const _ == binding as *const _ => return t,
_ => (binding, t),
}
}
};
// Define `new_binding` in `module`s glob importers.
if new_binding.is_importable() && new_binding.is_pseudo_public() {
for directive in module.glob_importers.borrow_mut().iter() {
let imported_binding = self.import(new_binding, directive);
// Define `binding` in `module`s glob importers.
for directive in module.glob_importers.borrow_mut().iter() {
if match self.new_import_semantics {
true => self.is_accessible_from(binding.vis, directive.parent),
false => binding.vis == ty::Visibility::Public,
} {
let imported_binding = self.import(binding, directive);
let _ = self.try_define(directive.parent, name, ns, imported_binding);
}
}
......@@ -381,14 +426,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
// remain or unsuccessfully when no forward progress in resolving imports
// is made.
fn set_current_module(&mut self, module: Module<'b>) {
self.current_module = module;
self.current_vis = ty::Visibility::Restricted({
let normal_module = self.get_nearest_normal_module_parent_or_self(module);
self.definitions.as_local_node_id(normal_module.def_id().unwrap()).unwrap()
});
}
/// Resolves all imports for the crate. This method performs the fixed-
/// point iteration.
fn resolve_imports(&mut self) {
......@@ -424,7 +461,7 @@ fn resolve_imports(&mut self) {
errors = true;
let (span, help) = match err {
Some((span, msg)) => (span, msg),
None => (import.span, String::new()),
None => continue,
};
// If the error is a single failed import then create a "fake" import
......@@ -450,13 +487,8 @@ fn resolve_imports(&mut self) {
// failed resolution
fn import_dummy_binding(&mut self, directive: &'b ImportDirective<'b>) {
if let SingleImport { target, .. } = directive.subclass {
let dummy_binding = self.arenas.alloc_name_binding(NameBinding {
kind: NameBindingKind::Def(Def::Err),
span: DUMMY_SP,
vis: ty::Visibility::Public,
});
let dummy_binding = self.dummy_binding;
let dummy_binding = self.import(dummy_binding, directive);
let _ = self.try_define(directive.parent, target, ValueNS, dummy_binding.clone());
let _ = self.try_define(directive.parent, target, TypeNS, dummy_binding);
}
......@@ -472,7 +504,7 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResul
names_to_string(&directive.module_path),
module_to_string(self.current_module));
self.set_current_module(directive.parent);
self.current_module = directive.parent;
let module = if let Some(module) = directive.imported_module.get() {
module
......@@ -548,7 +580,7 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResul
}
fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResult<()> {
self.set_current_module(directive.parent);
self.current_module = directive.parent;
let ImportDirective { ref module_path, span, .. } = *directive;
let module_result = self.resolve_module_path(&module_path, DontUseLexicalScope, Some(span));
......@@ -566,12 +598,23 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResu
let msg = "Cannot glob-import a module into itself.".into();
return Failed(Some((directive.span, msg)));
}
GlobImport { .. } => return Success(()),
GlobImport { is_prelude, ref max_vis } => {
if !is_prelude &&
max_vis.get() != ty::Visibility::PrivateExternal && // Allow empty globs.
!max_vis.get().is_at_least(directive.vis.get(), self) {
let msg = "A non-empty glob must import something with the glob's visibility";
self.session.span_err(directive.span, msg);
}
return Success(());
}
};
for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] {
if let Ok(binding) = result {
self.record_use(name, ns, binding);
if self.record_use(name, ns, binding, directive.span) {
self.resolution(module, name, ns).borrow_mut().binding =
Some(self.dummy_binding);
}
}
}
......@@ -608,22 +651,44 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResu
}
}
let session = self.session;
let reexport_error = || {
let msg = format!("`{}` is private, and cannot be reexported", name);
let note_msg =
format!("consider marking `{}` as `pub` in the imported module", name);
struct_span_err!(session, directive.span, E0364, "{}", &msg)
.span_note(directive.span, &note_msg)
.emit();
};
let extern_crate_lint = || {
let msg = format!("extern crate `{}` is private, and cannot be reexported \
(error E0364), consider declaring with `pub`",
name);
session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
};
match (value_result, type_result) {
// With `#![feature(item_like_imports)]`, all namespaces
// must be re-exported with extra visibility for an error to occur.
(Ok(value_binding), Ok(type_binding)) if self.new_import_semantics => {
let vis = directive.vis.get();
if !value_binding.pseudo_vis().is_at_least(vis, self) &&
!type_binding.pseudo_vis().is_at_least(vis, self) {
reexport_error();
} else if type_binding.is_extern_crate() &&
!type_binding.vis.is_at_least(vis, self) {
extern_crate_lint();
}
}
(Ok(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
let msg = format!("`{}` is private, and cannot be reexported", name);
let note_msg =
format!("consider marking `{}` as `pub` in the imported module", name);
struct_span_err!(self.session, directive.span, E0364, "{}", &msg)
.span_note(directive.span, &note_msg)
.emit();
reexport_error();
}
(_, Ok(binding)) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
if binding.is_extern_crate() {
let msg = format!("extern crate `{}` is private, and cannot be reexported \
(error E0364), consider declaring with `pub`",
name);
self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
extern_crate_lint();
} else {
struct_span_err!(self.session, directive.span, E0365,
"`{}` is private, and cannot be reexported", name)
......@@ -639,9 +704,9 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResu
// Record what this import resolves to for later uses in documentation,
// this may resolve to either a value or a type, but for documentation
// purposes it's good enough to just favor one over the other.
let def = match type_result.ok().and_then(NameBinding::def) {
let def = match type_result.ok().map(NameBinding::def) {
Some(def) => def,
None => value_result.ok().and_then(NameBinding::def).unwrap(),
None => value_result.ok().map(NameBinding::def).unwrap(),
};
let path_resolution = PathResolution::new(def);
self.def_map.insert(directive.id, path_resolution);
......@@ -656,11 +721,10 @@ fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
if let Some(Def::Trait(_)) = module.def {
self.session.span_err(directive.span, "items in traits are not importable.");
}
if module.def_id() == directive.parent.def_id() {
return;
} else if let GlobImport { is_prelude: true } = directive.subclass {
} else if module.def_id() == directive.parent.def_id() {
return;
} else if let GlobImport { is_prelude: true, .. } = directive.subclass {
self.prelude = Some(module);
return;
}
......@@ -674,7 +738,8 @@ fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
resolution.borrow().binding().map(|binding| (*name, binding))
}).collect::<Vec<_>>();
for ((name, ns), binding) in bindings {
if binding.is_importable() && binding.is_pseudo_public() {
if binding.pseudo_vis() == ty::Visibility::Public ||
self.new_import_semantics && self.is_accessible(binding.vis) {
let imported_binding = self.import(binding, directive);
let _ = self.try_define(directive.parent, name, ns, imported_binding);
}
......@@ -702,20 +767,23 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
};
// Report conflicts
for duplicate_glob in resolution.duplicate_globs.iter() {
// FIXME #31337: We currently allow items to shadow glob-imported re-exports.
if !binding.is_import() {
if let NameBindingKind::Import { binding, .. } = duplicate_glob.kind {
if binding.is_import() { continue }
if !self.new_import_semantics {
for duplicate_glob in resolution.duplicate_globs.iter() {
// FIXME #31337: We currently allow items to shadow glob-imported re-exports.
if !binding.is_import() {
if let NameBindingKind::Import { binding, .. } = duplicate_glob.kind {
if binding.is_import() { continue }
}
}
}
self.report_conflict(module, name, ns, duplicate_glob, binding);
self.report_conflict(module, name, ns, duplicate_glob, binding);
}
}
if binding.vis == ty::Visibility::Public &&
(binding.is_import() || binding.is_extern_crate()) {
if let Some(def) = binding.def() {
let def = binding.def();
if def != Def::Err {
reexports.push(Export { name: name, def_id: def.def_id() });
}
}
......
......@@ -285,7 +285,10 @@ pub fn new() -> Features {
// Allows the sysV64 ABI to be specified on all platforms
// instead of just the platforms on which it is the C ABI
(active, abi_sysv64, "1.13.0", Some(36167))
(active, abi_sysv64, "1.13.0", Some(36167)),
// Use the import semantics from RFC 1560.
(active, item_like_imports, "1.13.0", Some(35120))
);
declare_features! (
......
......@@ -8,6 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: failed to resolve. Use of undeclared type or module `thing`
fn main() {
let foo = thing::len(Vec::new());
//~^ ERROR failed to resolve. Use of undeclared type or module `thing`
fn main() { let foo = thing::len(Vec::new()); }
let foo = foo::bar::baz();
//~^ ERROR failed to resolve. Use of undeclared type or module `foo`
}
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(item_like_imports)]
mod a {
pub fn foo() {}
}
mod b {
pub fn foo() {}
}
mod c {
pub use a::foo;
}
mod d {
use a::foo; //~ NOTE previous import
use a::foo; //~ ERROR `foo` has already been imported
//~| NOTE already imported
}
mod e {
pub use a::*;
pub use c::*; // ok
}
mod f {
pub use a::*; //~ NOTE `foo` could resolve to the name imported here
pub use b::*; //~ NOTE `foo` could also resolve to the name imported here
}
mod g {
pub use a::*; //~ NOTE `foo` could resolve to the name imported here
pub use f::*; //~ NOTE `foo` could also resolve to the name imported here
}
fn main() {
e::foo();
f::foo(); //~ ERROR `foo` is ambiguous
//~| NOTE Consider adding an explicit import of `foo` to disambiguate
g::foo(); //~ ERROR `foo` is ambiguous
//~| NOTE Consider adding an explicit import of `foo` to disambiguate
}
mod ambiguous_module_errors {
pub mod m1 { pub use super::m1 as foo; }
pub mod m2 { pub use super::m2 as foo; }
use self::m1::*; //~ NOTE
//~| NOTE
use self::m2::*; //~ NOTE
//~| NOTE
use self::foo::bar; //~ ERROR `foo` is ambiguous
//~| NOTE
fn f() {
foo::bar(); //~ ERROR `foo` is ambiguous
//~| NOTE
}
}
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(item_like_imports)]
mod a {
fn foo() {}
mod foo {}
mod a {
pub use super::foo; //~ ERROR cannot be reexported
pub use super::*; //~ ERROR must import something with the glob's visibility
}
}
mod b {
pub fn foo() {}
mod foo { pub struct S; }
pub mod a {
pub use super::foo; // This is OK since the value `foo` is visible enough.
fn f(_: foo::S) {} // `foo` is imported in the type namespace (but not `pub` reexported).
}
pub mod b {
pub use super::*; // This is also OK since the value `foo` is visible enough.
fn f(_: foo::S) {} // Again, the module `foo` is imported (but not `pub` reexported).
}
}
mod c {
// Test that `foo` is not reexported.
use b::a::foo::S; //~ ERROR `foo`
use b::b::foo::S as T; //~ ERROR `foo`
}
fn main() {}
......@@ -10,10 +10,10 @@
// ensure that the ThreadRng isn't/doesn't become accidentally sendable.
use std::rand; //~ ERROR: module `rand` is private
use std::__rand::ThreadRng;
fn test_send<S: Send>() {}
pub fn main() {
test_send::<rand::ThreadRng>();
test_send::<ThreadRng>(); //~ ERROR std::marker::Send` is not satisfied
}
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-pretty : (#23623) problems when ending with // comments
#![feature(item_like_imports)]
#![allow(unused)]
// Like other items, private imports can be imported and used non-lexically in paths.
mod a {
use a as foo;
use self::foo::foo as bar;
mod b {
use super::bar;
}
}
mod foo { pub fn f() {} }
mod bar { pub fn f() {} }
pub fn f() -> bool { true }
// Items and explicit imports shadow globs.
fn g() {
use foo::*;
use bar::*;
fn f() -> bool { true }
let _: bool = f();
}
fn h() {
use foo::*;
use bar::*;
use f;
let _: bool = f();
}
// Here, there appears to be shadowing but isn't because of namespaces.
mod b {
use foo::*; // This imports `f` in the value namespace.
use super::b as f; // This imports `f` only in the type namespace,
fn test() { self::f(); } // so the glob isn't shadowed.
}
// Here, there is shadowing in one namespace, but not the other.
mod c {
mod test {
pub fn f() {}
pub mod f {}
}
use self::test::*; // This glob-imports `f` in both namespaces.
mod f { pub fn f() {} } // This shadows the glob only in the value namespace.
fn test() {
self::f(); // Check that the glob-imported value isn't shadowed.
self::f::f(); // Check that the glob-imported module is shadowed.
}
}
// Unused names can be ambiguous.
mod d {
pub use foo::*; // This imports `f` in the value namespace.
pub use bar::*; // This also imports `f` in the value namespace.
}
mod e {
pub use d::*; // n.b. Since `e::f` is not used, this is not considered to be a use of `d::f`.
}
fn main() {}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册