-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Use covariance on type relations of field projection types if possible #107969
Conversation
e3e7055
to
6e1d228
Compare
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.
that looks really nice 👍 🔥
r=me after nit
fn get_ambient_variance(&self, context: PlaceContext) -> ty::Variance { | ||
match context { | ||
PlaceContext::MutatingUse(_) => ty::Invariant, | ||
PlaceContext::NonMutatingUse(_) | PlaceContext::NonUse(_) => ty::Covariant, |
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.
there's NonUseContext::AscribeUserTy
which I feel should maybe be invariant 🤔
I can also imagine us adding NonMutatingUse
in the future which should be invariant. Can you also exhaustively match on the NonMutatingUseContext
and probably make all NonUse
invariant. Don't know how to write an example where Covariance
is needed here.
Considering that covariance can be unsound if used incorrectly, we should be as defensive as possible here.
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.
Sorry for the late answer.
We would need NonUseContext::AscribeUserTy
for field projections on enums in match statements where we always insert user type projections I believe, e.g.
struct Inv<'a>(&'a mut &'a ());
enum Foo<T> {
Bar,
Var(T),
}
type Supertype = Foo<for<'a> fn(Inv<'a>, Inv<'a>)>;
fn foo_nested(x: Foo<Foo<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>>) {
match x {
Foo::Bar => {}
Foo::Var(Supertype::Bar) => {}
Foo::Var(Supertype::Var(x)) => {}
}
}
would not compile if we would use ty::Invariant
on NonUse(AscribeUserTy)
.
I agree that we should be very conservative here, but I also can't see how using covariance here might be unsound. Can you show that it is? I've kept this as covariant for now.
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.
my worry is that we use AscribeUserTy
in a position which isn't covariant. E.g. only for arguments of a function we're calling. Thinking more about it I actually can't imagine that happening 🤔
👍
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.
The AscribeUserType
statement contains a variance. Should it be carried by NonUseContext::AscribeUserTy
for use here?
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.
yes, I think so 👍 while I don't think is exploitable as we only use contravariance in AscribeUserType
for places without any projections. Using the following in super_ascribe_user_ty
does not cause any failures
if variance != $(& $mutability)? ty::Variance::Covariant && !place.projection.is_empty() {
bug!()
}
we should still add the variance to the use context though as this isn't something I want to implicitly rely on.
@bors try @rust-timer queue probably neutral |
This comment has been minimized.
This comment has been minimized.
⌛ Trying commit 6e1d228 with merge 746726458a663cc90ceb903387bfb3974d85ef19... |
☀️ Try build successful - checks-actions |
This comment has been minimized.
This comment has been minimized.
Finished benchmarking commit (746726458a663cc90ceb903387bfb3974d85ef19): comparison URL. Overall result: ✅ improvements - no action neededBenchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf. @bors rollup=never Instruction countThis is a highly reliable metric that was used to determine the overall result at the top of this comment.
Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesThis benchmark run did not return any relevant results for this metric. |
@rustbot author |
@bors r+ |
☀️ Test successful - checks-actions |
Finished benchmarking commit (e7eaed2): comparison URL. Overall result: ✅ improvements - no action needed@rustbot label: -perf-regression Instruction countThis is a highly reliable metric that was used to determine the overall result at the top of this comment.
Max RSS (memory usage)This benchmark run did not return any relevant results for this metric. CyclesThis benchmark run did not return any relevant results for this metric. |
It's fine to use covariance here unless we're in a mutating context.
Fixes #96514
Supersedes #105958
r? @lcnr