Skip to content

Stack overflow compiling slice pattern for big array #53820

Closed

Description

@RalfJung

The following fails with a stack overflow:

#![feature(slice_patterns)]

fn main() {
    match [0u8; 16*1024] {
        [..] => {}
    }
}

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.

Activity

  1. RalfJung commented on Aug 30, 2018

    @RalfJung
    MemberAuthor

    Seems like we already had that once with #17877, and it came back?

  2. RalfJung commented on Aug 30, 2018

    @RalfJung
    MemberAuthor

    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
    
  3. oli-obk commented on Aug 30, 2018

    @oli-obk
    Contributor
  4. added
    I-slowIssue: Problems and improvements with respect to performance of generated code.
    A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html
    on Aug 30, 2018
  5. added
    I-compiletimeIssue: Problems and improvements with respect to compile times.
    and removed
    I-slowIssue: Problems and improvements with respect to performance of generated code.
    on Dec 15, 2018
  6. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Jul 30, 2019
  7. Centril commented on Jul 30, 2019

    @Centril
    Contributor

    cc @nagisa also?

  8. RalfJung commented on Jul 30, 2019

    @RalfJung
    MemberAuthor

    I updated the example to the changed syntax; it still reproduces with the latest nightly.

  9. changed the title [-]Stack overflow compiling slice pattern for big slice[/-] [+]Stack overflow compiling slice pattern for big array[/+] on Jul 30, 2019
  10. Nadrieril commented on Sep 2, 2019

    @Nadrieril
    Member

    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):

    match [0u8; 16*1024] {
        [..] => {}
    }

    From the stack trace, we know that the overflow occurs at the only line is_useful calls itself directly:

    match is_useful(cx, &matrix, &v[1..], witness) {

    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.

    Am I making sense ?

  11. Centril commented on Sep 2, 2019

    @Centril
    Contributor

    Am I making sense ?

    Thanks for the investigation! cc @varkor, @arielb1, and @matthewjasper.

  12. 10 remaining items

  13. oli-obk commented on Sep 24, 2019

    @oli-obk
    Contributor

    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 it

  14. Nadrieril commented on Sep 26, 2019

    @Nadrieril
    Member

    @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 ?

  15. Centril commented on Sep 26, 2019

    @Centril
    Contributor

    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.

  16. Nadrieril commented on Oct 6, 2019

    @Nadrieril
    Member

    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.

  17. added 3 commits that reference this issue on Nov 5, 2019
  18. added a commit that references this issue on Nov 20, 2019
    2d6e376
  19. added a commit that references this issue on Nov 20, 2019
    b9cf541
  20. added a commit that references this issue on Jan 18, 2020
  21. added a commit that references this issue on Jan 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlF-slice_patterns`#![feature(slice_patterns)]`I-compiletimeIssue: Problems and improvements with respect to compile times.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions