From 57fda672911d113602bfde8f9da22131f0cbff19 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Fri, 7 May 2021 22:42:12 -0700 Subject: [PATCH 1/2] Fix diagnostic for matching/creating x-crate re-exported tuple structs with private fields. The more helpful diagnostic already existed but wasn't working if the struct in question was a re-export from a different crate. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 13 +++++++++++- .../src/rmeta/decoder/cstore_impl.rs | 18 ++++++++++++++-- .../rustc_resolve/src/build_reduced_graph.rs | 21 ++++++++++++------- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index d74fef0045f51..bd2cc1c053aee 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -27,7 +27,7 @@ use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::mir::{self, Body, Promoted}; use rustc_middle::ty::codec::TyDecoder; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, Visibility}; use rustc_serialize::{opaque, Decodable, Decoder}; use rustc_session::Session; use rustc_span::hygiene::ExpnDataDecodeMode; @@ -1305,6 +1305,17 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .collect() } + fn get_struct_field_visibilities(&self, id: DefIndex) -> Vec { + self.root + .tables + .children + .get(self, id) + .unwrap_or_else(Lazy::empty) + .decode(self) + .map(|field_index| self.get_visibility(field_index)) + .collect() + } + fn get_inherent_implementations_for_type( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index b11ad6c7ff867..27057bbad41cf 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -8,7 +8,7 @@ use rustc_ast::expand::allocator::AllocatorKind; use rustc_data_structures::stable_map::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_hir as hir; -use rustc_hir::def::DefKind; +use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_middle::hir::exports::Export; @@ -17,7 +17,7 @@ use rustc_middle::middle::cstore::{CrateSource, CrateStore, EncodedMetadata}; use rustc_middle::middle::exported_symbols::ExportedSymbol; use rustc_middle::middle::stability::DeprecationEntry; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt, Visibility}; use rustc_session::utils::NativeLibKind; use rustc_session::{CrateDisambiguator, Session}; use rustc_span::source_map::{Span, Spanned}; @@ -392,6 +392,20 @@ impl CStore { self.get_crate_data(def.krate).get_struct_field_names(def.index, sess) } + pub fn struct_field_visibilities_untracked(&self, def: DefId) -> Vec { + self.get_crate_data(def.krate).get_struct_field_visibilities(def.index) + } + + pub fn ctor_def_id_and_kind_untracked(&self, def: DefId) -> Option<(DefId, CtorKind)> { + self.get_crate_data(def.krate).get_ctor_def_id(def.index).map(|ctor_def_id| { + (ctor_def_id, self.get_crate_data(def.krate).get_ctor_kind(def.index)) + }) + } + + pub fn visibility_untracked(&self, def: DefId) -> Visibility { + self.get_crate_data(def.krate).get_visibility(def.index) + } + pub fn item_children_untracked( &self, def_id: DefId, diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index b5c95cfcb29cb..e10314a11fc1b 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -995,7 +995,20 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { // Record some extra data for better diagnostics. let cstore = self.r.cstore(); match res { - Res::Def(DefKind::Struct | DefKind::Union, def_id) => { + Res::Def(DefKind::Struct, def_id) => { + let field_names = cstore.struct_field_names_untracked(def_id, self.r.session); + let ctor = cstore.ctor_def_id_and_kind_untracked(def_id); + if let Some((ctor_def_id, ctor_kind)) = ctor { + let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id); + let ctor_vis = cstore.visibility_untracked(ctor_def_id); + let field_visibilities = cstore.struct_field_visibilities_untracked(def_id); + self.r + .struct_constructors + .insert(def_id, (ctor_res, ctor_vis, field_visibilities)); + } + self.insert_field_names(def_id, field_names); + } + Res::Def(DefKind::Union, def_id) => { let field_names = cstore.struct_field_names_untracked(def_id, self.r.session); self.insert_field_names(def_id, field_names); } @@ -1007,12 +1020,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.has_self.insert(def_id); } } - Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => { - let parent = cstore.def_key(def_id).parent; - if let Some(struct_def_id) = parent.map(|index| DefId { index, ..def_id }) { - self.r.struct_constructors.insert(struct_def_id, (res, vis, vec![])); - } - } _ => {} } } From 89300cdebc4f888f64b142a2393623c502cfe3fe Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Sat, 8 May 2021 01:07:27 -0700 Subject: [PATCH 2/2] Add tests. --- src/test/ui/issues/auxiliary/issue-75907.rs | 12 +++++++++ src/test/ui/issues/issue-75907_b.rs | 5 +++- src/test/ui/issues/issue-75907_b.stderr | 26 +++++++++++++++++-- .../ui/rfc-2008-non-exhaustive/struct.stderr | 2 +- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/test/ui/issues/auxiliary/issue-75907.rs b/src/test/ui/issues/auxiliary/issue-75907.rs index 0b70452a24d71..389c9c35101ab 100644 --- a/src/test/ui/issues/auxiliary/issue-75907.rs +++ b/src/test/ui/issues/auxiliary/issue-75907.rs @@ -3,3 +3,15 @@ pub struct Bar(pub u8, u8, u8); pub fn make_bar() -> Bar { Bar(1, 12, 10) } + +mod inner { + pub struct Foo(u8, pub u8, u8); + + impl Foo { + pub fn new() -> Foo { + Foo(1, 12, 10) + } + } +} + +pub use inner::Foo; diff --git a/src/test/ui/issues/issue-75907_b.rs b/src/test/ui/issues/issue-75907_b.rs index a775845279eb8..e30747782339c 100644 --- a/src/test/ui/issues/issue-75907_b.rs +++ b/src/test/ui/issues/issue-75907_b.rs @@ -3,9 +3,12 @@ extern crate issue_75907 as a; -use a::{make_bar, Bar}; +use a::{make_bar, Bar, Foo}; fn main() { let Bar(x, y, z) = make_bar(); //~^ ERROR cannot match against a tuple struct which contains private fields + + let Foo(x, y, z) = Foo::new(); + //~^ ERROR cannot match against a tuple struct which contains private fields } diff --git a/src/test/ui/issues/issue-75907_b.stderr b/src/test/ui/issues/issue-75907_b.stderr index 8884484e18d81..b82d08473c8c9 100644 --- a/src/test/ui/issues/issue-75907_b.stderr +++ b/src/test/ui/issues/issue-75907_b.stderr @@ -2,8 +2,30 @@ error[E0532]: cannot match against a tuple struct which contains private fields --> $DIR/issue-75907_b.rs:9:9 | LL | let Bar(x, y, z) = make_bar(); - | ^^^ constructor is not visible here due to private fields + | ^^^ + | +note: constructor is not visible here due to private fields + --> $DIR/issue-75907_b.rs:9:16 + | +LL | let Bar(x, y, z) = make_bar(); + | ^ ^ private field + | | + | private field + +error[E0532]: cannot match against a tuple struct which contains private fields + --> $DIR/issue-75907_b.rs:12:9 + | +LL | let Foo(x, y, z) = Foo::new(); + | ^^^ + | +note: constructor is not visible here due to private fields + --> $DIR/issue-75907_b.rs:12:13 + | +LL | let Foo(x, y, z) = Foo::new(); + | ^ ^ private field + | | + | private field -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0532`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr index e2ee8d6a6fe5e..d023ba3096e68 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr @@ -2,7 +2,7 @@ error[E0423]: cannot initialize a tuple struct which contains private fields --> $DIR/struct.rs:20:14 | LL | let ts = TupleStruct(640, 480); - | ^^^^^^^^^^^ constructor is not visible here due to private fields + | ^^^^^^^^^^^ error[E0423]: expected value, found struct `UnitStruct` --> $DIR/struct.rs:29:14