Skip to content

Commit 5ce3f4c

Browse files
committed
Resolve enum field visibility correctly
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.
1 parent 2225ee1 commit 5ce3f4c

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)