-
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
fix let _: ty = expr
subtyping error
#93856
Conversation
r? @cjgillot (rust-highfive has picked a reviewer for you, use r? to override) |
r? @rust-lang/wg-compiler-nll |
This comment has been minimized.
This comment has been minimized.
c928e55
to
e2f3bb5
Compare
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #93148) made this pull request unmergeable. Please resolve the merge conflicts. |
ty, | ||
variance.xform(ty::Variance::Contravariant), | ||
inferred_ty, | ||
Locations::All(span), | ||
ConstraintCategory::BoringNoLocation, |
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.
I'm trying to remember why we chose to use "type equality" here. I have a vague memory that there was a reason, but it seems there aren't any failing tests, at least.
@bors rollup=never |
b8d1a3f
to
5ee4525
Compare
@nikomatsakis this is now ready for review. I think we always |
let _: ty = expr
subtyping errorlet _: ty = expr
subtyping error
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
8fe1b2c
to
c3a91a8
Compare
This comment has been minimized.
This comment has been minimized.
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.
r=me with fresh comments + tests
/// If this is covariant, then `inferred_ty` has to be a subtype of `user_ty`. | ||
/// | ||
/// As the variance is already applied from `user_ty` to `inferred_ty`, all | ||
/// other uses of `inferred_ty` should be invariant. |
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.
It would be good to have a comment explaining:
let x: T = ...; // invariant
let _: T = ...; // covariant
the following is still broken: struct Foo<T>(T); // `T` is covariant.
fn foo<'b>(x: Foo<for<'a> fn(&'a ())>) {
let Foo(y): Foo<fn(&'b ())> = x;
} going to take some time to think about the bigger picture here |
☔ The latest upstream changes (presumably #94059) made this pull request unmergeable. Please resolve the merge conflicts. |
@rustbot author |
@lcnr whats the status on this? |
this needs a bigger change to the mir, intend to continue this work at some point in the near future. Can close this PR for now |
correctly deal with user type ascriptions in pat supersedes rust-lang#93856 `thir::PatKind::AscribeUserType` previously resulted in `CanonicalUserTypeAnnotations` where the inferred type already had a subtyping relation according to `variance` to the `user_ty`. The bug can pretty much be summarized as follows: - during mir building - `user_ty -> inferred_ty`: considers variance - `StatementKind::AscribeUserType`: `inferred_ty` is the type of the place, so no variance needed - during mir borrowck - `user_ty -> inferred_ty`: does not consider variance - `StatementKind::AscribeUserType`: applies variance This mostly worked fine. The lifetimes in `inferred_ty` were only bound by its relation to `user_ty` and to the `place` of `StatementKind::AscribeUserType`, so it doesn't matter where exactly the subtyping happens. It does however matter when having higher ranked subtying. At this point the place where the subtyping happens is forced, causing this mismatch between building and borrowck to result in unintended errors. cc rust-lang#96514 which is pretty much the same issue r? `@nikomatsakis`
Placeholder patterns
_
end up getting converted toAscribeUserType(_1, UserTypeProjection { base: UserType(1), projs: [] })
in the mir. This type ascription is covariant.In
fn check_user_type_annotations
we previously checked the type annotations without considering variance, breaking the above example. As lifetimes in theinferred_type
get erased they don't have any relation to other lifetimes in the body, sodoes not error because
'static
in theinferred_ty
gets erased and then replaced with an unbound inference variable.Note that the following example wouldn't have any issues here either way as there is an implicit reborrow before the assignment.
With this PR we now eagerly consider variance in
check_user_type_annotations
and then always use invariance when encountering user type annotation statements in the mir.