item_like_imports: Allow single imports with a given visibility
to reexport some (but not all) namespaces with less visibility.
This commit is contained in:
parent
aad1f3cbf3
commit
c56a5afd4d
@ -285,13 +285,20 @@ impl<'a> Resolver<'a> {
|
|||||||
// return the corresponding binding defined by the import directive.
|
// return the corresponding binding defined by the import directive.
|
||||||
fn import(&mut self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
|
fn import(&mut self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
|
||||||
-> NameBinding<'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()
|
||||||
|
};
|
||||||
|
|
||||||
NameBinding {
|
NameBinding {
|
||||||
kind: NameBindingKind::Import {
|
kind: NameBindingKind::Import {
|
||||||
binding: binding,
|
binding: binding,
|
||||||
directive: directive,
|
directive: directive,
|
||||||
},
|
},
|
||||||
span: directive.span,
|
span: directive.span,
|
||||||
vis: directive.vis.get(),
|
vis: vis,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,22 +604,44 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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, ¬e_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) {
|
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) => {
|
(Ok(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
|
||||||
let msg = format!("`{}` is private, and cannot be reexported", name);
|
reexport_error();
|
||||||
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, ¬e_msg)
|
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(_, Ok(binding)) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
|
(_, Ok(binding)) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
|
||||||
if binding.is_extern_crate() {
|
if binding.is_extern_crate() {
|
||||||
let msg = format!("extern crate `{}` is private, and cannot be reexported \
|
extern_crate_lint();
|
||||||
(error E0364), consider declaring with `pub`",
|
|
||||||
name);
|
|
||||||
self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
|
|
||||||
} else {
|
} else {
|
||||||
struct_span_err!(self.session, directive.span, E0365,
|
struct_span_err!(self.session, directive.span, E0365,
|
||||||
"`{}` is private, and cannot be reexported", name)
|
"`{}` is private, and cannot be reexported", name)
|
||||||
|
37
src/test/compile-fail/imports/reexports.rs
Normal file
37
src/test/compile-fail/imports/reexports.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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).
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod c {
|
||||||
|
// Test that `foo` is not reexported.
|
||||||
|
use b::a::foo::S; //~ ERROR `foo`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Reference in New Issue
Block a user