1
Fork 0

Rollup merge of #90628 - ken-matsui:clarify-error-messages-caused-by-reexporting-pub-crate-visibility-to-outside, r=oli-obk

Clarify error messages caused by re-exporting `pub(crate)` visibility to outside

This PR clarifies error messages and suggestions caused by re-exporting pub(crate) visibility outside the crate.

Here is a small example ([Rust Playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=e2cd0bd4422d4f20e6522dcbad167d3b)):

```rust
mod m {
    pub(crate) enum E {}
}
pub use m::E;

fn main() {}
```

This code is compiled to:

```
error[E0365]: `E` is private, and cannot be re-exported
 --> prog.rs:4:9
  |
4 | pub use m::E;
  |         ^^^^ re-export of private `E`
  |
  = note: consider declaring type or module `E` with `pub`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0365`.
```

However, enum `E` is actually public to the crate, not private totally—nevertheless, rustc treats `pub(crate)` and private visibility as the same on the error messages. They are not clear and should be segmented distinctly.

By applying changes in this PR, the error message below will be the following message that would be clearer:

```
error[E0365]: `E` is only public to inside of the crate, and cannot be re-exported outside
 --> prog.rs:4:9
  |
4 | pub use m::E;
  |         ^^^^ re-export of crate public `E`
  |
  = note: consider declaring type or module `E` with `pub`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0365`.
```
This commit is contained in:
Matthias Krüger 2021-11-20 10:21:13 +01:00 committed by GitHub
commit 81f3ae8997
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 334 additions and 32 deletions

View file

@ -1180,11 +1180,17 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let mut reexport_error = None;
let mut any_successful_reexport = false;
let mut crate_private_reexport = false;
self.r.per_ns(|this, ns| {
if let Ok(binding) = source_bindings[ns].get() {
let vis = import.vis.get();
if !binding.vis.is_at_least(vis, &*this) {
reexport_error = Some((ns, binding));
if let ty::Visibility::Restricted(binding_def_id) = binding.vis {
if binding_def_id.is_top_level_module() {
crate_private_reexport = true;
}
}
} else {
any_successful_reexport = true;
}
@ -1207,24 +1213,34 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
import.span,
&msg,
);
} else if ns == TypeNS {
struct_span_err!(
self.r.session,
import.span,
E0365,
"`{}` is private, and cannot be re-exported",
ident
)
.span_label(import.span, format!("re-export of private `{}`", ident))
.note(&format!("consider declaring type or module `{}` with `pub`", ident))
.emit();
} else {
let msg = format!("`{}` is private, and cannot be re-exported", ident);
let note_msg =
format!("consider marking `{}` as `pub` in the imported module", ident,);
struct_span_err!(self.r.session, import.span, E0364, "{}", &msg)
.span_note(import.span, &note_msg)
.emit();
let error_msg = if crate_private_reexport {
format!(
"`{}` is only public within the crate, and cannot be re-exported outside",
ident
)
} else {
format!("`{}` is private, and cannot be re-exported", ident)
};
if ns == TypeNS {
let label_msg = if crate_private_reexport {
format!("re-export of crate public `{}`", ident)
} else {
format!("re-export of private `{}`", ident)
};
struct_span_err!(self.r.session, import.span, E0365, "{}", error_msg)
.span_label(import.span, label_msg)
.note(&format!("consider declaring type or module `{}` with `pub`", ident))
.emit();
} else {
let note_msg =
format!("consider marking `{}` as `pub` in the imported module", ident);
struct_span_err!(self.r.session, import.span, E0364, "{}", error_msg)
.span_note(import.span, &note_msg)
.emit();
}
}
}