You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Stack overflow compiling slice pattern for big array #53820
I see tests failing on miri's CI on Windows when the size is just 1024, so my suspicion is that this code will fail to compile on Windows with a smaller slice -- but I do not have a Windows machine to test that.
Running this in gdb, the top end of the stack looks like
#0 0x00007ffff6a91a75 in <core::iter::FlatMap<I, U, F> as core::iter::iterator::Iterator>::next () at /home/r/src/rust/rustc.2/src/libcore/iter/mod.rs:2523
#1 0x00007ffff6a7ef11 in <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T, I>>::from_iter () at /home/r/src/rust/rustc.2/src/liballoc/vec.rs:1860
#2 0x00007ffff6dcaa1a in <alloc::vec::Vec<T> as core::iter::traits::FromIterator<T>>::from_iter () at /home/r/src/rust/rustc.2/src/liballoc/vec.rs:1772
#3 core::iter::iterator::Iterator::collect () at /home/r/src/rust/rustc.2/src/libcore/iter/iterator.rs:1415
#4 rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1058
#5 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#6 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#7 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#8 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#9 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#10 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#11 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#12 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#13 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#14 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#15 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#16 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#17 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#18 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#19 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#20 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#21 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#22 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#23 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#24 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#25 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#26 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#27 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#28 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#29 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#30 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#31 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#32 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#33 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#34 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#35 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#36 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#37 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#38 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#39 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#40 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#41 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#42 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#43 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#44 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#45 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#46 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#47 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#48 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#49 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#50 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#51 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#52 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#53 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#54 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#55 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#56 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#57 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#58 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
Further down:
#16319 0x00007ffff6dcc218 in rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1111
#16320 0x00007ffff6dccf32 in rustc_mir::hair::pattern::_match::is_useful_specialized () at librustc_mir/hair/pattern/_match.rs:1212
#16321 0x00007ffff6af5cd3 in rustc_mir::hair::pattern::_match::is_useful::{{closure}} () at librustc_mir/hair/pattern/_match.rs:1101
#16322 <core::iter::Map<I, F> as core::iter::iterator::Iterator>::try_fold::{{closure}} () at /home/r/src/rust/rustc.2/src/libcore/iter/mod.rs:1406
#16323 core::iter::iterator::Iterator::try_fold () at /home/r/src/rust/rustc.2/src/libcore/iter/iterator.rs:1522
#16324 <core::iter::Map<I, F> as core::iter::iterator::Iterator>::try_fold () at /home/r/src/rust/rustc.2/src/libcore/iter/mod.rs:1406
#16325 0x00007ffff6b0eb29 in <core::iter::Map<I, F> as core::iter::iterator::Iterator>::try_fold ()
from /home/r/src/rust/rustc.2/build/x86_64-unknown-linux-gnu/stage2/bin/../lib/../lib/librustc_mir-336e26fd9f56cf35.so
#16326 0x00007ffff6dca95b in core::iter::iterator::Iterator::try_for_each () at /home/r/src/rust/rustc.2/src/libcore/iter/iterator.rs:1559
#16327 core::iter::iterator::Iterator::find () at /home/r/src/rust/rustc.2/src/libcore/iter/iterator.rs:1782
#16328 rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1052
#16329 0x00007ffff6dccf32 in rustc_mir::hair::pattern::_match::is_useful_specialized () at librustc_mir/hair/pattern/_match.rs:1212
#16330 0x00007ffff6af5cd3 in rustc_mir::hair::pattern::_match::is_useful::{{closure}} () at librustc_mir/hair/pattern/_match.rs:1101
#16331 <core::iter::Map<I, F> as core::iter::iterator::Iterator>::try_fold::{{closure}} () at /home/r/src/rust/rustc.2/src/libcore/iter/mod.rs:1406
#16332 core::iter::iterator::Iterator::try_fold () at /home/r/src/rust/rustc.2/src/libcore/iter/iterator.rs:1522
#16333 <core::iter::Map<I, F> as core::iter::iterator::Iterator>::try_fold () at /home/r/src/rust/rustc.2/src/libcore/iter/mod.rs:1406
#16334 0x00007ffff6b0eb29 in <core::iter::Map<I, F> as core::iter::iterator::Iterator>::try_fold ()
from /home/r/src/rust/rustc.2/build/x86_64-unknown-linux-gnu/stage2/bin/../lib/../lib/librustc_mir-336e26fd9f56cf35.so
#16335 0x00007ffff6dca95b in core::iter::iterator::Iterator::try_for_each () at /home/r/src/rust/rustc.2/src/libcore/iter/iterator.rs:1559
#16336 core::iter::iterator::Iterator::find () at /home/r/src/rust/rustc.2/src/libcore/iter/iterator.rs:1782
#16337 rustc_mir::hair::pattern::_match::is_useful () at librustc_mir/hair/pattern/_match.rs:1052
#16338 0x00007ffff6dd00fe in rustc_mir::hair::pattern::check_match::check_arms () at librustc_mir/hair/pattern/check_match.rs:369
#16339 rustc_mir::hair::pattern::check_match::MatchVisitor::check_match::{{closure}} () at librustc_mir/hair/pattern/check_match.rs:220
#16340 rustc_mir::hair::pattern::_match::MatchCheckCtxt::create_and_enter () at librustc_mir/hair/pattern/_match.rs:325
changed the title [-]Stack overflow compiling slice pattern for big slice[/-][+]Stack overflow compiling slice pattern for big array[/+]on Jul 30, 2019
From my understanding of the code and the algorithm, this means that matrix has way too many columns. This is precisely what we would expect to happen if we considered a fixed-size array as a large tuple and naively applied the algorithm from the paper.
And this is in fact what seems to be happening: in the case of a fixed-size array, constructor_sub_pattern_tys returns a Vec of the same size as the array, and is_useful_specialized ends up making a Matrix with as many columns. Whereas the code for matching slices only uses as many matrix columns as (essentially) the longest pattern of the match, the code for fixed-size arrays brutally considers them as big tuples and calls it a day. It essentially considers [a, ..] as if it was [a, _, _, _, ..., _]. The algorithm then proceeds with these subpatterns one-by-one recursively, hence the stack overflow.
I looks to me like this issue doesn't come from a small oversight somewhere, but rather is a structural consequence of how fixed-size array patterns where shoehorned into the usefulness algorithm. So I feel that a good solution to this issue would need to rethink how to hande arrays (and slices too probably).
My idea for a solution would be the following: We would view a pattern [a, b, .., c] as something like Cons(a, Cons(b, Snoc(c, [..]))), which means we keep the number of matrix columns to a minimum, but we treat [..] specially when trying to specialize. For example, if we encounter a [..] when computing S(Cons, P), we would pretend [..] was actually [] | Cons(_, [..]) (or just [] if we know the size is 0), and then continue as usual.
So I've started working on this, and so far I've refactored some things here and there to make the code easier to follow. I'm not sure my decisions are good and this actually improves the code though. Also this is not strictly necessary to fix this particular issue. Is that an ok thing for me to be doing ? Should I maybe push those changes as a separate refactor PR ?
Is that an ok thing for me to be doing? Should I maybe push those changes as a separate refactor PR ?
Not only is it OK, it's awesome to first refactor and then implement. :) If it is a large refactor it might make sense to split things into different PRs.
I've put up a large refactor over there: #65160.
If and once it gets merged, fixing the issue should just be a case of using the VarLenSlice constructor for fixed-length arrays as well.
Activity
RalfJung commentedon Aug 30, 2018
Seems like we already had that once with #17877, and it came back?
RalfJung commentedon Aug 30, 2018
Running this in gdb, the top end of the stack looks like
Further down:
oli-obk commentedon Aug 30, 2018
cc @varkor
Centril commentedon Jul 30, 2019
cc @nagisa also?
RalfJung commentedon Jul 30, 2019
I updated the example to the changed syntax; it still reproduces with the latest nightly.
[-]Stack overflow compiling slice pattern for big slice[/-][+]Stack overflow compiling slice pattern for big array[/+]Nadrieril commentedon Sep 2, 2019
Since no one has done it publicly so far, I thought I'd investigate this error a bit.
First, I reduced the example to (playground link):
From the stack trace, we know that the overflow occurs at the only line
is_usefulcalls itself directly:rust/src/librustc_mir/hair/pattern/_match.rs
Line 1199 in fdaf594
From my understanding of the code and the algorithm, this means that
matrixhas way too many columns. This is precisely what we would expect to happen if we considered a fixed-size array as a large tuple and naively applied the algorithm from the paper.And this is in fact what seems to be happening: in the case of a fixed-size array,
constructor_sub_pattern_tysreturns a Vec of the same size as the array, andis_useful_specializedends up making aMatrixwith as many columns. Whereas the code for matching slices only uses as many matrix columns as (essentially) the longest pattern of the match, the code for fixed-size arrays brutally considers them as big tuples and calls it a day. It essentially considers[a, ..]as if it was[a, _, _, _, ..., _]. The algorithm then proceeds with these subpatterns one-by-one recursively, hence the stack overflow.I looks to me like this issue doesn't come from a small oversight somewhere, but rather is a structural consequence of how fixed-size array patterns where shoehorned into the usefulness algorithm. So I feel that a good solution to this issue would need to rethink how to hande arrays (and slices too probably).
My idea for a solution would be the following: We would view a pattern
[a, b, .., c]as something likeCons(a, Cons(b, Snoc(c, [..]))), which means we keep the number of matrix columns to a minimum, but we treat[..]specially when trying to specialize. For example, if we encounter a[..]when computingS(Cons, P), we would pretend[..]was actually[] | Cons(_, [..])(or just[]if we know the size is 0), and then continue as usual.Am I making sense ?
Centril commentedon Sep 2, 2019
Thanks for the investigation! cc @varkor, @arielb1, and @matthewjasper.
10 remaining items
oli-obk commentedon Sep 24, 2019
technically it should be
./x.py test src/librustc_mir --stage 1, but I don't know if that does what it appears it should, never tested itNadrieril commentedon Sep 26, 2019
@oli-obk Thanks !
So I've started working on this, and so far I've refactored some things here and there to make the code easier to follow. I'm not sure my decisions are good and this actually improves the code though. Also this is not strictly necessary to fix this particular issue. Is that an ok thing for me to be doing ? Should I maybe push those changes as a separate refactor PR ?
Centril commentedon Sep 26, 2019
Not only is it OK, it's awesome to first refactor and then implement. :) If it is a large refactor it might make sense to split things into different PRs.
Nadrieril commentedon Oct 6, 2019
I've put up a large refactor over there: #65160.
If and once it gets merged, fixing the issue should just be a case of using the VarLenSlice constructor for fixed-length arrays as well.
Auto merge of #66129 - Nadrieril:refactor-slice-pat-usefulness, r=<try>
Auto merge of #66129 - Nadrieril:refactor-slice-pat-usefulness, r=varkor
Rollup merge of rust-lang#66497 - Nadrieril:fix-53820, r=varkor
Auto merge of #66571 - Centril:rollup-41tn2fw, r=Centril
Rollup merge of rust-lang#67712 - Centril:stabilize-slice_patterns, r…
Rollup merge of rust-lang#67712 - Centril:stabilize-slice_patterns, r…