Skip to content

Commit 26ad8a8

Browse files
committed
Auto merge of #138458 - petrochenkov:privtup, r=<try>
type privacy: Check constructor types in tuple struct patterns This fixes a hole in type privacy checker. In `TupleStruct(something)` expression the `TupleStruct` part has its type recorded and we are checking it, but in patterns only type of the whole pattern is kept, so we were missing the constructor's type in the privacy check.
2 parents 9c67cec + 819edd9 commit 26ad8a8

File tree

3 files changed

+95
-0
lines changed

3 files changed

+95
-0
lines changed

compiler/rustc_privacy/src/lib.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,6 +1302,27 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
13021302
return;
13031303
}
13041304

1305+
match pattern.kind {
1306+
hir::PatKind::TupleStruct(qpath, ..) => {
1307+
// Tuple struct constructors have to be checked specially.
1308+
self.span = qpath.span();
1309+
let def_id = match qpath {
1310+
hir::QPath::Resolved(_, path) => path.res.opt_def_id(),
1311+
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
1312+
.maybe_typeck_results
1313+
.unwrap_or_else(|| span_bug!(self.span, "`hir::Pat` outside of a body"))
1314+
.type_dependent_def_id(pattern.hir_id),
1315+
};
1316+
1317+
if let Some(def_id) = def_id {
1318+
if self.visit(self.tcx.type_of(def_id).instantiate_identity()).is_break() {
1319+
return;
1320+
}
1321+
}
1322+
}
1323+
_ => {}
1324+
}
1325+
13051326
intravisit::walk_pat(self, pattern);
13061327
}
13071328

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
mod m {
2+
struct Priv;
3+
4+
#[allow(private_interfaces)]
5+
pub struct PubStruct(pub Priv);
6+
pub enum PubEnum {
7+
#[allow(private_interfaces)]
8+
Variant(Priv),
9+
}
10+
11+
impl PubStruct {
12+
pub fn new() -> PubStruct {
13+
PubStruct(Priv)
14+
}
15+
}
16+
impl PubEnum {
17+
pub fn new() -> PubEnum {
18+
PubEnum::Variant(Priv)
19+
}
20+
}
21+
}
22+
23+
fn main() {
24+
match m::PubStruct::new() {
25+
m::PubStruct(_) => {} //~ ERROR type `Priv` is private
26+
m::PubStruct(..) => {} //~ ERROR type `Priv` is private
27+
}
28+
29+
match m::PubEnum::new() {
30+
m::PubEnum::Variant(_) => {} //~ ERROR type `Priv` is private
31+
m::PubEnum::Variant(..) => {} //~ ERROR type `Priv` is private
32+
}
33+
34+
let _ = m::PubStruct; //~ ERROR type `Priv` is private
35+
let _ = m::PubEnum::Variant; //~ ERROR type `Priv` is private
36+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
error: type `Priv` is private
2+
--> $DIR/private-in-public-tuple-struct-pat.rs:25:9
3+
|
4+
LL | m::PubStruct(_) => {}
5+
| ^^^^^^^^^^^^ private type
6+
7+
error: type `Priv` is private
8+
--> $DIR/private-in-public-tuple-struct-pat.rs:26:9
9+
|
10+
LL | m::PubStruct(..) => {}
11+
| ^^^^^^^^^^^^ private type
12+
13+
error: type `Priv` is private
14+
--> $DIR/private-in-public-tuple-struct-pat.rs:30:9
15+
|
16+
LL | m::PubEnum::Variant(_) => {}
17+
| ^^^^^^^^^^^^^^^^^^^ private type
18+
19+
error: type `Priv` is private
20+
--> $DIR/private-in-public-tuple-struct-pat.rs:31:9
21+
|
22+
LL | m::PubEnum::Variant(..) => {}
23+
| ^^^^^^^^^^^^^^^^^^^ private type
24+
25+
error: type `Priv` is private
26+
--> $DIR/private-in-public-tuple-struct-pat.rs:34:13
27+
|
28+
LL | let _ = m::PubStruct;
29+
| ^^^^^^^^^^^^ private type
30+
31+
error: type `Priv` is private
32+
--> $DIR/private-in-public-tuple-struct-pat.rs:35:13
33+
|
34+
LL | let _ = m::PubEnum::Variant;
35+
| ^^^^^^^^^^^^^^^^^^^ private type
36+
37+
error: aborting due to 6 previous errors
38+

0 commit comments

Comments
 (0)