Skip to content

Commit e708189

Browse files
authored
Rollup merge of #110013 - compiler-errors:non-exhaustive-privacy-reason, r=WaffleLapkin
Label `non_exhaustive` attribute on privacy errors from non-local items Label when an ADT is `non_exhaustive` and we get a privacy error, help with confusion in a case like this: ```rust #[non_exhaustive] pub struct Foo; // other crate let x = Foo; //~^ ERROR unit struct `Foo` is private ```
2 parents 17ed06a + 8ed2dc0 commit e708189

File tree

3 files changed

+38
-11
lines changed

3 files changed

+38
-11
lines changed

compiler/rustc_resolve/src/diagnostics.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -1607,7 +1607,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
16071607
let mut err =
16081608
struct_span_err!(self.tcx.sess, ident.span, E0603, "{} `{}` is private", descr, ident);
16091609
err.span_label(ident.span, &format!("private {}", descr));
1610-
if let Some(span) = ctor_fields_span {
1610+
1611+
let mut non_exhaustive = None;
1612+
// If an ADT is foreign and marked as `non_exhaustive`, then that's
1613+
// probably why we have the privacy error.
1614+
// Otherwise, point out if the struct has any private fields.
1615+
if let Some(def_id) = res.opt_def_id()
1616+
&& !def_id.is_local()
1617+
&& let Some(attr) = self.tcx.get_attr(def_id, sym::non_exhaustive)
1618+
{
1619+
non_exhaustive = Some(attr.span);
1620+
} else if let Some(span) = ctor_fields_span {
16111621
err.span_label(span, "a constructor is private if any of the fields is private");
16121622
if let Res::Def(_, d) = res && let Some(fields) = self.field_visibility_spans.get(&d) {
16131623
err.multipart_suggestion_verbose(
@@ -1656,6 +1666,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
16561666
if !first && binding.vis.is_public() {
16571667
note_span.push_span_label(def_span, "consider importing it directly");
16581668
}
1669+
// Final step in the import chain, point out if the ADT is `non_exhaustive`
1670+
// which is probably why this privacy violation occurred.
1671+
if next_binding.is_none() && let Some(span) = non_exhaustive {
1672+
note_span.push_span_label(
1673+
span,
1674+
format!("cannot be constructed because it is `#[non_exhaustive]`"),
1675+
);
1676+
}
16591677
err.span_note(note_span, &msg);
16601678
}
16611679

tests/ui/rfc-2008-non-exhaustive/struct.stderr

+4-5
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,11 @@ error[E0603]: tuple struct constructor `TupleStruct` is private
1010
LL | let ts_explicit = structs::TupleStruct(640, 480);
1111
| ^^^^^^^^^^^ private tuple struct constructor
1212
|
13-
::: $DIR/auxiliary/structs.rs:12:24
14-
|
15-
LL | pub struct TupleStruct(pub u16, pub u16);
16-
| ---------------- a constructor is private if any of the fields is private
17-
|
1813
note: the tuple struct constructor `TupleStruct` is defined here
1914
--> $DIR/auxiliary/structs.rs:12:1
2015
|
16+
LL | #[non_exhaustive]
17+
| ----------------- cannot be constructed because it is `#[non_exhaustive]`
2118
LL | pub struct TupleStruct(pub u16, pub u16);
2219
| ^^^^^^^^^^^^^^^^^^^^^^
2320

@@ -30,6 +27,8 @@ LL | let us_explicit = structs::UnitStruct;
3027
note: the unit struct `UnitStruct` is defined here
3128
--> $DIR/auxiliary/structs.rs:9:1
3229
|
30+
LL | #[non_exhaustive]
31+
| ----------------- cannot be constructed because it is `#[non_exhaustive]`
3332
LL | pub struct UnitStruct;
3433
| ^^^^^^^^^^^^^^^^^^^^^
3534

tests/ui/rfc-2008-non-exhaustive/variant.stderr

+15-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ note: the tuple variant `Tuple` is defined here
88
--> $DIR/auxiliary/variants.rs:5:23
99
|
1010
LL | #[non_exhaustive] Tuple(u32),
11-
| ^^^^^
11+
| ----------------- ^^^^^
12+
| |
13+
| cannot be constructed because it is `#[non_exhaustive]`
1214

1315
error[E0603]: unit variant `Unit` is private
1416
--> $DIR/variant.rs:14:47
@@ -20,7 +22,9 @@ note: the unit variant `Unit` is defined here
2022
--> $DIR/auxiliary/variants.rs:4:23
2123
|
2224
LL | #[non_exhaustive] Unit,
23-
| ^^^^
25+
| ----------------- ^^^^
26+
| |
27+
| cannot be constructed because it is `#[non_exhaustive]`
2428

2529
error[E0603]: unit variant `Unit` is private
2630
--> $DIR/variant.rs:18:32
@@ -32,7 +36,9 @@ note: the unit variant `Unit` is defined here
3236
--> $DIR/auxiliary/variants.rs:4:23
3337
|
3438
LL | #[non_exhaustive] Unit,
35-
| ^^^^
39+
| ----------------- ^^^^
40+
| |
41+
| cannot be constructed because it is `#[non_exhaustive]`
3642

3743
error[E0603]: tuple variant `Tuple` is private
3844
--> $DIR/variant.rs:20:32
@@ -44,7 +50,9 @@ note: the tuple variant `Tuple` is defined here
4450
--> $DIR/auxiliary/variants.rs:5:23
4551
|
4652
LL | #[non_exhaustive] Tuple(u32),
47-
| ^^^^^
53+
| ----------------- ^^^^^
54+
| |
55+
| cannot be constructed because it is `#[non_exhaustive]`
4856

4957
error[E0603]: tuple variant `Tuple` is private
5058
--> $DIR/variant.rs:26:35
@@ -56,7 +64,9 @@ note: the tuple variant `Tuple` is defined here
5664
--> $DIR/auxiliary/variants.rs:5:23
5765
|
5866
LL | #[non_exhaustive] Tuple(u32),
59-
| ^^^^^
67+
| ----------------- ^^^^^
68+
| |
69+
| cannot be constructed because it is `#[non_exhaustive]`
6070

6171
error[E0639]: cannot create non-exhaustive variant using struct expression
6272
--> $DIR/variant.rs:8:26

0 commit comments

Comments
 (0)