-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Handle bindings in substructure of patterns with type ascriptions #55274
Handle bindings in substructure of patterns with type ascriptions #55274
Conversation
813f5aa
to
e8c1c8b
Compare
r? @zackmdavis (rust_highfive has picked a reviewer for you, use r? to override) |
Oh, also: the If I don't get a chance to add that to this PR before its reviewed, then I will file a follow-up |
Oh, and I just realized that I should have looked more carefully at @nikomatsakis 's note a couple more times; namely, he anticipated the issue with My own code has its own hacked up version of that which only covers a subset of the cases, here: Now, comparing the above to: rust/src/librustc_mir/borrow_check/nll/type_check/mod.rs Lines 641 to 708 in a66dc8a
my main takeaway is that ... my hacked up version does not handle closures nor generators. But ... does it need to??? Can those arise in this context (of user type ascriptions)?
|
e8c1c8b
to
d5afe62
Compare
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
Hmm i didn’t see that in my (stage1) builds. Will investigate. |
Okay I've derived a standalone test case from the Minimized test: #![feature(nll)]
#[derive(Copy, Clone)]
pub struct Spanned<T> {
pub node: T,
pub span: Span,
}
pub type Variant = Spanned<VariantKind>;
// #[derive(Clone)] pub struct Variant { pub node: VariantKind, pub span: Span, }
#[derive(Clone)]
pub struct VariantKind { }
#[derive(Copy, Clone)]
pub struct Span;
pub fn variant_to_span(variant: Variant) {
match variant {
Variant {
span: _span,
..
} => { }
};
}
fn main() { } |
Hmm I must be missing a normalization step somewhere in there; my minimized test seems to pivot on whether one is using a |
and it also seems to pivot on the particular order I use for the fields in my local definition of |
@pnkfelix it wasn't clear to me — is this ready for review? at least partial review, I guess? |
@nikomatsakis I think its definitely ready for partial review. I've already tagged the bit of code that I suspect is most suspicious / in-need-of-revision. Namely, the way I've dealt with But a review of the overall architecture would still be very useful at this point. |
(but in case its not clear: It also is slightly buggy. I need to fix it so that the above test works. But my hope is that this will go hand-in-hand with revising the strategy for |
Oh! I bet the bug is this: namely, the index |
(and I think the fix is pretty simple; I really should have reviewed HAIR more carefully before I wrote this code.) |
d3c91ae
to
1005c56
Compare
(implemented aforementioned fix, rebased (so you'll never see what madness I had before), and added the reduced test. Unfortunately I couldn't figure out a way to generalize the test to actually appear relevant to the change here without causing other checks to fire and thus mask the ICE.) |
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.
First review — looks good but for the normalization question
src/librustc/mir/tcx.rs
Outdated
/// `handle_field` callback is used to map a `Field` to its `Ty`; | ||
/// in most cases one can just use the `Ty` stored inline, which | ||
/// is passed as the third parameter to the `handle_field` | ||
/// callback. |
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.
Maybe we want a convenient wrapper and an "inner" fn that takes the closure?
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.
probably; will fix.
let mut projected_ty = PlaceTy::from_ty(ty); | ||
for proj in &user_ty.projs { | ||
projected_ty = projected_ty.projection_ty( | ||
tcx, proj, |this, field, &()| this.field_ty(tcx, field)); |
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.
We will need to normalize here, I think
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.
yeah I thought that might be the case. I haven't tried hard to make a test that exposes the weakness here. (Its a bit hard to make tests that exercise just the code added here...)
but I will look into it.
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.
Okay I think this will serve as a basis for a test showing that we need to normalize as we project the fields:
struct Single<T> { value: T }
trait Indirect {
type U;
}
impl<'a> Indirect for &'a u32 {
type U = &'a u32;
}
fn static_to_a_to_static_through_struct_2<'a>(_x: &'a u32) -> &'static u32 {
let Single { value: y }: Single<<&'a u32 as Indirect>::U> = Single { value: &22 };
y //~ ERROR
}
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.
(well, either that, or the example exposes bugs elsewhere. Ha ha ... ha. ha.)
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.
right, the previous example looks an awful like an embedding of #54940. So maybe thats not going to get me anywhere.
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.
(If it comes down to it, I'll happily put in the code to normalize in the callback itself. But I would like to spend a bit longer trying to identify a test case that the current PR breaks on...)
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.
ah this one looks promising:
trait Indirect { type Assoc; }
struct StaticU32;
impl Indirect for StaticU32 { type Assoc = &'static u32; }
struct Single2<T: Indirect> { value: <T as Indirect>::Assoc }
fn static_no_initializer_2() {
let x = 22;
let Single2 { value: mut _y }: Single2<StaticU32>;
_y = &x; //~ ERROR
}
(it causes an ICE on my PR; and of course it is incorrectly accepted by nightly+NLL)
3f82689
to
b023055
Compare
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
☔ The latest upstream changes (presumably #55323) made this pull request unmergeable. Please resolve the merge conflicts. |
☔ The latest upstream changes (presumably #55382) made this pull request unmergeable. Please resolve the merge conflicts. |
It is unused, and would not make sense to maintain in the commits later in this PR.
…notation` to ease future changes.
… *into* a given UserTypeAnnotation. (That is, it will pull out some component type held or referenced by the type annotation.) Note: this still needs to actually do projection itself. That comes in a later commit
…r type. I did not think I would need this in the MIR, but in general local decls are going to need to support this. (That, or we need to be able define a least-upper-bound for a collection of types encountered via the pattern compilation.)
Update the existing NLL `patterns.rs` test accordingly. includes changes addressing review feedback: * Added example to docs for `UserTypeProjections` illustrating how we build up multiple projections when descending into a pattern with type ascriptions. * Adapted niko's suggested docs for `UserTypeProjection`. * Factored out `projection_ty` from more general `projection_ty_core` (as a drive-by, made its callback an `FnMut`, as I discovered later that I need that). * Add note to docs that `PlaceTy.field_ty(..)` does not normalize its result. * Normalize as we project out `field_ty`.
…a `UserTypeProjection`.
…bed types. As a drive-by, also added test analogous to existing static_to_a_to_static_through_tuple, but now apply to a struct instead of a tuple.
Also added alias `ProjectionKind<'tcx>` for `ProjectionElem<'tcx, (), ()>`.
b7e3a6c
to
639a3ff
Compare
@bors r=nikomatsakis p=1 |
📌 Commit 639a3ff has been approved by |
…type-take-2, r=nikomatsakis Handle bindings in substructure of patterns with type ascriptions This attempts to follow the outline described by @nikomatsakis [here](#47184 (comment)). Its a bit more complicated than expected for two reasons: 1. In general it handles sets of type ascriptions, because such ascriptions can be nested within patterns 2. It has a separate types in the HAIR, `PatternTypeProjections` and `PatternTypeProjection`, which are analogues to the corresponding types in the MIR. The main reason I added the new HAIR types was because I am worried that the current implementation is inefficent, and asymptotically so: It makes copies of vectors as it descends the patterns, even when those accumulated vectors are never used. Longer term, I would like to used a linked tree structure for the `PatternTypeProjections` and `PatternTypeProjection`, and save the construction of standalone vectors for the MIR types. I didn't want to block landing this on that hypoethetical revision; but I figured I could at least make the future change easier by differentiating between the two types now. Oh, one more thing: This doesn't attempt to handle `ref x` (in terms of ensuring that any necessary types are ascribed to `x` in that scenario as well). We should open an issue to investigate supporting that as well. But I didn't want to block this PR on that future work. Fix #54570
☀️ Test successful - status-appveyor, status-travis |
[beta]: Prepare the 1.31.0 beta release * Update to Cargo's branched 1.31.0 branch * Update the channel to `beta` Rolled up beta-accepted PRs: * #55362: Remove `cargo new --edition` from release notes. * #55325: Fix link to macros chapter * #55358: Remove redundant clone (2) * #55346: Shrink `Statement`. * #55274: Handle bindings in substructure of patterns with type ascriptions * #55297: Partial implementation of uniform paths 2.0 to land before beta * #55192: Fix ordering of nested modules in non-mod.rs mods * #55185: path suggestions in Rust 2018 should point out the change in semantics * #55423: back out bogus `Ok`-wrapping suggestion on `?` arm type mismatch Note that **this does not update the bootstrap compiler** due to #55404
This attempts to follow the outline described by @nikomatsakis here. Its a bit more complicated than expected for two reasons:
PatternTypeProjections
andPatternTypeProjection
, which are analogues to the corresponding types in the MIR.The main reason I added the new HAIR types was because I am worried that the current implementation is inefficent, and asymptotically so: It makes copies of vectors as it descends the patterns, even when those accumulated vectors are never used.
Longer term, I would like to used a linked tree structure for the
PatternTypeProjections
andPatternTypeProjection
, and save the construction of standalone vectors for the MIR types. I didn't want to block landing this on that hypoethetical revision; but I figured I could at least make the future change easier by differentiating between the two types now.Oh, one more thing: This doesn't attempt to handle
ref x
(in terms of ensuring that any necessary types are ascribed tox
in that scenario as well). We should open an issue to investigate supporting that as well. But I didn't want to block this PR on that future work.Fix #54570