Uh oh!
There was an error while loading. Please reload this page.
Fix built-in indexing not being used where index type wasn't "obviously" usize - #47167
Conversation
rust-highfive
commented
Jan 3, 2018
r? @estebank (rust_highfive has picked a reviewer for you, use r? to override) |
There was a problem hiding this comment.
This comment is far too specific IMO, without this logic Index<usize> for [T]impl would infinitely recurse, for example.
There was a problem hiding this comment.
We always write this as ty::TyRef
There was a problem hiding this comment.
index_ty should be compared to tcx.types.usize.
There was a problem hiding this comment.
The is_uint() does that, from my understanding - would a direct comparison work in the case of the index being just literals?
There was a problem hiding this comment.
Since you resolved the type, it can't be TyInfer(IntVar(_)) anymore, only an usize. is_uint is pretty useless IMO, and misleading nowadays, when uint typically means "any unsigned integer" not usize.
eddyb
commented
Jan 3, 2018
There was a problem hiding this comment.
This makes me a bit ... nervous. It seems strange to strip out the &T based purely on the type involved. That is, if we were looking at the adjustment and deciding to strip off a layer of references, that'd be one thing, but I deciding based on the type alone makes me nervous. Can you give some examples of why this line of code was needed?
There was a problem hiding this comment.
I'd guess TyError, but we should probably skip doing this at all if there are any errors.
There was a problem hiding this comment.
The Unsize adjustment made by the index typechecking code (2252-2257 in this codebase) doesn't have the unsized type as the target, instead taking method.sig.inputs()[0], a &self. This is, to my understanding, the only way for the result of expr_ty_adjusted to result in a TyRef, since otherwise a reference would be deref'd, and you can't do an impl<'a, T> Index<usize> for &'a [T] of some kind.
builtin_index() returns None on TyRef, regardless of the underlying type - I considered changing this instead, but I felt this would confuse the dereferencing logic. Alternatively, I could introduce some kind of fn unsize_type to use in place of the trait argument, which would return TySlice for TyArray, which is the only case I can think of that matters.
There was a problem hiding this comment.
Actually, on a second closer look, this just requires using self_ty, which is the correct unsized type, and not method.sigs.inputs()[0], in that adjustment.
There was a problem hiding this comment.
Unsizing coercions happen on references and raw/smart pointers, so you first have a borrow to get &[T; N] and then an unsizing of that reference to &[T].
There was a problem hiding this comment.
@ivanbakel my point was that I would feel more comfortbale "skipping" the ref if we only did it when the coercion was an Unsize coercion -- i.e., I don't like deciding to skip based on the type, that feels like it could misfire and skip when we didn't expect.
There was a problem hiding this comment.
What @eddyb said made me re-examine the behaviour, and this ref skip is always necessary, because it's always introduced in the indexing logic even without an Unsize. I've rewritten the code to reflect that. Let me know if you still have the same concern.
nikomatsakis
commented
Jan 4, 2018
@ivanbakel if you have a build of this branch handy, could you tell me the result of running fnmain(){letmut i = [1,2,3];
i[i[0] - 1] = 0;}Does it compile? I'm just curious to see if it fixes another random bug. Thanks =) |
ivanbakel
commented
Jan 5, 2018
Compiles, and from a little bit of |
bors
commented
Jan 6, 2018
☔ The latest upstream changes (presumably #47235) made this pull request unmergeable. Please resolve the merge conflicts. |
Use of builtin indexing is now only checked after types are fully resolved. Types are not correctly checked in case of autoderefs.
Tests match issues opened on Github. Tests would not previously compile and pass.
The adjusted type is now used instead in cases of autoderefs.
If the final type coming out of an Adjust is a ref, it is deconstructed. Also made some formatting changes.
The ref was actually always necessary. This clarifies some incorrect thinking in the original code that might have led to errors in the future to do with unsizing.
3ba7d18 to
6132806Compare| // So the borrow discard actually happens here | ||
| a.pop(); | ||
| }, | ||
| _ => {} |
There was a problem hiding this comment.
Can we add some kind of assertion here? That is, the adjustment we are popping, will it always be a ref adjustment or something similar?
There was a problem hiding this comment.
Eh, looking at the other cases, this looks similarly paranoid (or not paranoid). Seems fine.
nikomatsakis
left a comment
There was a problem hiding this comment.
This looks much better. One last question is whether there is some form of assertion we can add that would be helpful.
nikomatsakis
commented
Jan 9, 2018
@bors r+ |
bors
commented
Jan 9, 2018
📌 Commit 6132806 has been approved by |
bors
commented
Jan 9, 2018
⌛ Testing commit 6132806 with merge 9f9ba8a5bf0182a0009f6fb71c8b5374be3123c0... |
bors
commented
Jan 9, 2018
💔 Test failed - status-appveyor |
estebank
commented
Jan 9, 2018
@bors retry |
bors
commented
Jan 9, 2018
⌛ Testing commit 6132806 with merge 52a9637bf87b98d1110e48c65f7507fc232f8440... |
bors
commented
Jan 9, 2018
💔 Test failed - status-appveyor |
kennytm
commented
Jan 10, 2018
bors
commented
Jan 10, 2018
Fix built-in indexing not being used where index type wasn't "obviously" usize Fixes#33903Fixes#46095 This PR was made possible thanks to the generous help of @eddyb Following the example of binary operators, builtin checking for indexing has been moved from the typecheck stage to a writeback stage, after type constraints have been resolved.
bors
commented
Jan 10, 2018
☀️ Test successful - status-appveyor, status-travis |
SimonSapin
commented
Jan 11, 2018
Is this change intended to reject during borrow-checking programs that were previously accepted? #47349 |
nikomatsakis
commented
Jan 25, 2018
Adding relnotes tag because, as @SimonSapin noted, this did cause a regression (#47349), though it appears to be a genuine bug fix. In particular, I would summarize it as:
|
Fixes#33903
Fixes#46095
This PR was made possible thanks to the generous help of @eddyb
Following the example of binary operators, builtin checking for indexing has been moved from the typecheck stage to a writeback stage, after type constraints have been resolved.