Rollup merge of #85068 - luqmana:78708-xcrate-diag, r=estebank
Fix diagnostic for cross crate private tuple struct constructors Fixes #78708. There was already some limited support for certain cross-crate scenarios but that didn't handle a tuple struct rexported from an inner module for example (e.g. the NonZero* types as seen in #85049). ```Rust ➜ cat bug.rs fn main() { let _x = std::num::NonZeroU32(12); let n = std::num::NonZeroU32::new(1).unwrap(); match n { std::num::NonZeroU32(i) => {}, } } ``` **Before:** <details> ```Rust ➜ rustc +nightly bug.rs error[E0423]: expected function, tuple struct or tuple variant, found struct `std::num::NonZeroU32` --> bug.rs:2:14 | 2 | let _x = std::num::NonZeroU32(12); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `std::num::NonZeroU32 { 0: val }` | ::: /home/luqman/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/nonzero.rs:148:1 [snip] error[E0532]: expected tuple struct or tuple variant, found struct `std::num::NonZeroU32` --> bug.rs:5:9 | 5 | std::num::NonZeroU32(i) => {}, | ^^^^^^^^^^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `std::num::NonZeroU32 { 0 }` | ::: /home/luqman/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/nonzero.rs:148:1 [snip] error: aborting due to 2 previous errors Some errors have detailed explanations: E0423, E0532. For more information about an error, try `rustc --explain E0423`. ``` </details> **After:** <details> ```Rust ➜ /rust/build/x86_64-unknown-linux-gnu/stage1/bin/rustc bug.rs error[E0423]: cannot initialize a tuple struct which contains private fields --> bug.rs:2:14 | 2 | let _x = std::num::NonZeroU32(12); | ^^^^^^^^^^^^^^^^^^^^ | note: constructor is not visible here due to private fields --> /rust/library/core/src/num/nonzero.rs:148:1 [snip] error[E0532]: cannot match against a tuple struct which contains private fields --> bug.rs:5:9 | 5 | std::num::NonZeroU32(i) => {}, | ^^^^^^^^^^^^^^^^^^^^ | note: constructor is not visible here due to private fields --> bug.rs:5:30 | 5 | std::num::NonZeroU32(i) => {}, | ^ private field error: aborting due to 2 previous errors Some errors have detailed explanations: E0423, E0532. For more information about an error, try `rustc --explain E0423`. ``` </details> One question is if we should only collect the needed info for the cross-crate case after encountering an error instead of always doing it. Perf run perhaps to gauge the impact.
This commit is contained in:
commit
3db335b934
7 changed files with 83 additions and 14 deletions
|
@ -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;
|
||||
|
@ -1312,6 +1312,17 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
fn get_struct_field_visibilities(&self, id: DefIndex) -> Vec<Visibility> {
|
||||
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>,
|
||||
|
|
|
@ -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<Visibility> {
|
||||
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,
|
||||
|
|
|
@ -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![]));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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: aborting due to previous error
|
||||
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 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0532`.
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue