Skip to content

Commit 3db335b

Browse files
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.
2 parents 17b60b8 + 89300cd commit 3db335b

File tree

7 files changed

+83
-14
lines changed

7 files changed

+83
-14
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
2727
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
2828
use rustc_middle::mir::{self, Body, Promoted};
2929
use rustc_middle::ty::codec::TyDecoder;
30-
use rustc_middle::ty::{self, Ty, TyCtxt};
30+
use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
3131
use rustc_serialize::{opaque, Decodable, Decoder};
3232
use rustc_session::Session;
3333
use rustc_span::hygiene::ExpnDataDecodeMode;
@@ -1312,6 +1312,17 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
13121312
.collect()
13131313
}
13141314

1315+
fn get_struct_field_visibilities(&self, id: DefIndex) -> Vec<Visibility> {
1316+
self.root
1317+
.tables
1318+
.children
1319+
.get(self, id)
1320+
.unwrap_or_else(Lazy::empty)
1321+
.decode(self)
1322+
.map(|field_index| self.get_visibility(field_index))
1323+
.collect()
1324+
}
1325+
13151326
fn get_inherent_implementations_for_type(
13161327
&self,
13171328
tcx: TyCtxt<'tcx>,

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_ast::expand::allocator::AllocatorKind;
88
use rustc_data_structures::stable_map::FxHashMap;
99
use rustc_data_structures::svh::Svh;
1010
use rustc_hir as hir;
11-
use rustc_hir::def::DefKind;
11+
use rustc_hir::def::{CtorKind, DefKind};
1212
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
1313
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
1414
use rustc_middle::hir::exports::Export;
@@ -17,7 +17,7 @@ use rustc_middle::middle::cstore::{CrateSource, CrateStore, EncodedMetadata};
1717
use rustc_middle::middle::exported_symbols::ExportedSymbol;
1818
use rustc_middle::middle::stability::DeprecationEntry;
1919
use rustc_middle::ty::query::Providers;
20-
use rustc_middle::ty::{self, TyCtxt};
20+
use rustc_middle::ty::{self, TyCtxt, Visibility};
2121
use rustc_session::utils::NativeLibKind;
2222
use rustc_session::{CrateDisambiguator, Session};
2323
use rustc_span::source_map::{Span, Spanned};
@@ -392,6 +392,20 @@ impl CStore {
392392
self.get_crate_data(def.krate).get_struct_field_names(def.index, sess)
393393
}
394394

395+
pub fn struct_field_visibilities_untracked(&self, def: DefId) -> Vec<Visibility> {
396+
self.get_crate_data(def.krate).get_struct_field_visibilities(def.index)
397+
}
398+
399+
pub fn ctor_def_id_and_kind_untracked(&self, def: DefId) -> Option<(DefId, CtorKind)> {
400+
self.get_crate_data(def.krate).get_ctor_def_id(def.index).map(|ctor_def_id| {
401+
(ctor_def_id, self.get_crate_data(def.krate).get_ctor_kind(def.index))
402+
})
403+
}
404+
405+
pub fn visibility_untracked(&self, def: DefId) -> Visibility {
406+
self.get_crate_data(def.krate).get_visibility(def.index)
407+
}
408+
395409
pub fn item_children_untracked(
396410
&self,
397411
def_id: DefId,

compiler/rustc_resolve/src/build_reduced_graph.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,20 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
995995
// Record some extra data for better diagnostics.
996996
let cstore = self.r.cstore();
997997
match res {
998-
Res::Def(DefKind::Struct | DefKind::Union, def_id) => {
998+
Res::Def(DefKind::Struct, def_id) => {
999+
let field_names = cstore.struct_field_names_untracked(def_id, self.r.session);
1000+
let ctor = cstore.ctor_def_id_and_kind_untracked(def_id);
1001+
if let Some((ctor_def_id, ctor_kind)) = ctor {
1002+
let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
1003+
let ctor_vis = cstore.visibility_untracked(ctor_def_id);
1004+
let field_visibilities = cstore.struct_field_visibilities_untracked(def_id);
1005+
self.r
1006+
.struct_constructors
1007+
.insert(def_id, (ctor_res, ctor_vis, field_visibilities));
1008+
}
1009+
self.insert_field_names(def_id, field_names);
1010+
}
1011+
Res::Def(DefKind::Union, def_id) => {
9991012
let field_names = cstore.struct_field_names_untracked(def_id, self.r.session);
10001013
self.insert_field_names(def_id, field_names);
10011014
}
@@ -1007,12 +1020,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
10071020
self.r.has_self.insert(def_id);
10081021
}
10091022
}
1010-
Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => {
1011-
let parent = cstore.def_key(def_id).parent;
1012-
if let Some(struct_def_id) = parent.map(|index| DefId { index, ..def_id }) {
1013-
self.r.struct_constructors.insert(struct_def_id, (res, vis, vec![]));
1014-
}
1015-
}
10161023
_ => {}
10171024
}
10181025
}

src/test/ui/issues/auxiliary/issue-75907.rs

+12
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,15 @@ pub struct Bar(pub u8, u8, u8);
33
pub fn make_bar() -> Bar {
44
Bar(1, 12, 10)
55
}
6+
7+
mod inner {
8+
pub struct Foo(u8, pub u8, u8);
9+
10+
impl Foo {
11+
pub fn new() -> Foo {
12+
Foo(1, 12, 10)
13+
}
14+
}
15+
}
16+
17+
pub use inner::Foo;

src/test/ui/issues/issue-75907_b.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33

44
extern crate issue_75907 as a;
55

6-
use a::{make_bar, Bar};
6+
use a::{make_bar, Bar, Foo};
77

88
fn main() {
99
let Bar(x, y, z) = make_bar();
1010
//~^ ERROR cannot match against a tuple struct which contains private fields
11+
12+
let Foo(x, y, z) = Foo::new();
13+
//~^ ERROR cannot match against a tuple struct which contains private fields
1114
}

src/test/ui/issues/issue-75907_b.stderr

+24-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,30 @@ error[E0532]: cannot match against a tuple struct which contains private fields
22
--> $DIR/issue-75907_b.rs:9:9
33
|
44
LL | let Bar(x, y, z) = make_bar();
5-
| ^^^ constructor is not visible here due to private fields
5+
| ^^^
6+
|
7+
note: constructor is not visible here due to private fields
8+
--> $DIR/issue-75907_b.rs:9:16
9+
|
10+
LL | let Bar(x, y, z) = make_bar();
11+
| ^ ^ private field
12+
| |
13+
| private field
14+
15+
error[E0532]: cannot match against a tuple struct which contains private fields
16+
--> $DIR/issue-75907_b.rs:12:9
17+
|
18+
LL | let Foo(x, y, z) = Foo::new();
19+
| ^^^
20+
|
21+
note: constructor is not visible here due to private fields
22+
--> $DIR/issue-75907_b.rs:12:13
23+
|
24+
LL | let Foo(x, y, z) = Foo::new();
25+
| ^ ^ private field
26+
| |
27+
| private field
628

7-
error: aborting due to previous error
29+
error: aborting due to 2 previous errors
830

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

src/test/ui/rfc-2008-non-exhaustive/struct.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0423]: cannot initialize a tuple struct which contains private fields
22
--> $DIR/struct.rs:20:14
33
|
44
LL | let ts = TupleStruct(640, 480);
5-
| ^^^^^^^^^^^ constructor is not visible here due to private fields
5+
| ^^^^^^^^^^^
66

77
error[E0423]: expected value, found struct `UnitStruct`
88
--> $DIR/struct.rs:29:14

0 commit comments

Comments
 (0)