Skip to content

Commit d149b65

Browse files
committed
Auto merge of #79956 - camelid:variant-field-vis, r=petrochenkov
Resolve enum field visibility correctly Fixes #79593. 🎉 Previously, this code treated enum fields' visibility as if they were struct fields. However, that's not correct because the visibility of a struct field with `ast::VisibilityKind::Inherited` is private to the module it's defined in, whereas the visibility of an *enum* field with `ast::VisibilityKind::Inherited` is the visibility of the enum it belongs to.
2 parents 1281315 + 5ce3f4c commit d149b65

File tree

5 files changed

+75
-3
lines changed

5 files changed

+75
-3
lines changed

compiler/rustc_resolve/src/build_reduced_graph.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,16 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
258258
Ok(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)))
259259
}
260260
ast::VisibilityKind::Inherited => {
261-
Ok(ty::Visibility::Restricted(parent_scope.module.normal_ancestor_id))
261+
if matches!(self.parent_scope.module.kind, ModuleKind::Def(DefKind::Enum, _, _)) {
262+
// Any inherited visibility resolved directly inside an enum
263+
// (e.g. variants or fields) inherits from the visibility of the enum.
264+
let parent_enum = self.parent_scope.module.def_id().unwrap().expect_local();
265+
Ok(self.r.visibilities[&parent_enum])
266+
} else {
267+
// If it's not in an enum, its visibility is restricted to the `mod` item
268+
// that it's defined in.
269+
Ok(ty::Visibility::Restricted(self.parent_scope.module.normal_ancestor_id))
270+
}
262271
}
263272
ast::VisibilityKind::Restricted { ref path, id, .. } => {
264273
// For visibilities we are not ready to provide correct implementation of "uniform

compiler/rustc_resolve/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ enum PathResult<'a> {
403403
},
404404
}
405405

406+
#[derive(Debug)]
406407
enum ModuleKind {
407408
/// An anonymous module; e.g., just a block.
408409
///

compiler/rustc_typeck/src/check/expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1248,7 +1248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12481248
if no_accessible_remaining_fields {
12491249
self.report_no_accessible_fields(adt_ty, span);
12501250
} else {
1251-
self.report_missing_field(adt_ty, span, remaining_fields);
1251+
self.report_missing_fields(adt_ty, span, remaining_fields);
12521252
}
12531253
}
12541254

@@ -1279,7 +1279,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12791279
///
12801280
/// error: aborting due to previous error
12811281
/// ```
1282-
fn report_missing_field(
1282+
fn report_missing_fields(
12831283
&self,
12841284
adt_ty: Ty<'tcx>,
12851285
span: Span,

src/test/ui/issues/issue-79593.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
mod foo {
2+
pub struct Pub { private: () }
3+
4+
pub enum Enum {
5+
Variant { x: (), y: () },
6+
Other
7+
}
8+
9+
fn correct() {
10+
Pub {};
11+
//~^ ERROR missing field `private` in initializer of `Pub`
12+
Enum::Variant { x: () };
13+
//~^ ERROR missing field `y` in initializer of `Enum`
14+
}
15+
}
16+
17+
fn correct() {
18+
foo::Pub {};
19+
//~^ ERROR cannot construct `Pub` with struct literal syntax due to inaccessible fields
20+
}
21+
22+
fn wrong() {
23+
foo::Enum::Variant { x: () };
24+
//~^ ERROR missing field `y` in initializer of `Enum`
25+
foo::Enum::Variant { };
26+
//~^ ERROR missing fields `x`, `y` in initializer of `Enum`
27+
}
28+
29+
fn main() {}

src/test/ui/issues/issue-79593.stderr

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
error[E0063]: missing field `private` in initializer of `Pub`
2+
--> $DIR/issue-79593.rs:10:9
3+
|
4+
LL | Pub {};
5+
| ^^^ missing `private`
6+
7+
error[E0063]: missing field `y` in initializer of `Enum`
8+
--> $DIR/issue-79593.rs:12:9
9+
|
10+
LL | Enum::Variant { x: () };
11+
| ^^^^^^^^^^^^^ missing `y`
12+
13+
error: cannot construct `Pub` with struct literal syntax due to inaccessible fields
14+
--> $DIR/issue-79593.rs:18:5
15+
|
16+
LL | foo::Pub {};
17+
| ^^^^^^^^
18+
19+
error[E0063]: missing field `y` in initializer of `Enum`
20+
--> $DIR/issue-79593.rs:23:5
21+
|
22+
LL | foo::Enum::Variant { x: () };
23+
| ^^^^^^^^^^^^^^^^^^ missing `y`
24+
25+
error[E0063]: missing fields `x`, `y` in initializer of `Enum`
26+
--> $DIR/issue-79593.rs:25:5
27+
|
28+
LL | foo::Enum::Variant { };
29+
| ^^^^^^^^^^^^^^^^^^ missing `x`, `y`
30+
31+
error: aborting due to 5 previous errors
32+
33+
For more information about this error, try `rustc --explain E0063`.

0 commit comments

Comments
 (0)