Skip to content

Commit

Permalink
Auto merge of #79956 - camelid:variant-field-vis, r=petrochenkov
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bors committed Dec 13, 2020
2 parents 1281315 + 5ce3f4c commit d149b65
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 3 deletions.
11 changes: 10 additions & 1 deletion compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,16 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
Ok(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)))
}
ast::VisibilityKind::Inherited => {
Ok(ty::Visibility::Restricted(parent_scope.module.normal_ancestor_id))
if matches!(self.parent_scope.module.kind, ModuleKind::Def(DefKind::Enum, _, _)) {
// Any inherited visibility resolved directly inside an enum
// (e.g. variants or fields) inherits from the visibility of the enum.
let parent_enum = self.parent_scope.module.def_id().unwrap().expect_local();
Ok(self.r.visibilities[&parent_enum])
} else {
// If it's not in an enum, its visibility is restricted to the `mod` item
// that it's defined in.
Ok(ty::Visibility::Restricted(self.parent_scope.module.normal_ancestor_id))
}
}
ast::VisibilityKind::Restricted { ref path, id, .. } => {
// For visibilities we are not ready to provide correct implementation of "uniform
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ enum PathResult<'a> {
},
}

#[derive(Debug)]
enum ModuleKind {
/// An anonymous module; e.g., just a block.
///
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_typeck/src/check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1248,7 +1248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if no_accessible_remaining_fields {
self.report_no_accessible_fields(adt_ty, span);
} else {
self.report_missing_field(adt_ty, span, remaining_fields);
self.report_missing_fields(adt_ty, span, remaining_fields);
}
}

Expand Down Expand Up @@ -1279,7 +1279,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
///
/// error: aborting due to previous error
/// ```
fn report_missing_field(
fn report_missing_fields(
&self,
adt_ty: Ty<'tcx>,
span: Span,
Expand Down
29 changes: 29 additions & 0 deletions src/test/ui/issues/issue-79593.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
mod foo {
pub struct Pub { private: () }

pub enum Enum {
Variant { x: (), y: () },
Other
}

fn correct() {
Pub {};
//~^ ERROR missing field `private` in initializer of `Pub`
Enum::Variant { x: () };
//~^ ERROR missing field `y` in initializer of `Enum`
}
}

fn correct() {
foo::Pub {};
//~^ ERROR cannot construct `Pub` with struct literal syntax due to inaccessible fields
}

fn wrong() {
foo::Enum::Variant { x: () };
//~^ ERROR missing field `y` in initializer of `Enum`
foo::Enum::Variant { };
//~^ ERROR missing fields `x`, `y` in initializer of `Enum`
}

fn main() {}
33 changes: 33 additions & 0 deletions src/test/ui/issues/issue-79593.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
error[E0063]: missing field `private` in initializer of `Pub`
--> $DIR/issue-79593.rs:10:9
|
LL | Pub {};
| ^^^ missing `private`

error[E0063]: missing field `y` in initializer of `Enum`
--> $DIR/issue-79593.rs:12:9
|
LL | Enum::Variant { x: () };
| ^^^^^^^^^^^^^ missing `y`

error: cannot construct `Pub` with struct literal syntax due to inaccessible fields
--> $DIR/issue-79593.rs:18:5
|
LL | foo::Pub {};
| ^^^^^^^^

error[E0063]: missing field `y` in initializer of `Enum`
--> $DIR/issue-79593.rs:23:5
|
LL | foo::Enum::Variant { x: () };
| ^^^^^^^^^^^^^^^^^^ missing `y`

error[E0063]: missing fields `x`, `y` in initializer of `Enum`
--> $DIR/issue-79593.rs:25:5
|
LL | foo::Enum::Variant { };
| ^^^^^^^^^^^^^^^^^^ missing `x`, `y`

error: aborting due to 5 previous errors

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

0 comments on commit d149b65

Please sign in to comment.