Skip to content

Commit c56a5af

Browse files
committed
item_like_imports: Allow single imports with a given visibility
to reexport some (but not all) namespaces with less visibility.
1 parent aad1f3c commit c56a5af

File tree

2 files changed

+77
-11
lines changed

2 files changed

+77
-11
lines changed

src/librustc_resolve/resolve_imports.rs

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -285,13 +285,20 @@ impl<'a> Resolver<'a> {
285285
// return the corresponding binding defined by the import directive.
286286
fn import(&mut self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
287287
-> NameBinding<'a> {
288+
let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) ||
289+
!directive.is_glob() && binding.is_extern_crate() { // c.f. `PRIVATE_IN_PUBLIC`
290+
directive.vis.get()
291+
} else {
292+
binding.pseudo_vis()
293+
};
294+
288295
NameBinding {
289296
kind: NameBindingKind::Import {
290297
binding: binding,
291298
directive: directive,
292299
},
293300
span: directive.span,
294-
vis: directive.vis.get(),
301+
vis: vis,
295302
}
296303
}
297304

@@ -597,22 +604,44 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
597604
}
598605
}
599606

607+
let session = self.session;
608+
let reexport_error = || {
609+
let msg = format!("`{}` is private, and cannot be reexported", name);
610+
let note_msg =
611+
format!("consider marking `{}` as `pub` in the imported module", name);
612+
struct_span_err!(session, directive.span, E0364, "{}", &msg)
613+
.span_note(directive.span, &note_msg)
614+
.emit();
615+
};
616+
617+
let extern_crate_lint = || {
618+
let msg = format!("extern crate `{}` is private, and cannot be reexported \
619+
(error E0364), consider declaring with `pub`",
620+
name);
621+
session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
622+
};
623+
600624
match (value_result, type_result) {
625+
// With `#![feature(item_like_imports)]`, all namespaces
626+
// must be re-exported with extra visibility for an error to occur.
627+
(Ok(value_binding), Ok(type_binding)) if self.new_import_semantics => {
628+
let vis = directive.vis.get();
629+
if !value_binding.pseudo_vis().is_at_least(vis, self) &&
630+
!type_binding.pseudo_vis().is_at_least(vis, self) {
631+
reexport_error();
632+
} else if type_binding.is_extern_crate() &&
633+
!type_binding.vis.is_at_least(vis, self) {
634+
extern_crate_lint();
635+
}
636+
}
637+
601638
(Ok(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
602-
let msg = format!("`{}` is private, and cannot be reexported", name);
603-
let note_msg =
604-
format!("consider marking `{}` as `pub` in the imported module", name);
605-
struct_span_err!(self.session, directive.span, E0364, "{}", &msg)
606-
.span_note(directive.span, &note_msg)
607-
.emit();
639+
reexport_error();
608640
}
609641

610642
(_, Ok(binding)) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
611643
if binding.is_extern_crate() {
612-
let msg = format!("extern crate `{}` is private, and cannot be reexported \
613-
(error E0364), consider declaring with `pub`",
614-
name);
615-
self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
644+
extern_crate_lint();
616645
} else {
617646
struct_span_err!(self.session, directive.span, E0365,
618647
"`{}` is private, and cannot be reexported", name)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(item_like_imports)]
12+
13+
mod a {
14+
fn foo() {}
15+
mod foo {}
16+
17+
mod a {
18+
pub use super::foo; //~ ERROR cannot be reexported
19+
}
20+
}
21+
22+
mod b {
23+
pub fn foo() {}
24+
mod foo { pub struct S; }
25+
26+
pub mod a {
27+
pub use super::foo; // This is OK since the value `foo` is visible enough.
28+
fn f(_: foo::S) {} // `foo` is imported in the type namespace (but not `pub` reexported).
29+
}
30+
}
31+
32+
mod c {
33+
// Test that `foo` is not reexported.
34+
use b::a::foo::S; //~ ERROR `foo`
35+
}
36+
37+
fn main() {}

0 commit comments

Comments
 (0)