-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
type privacy: Check constructor types in tuple struct patterns #138458
base: master
Are you sure you want to change the base?
Conversation
@bors try |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes LGTM, but presumably this needs a crater run and T-lang signoff? If there's no fallout should be an easy decision.
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.
☀️ Try build successful - checks-actions |
@craterbot check |
🚨 Error: database is locked 🆘 If you have any trouble with Crater please ping |
@craterbot check |
1 similar comment
@craterbot check |
🚨 Error: missing start toolchain 🆘 If you have any trouble with Crater please ping |
@bors 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.
☀️ Try build successful - checks-actions |
@craterbot check |
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
🚧 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
🎉 Experiment
|
All the regressions are unrelated to this change. |
Change descriptionThis PR makes using wild card tuple struct and tuple variant patterns an error, if the struct or variant has a private field. mod m {
struct Priv;
pub struct TupleStruct(pub Priv);
pub enum Enum { TupleVariant(Priv) }
}
match something {
m::TupleStruct(..) => {} // ERROR `TupleStruct` has private type
}
match something {
m::Enum::TupleVariant(..) => {} // ERROR `Enum::TupleVariant` has private type
} To reproduce this you have to This now works according to the type privacy rules and reports a type privacy error because the types of constructors |
We talked about this on Wednesday and it turned out to not be an easy call for us. It'd probably help if you could walk us through how this is either specified by the RFC 2145 rules or falls out from them, and in those terms, if you could walk through how we'd distinguish (or not) the case you propose to disallow from other uses in the type namespace, e.g.: #![allow(private_interfaces, unreachable_code)]
mod m {
struct Priv;
pub struct TupleStruct(pub Priv);
}
fn main() {
let _: m::TupleStruct = loop {}; //~ OK
let m::TupleStruct { .. } = loop {}; //~ OK
let m::TupleStruct(..) = loop {}; //~ OK?
// In the value namespace, the use clearly
// should be (and is) an error.
let _ = m::TupleStruct; //~ ERROR
} |
@traviscross #![allow(private_interfaces, unreachable_code)]
mod m {
struct Priv;
pub struct TupleStruct(pub Priv);
}
fn main() {
// There's one type here - `m::TupleStruct`, it is public, no error.
// There are also two values here
// - `_` (its type `m::TupleStruct` is public, no errror),
// - `loop {}` (its types are `!` and `m::TupleStruct` before and after coercion, both public, no error).
let _: m::TupleStruct = loop {}; // OK
// There's one type here - `m::TupleStruct`, it is public, no error.
// There are also two values here
// - `m::TupleStruct { .. }` (its type `m::TupleStruct` is public, no error)
// - `loop {}` (same as above, no error).
let m::TupleStruct { .. } = loop {}; // OK
// There are no types here.
// There are three values here
// - `m::TupleStruct` (its type `fn(Priv) -> m::TupleStruct` is private due to `Priv` in the signature, error)
// - `m::TupleStruct(..)` (its type `m::TupleStruct` is public, no error)
// - `loop {}` (same as above, no error).
let m::TupleStruct(..) = loop {}; // ERROR
// There are no types here.
// There are two values here
// - `m::TupleStruct` (its type `fn(Priv) -> m::TupleStruct` is private due to `Priv` in the signature, error)
// - `_` (its type `fn(Priv) -> m::TupleStruct` is private due to `Priv` in the signature, error).
let _ = m::TupleStruct; // ERROR
} |
The relevant RFC part is https://github.com/rust-lang/rfcs/blob/master/text/2145-type-privacy.md#the-type-privacy-rule. I guess the only point of doubt here is whether |
This fixes a hole in type privacy checker that was noticed in #137623.
In
TupleStruct(something)
expression theTupleStruct
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.