Skip to content

Commit

Permalink
Resolve enum field visibility correctly
Browse files Browse the repository at this point in the history
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
camelid committed Dec 12, 2020
1 parent 2225ee1 commit 5ce3f4c
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 5ce3f4c

Please sign in to comment.