Skip to content

str::split_terminator is never finished #84974

Closed
@WaffleLapkin

Description

@WaffleLapkin

I tried this code:

let mut iter = "A..B..".split_terminator('.');
dbg!(&iter); // finished: false (expected)
    
iter.by_ref().for_each(drop);
dbg!(&iter); // finished: false (unexpected)
    
dbg!(iter.next());
dbg!(&iter); // finished: false (unexpected)
output

[src/main.rs:3] &iter = SplitTerminator(
    SplitInternal {
        start: 0,
        end: 6,
        matcher: CharSearcher {
            haystack: "A..B..",
            finger: 0,
            finger_back: 6,
            needle: '.',
            utf8_size: 1,
            utf8_encoded: [
                46,
                0,
                0,
                0,
            ],
        },
        allow_trailing_empty: false,
        finished: false,
    },
)
[src/main.rs:6] &iter = SplitTerminator(
    SplitInternal {
        start: 6,
        end: 6,
        matcher: CharSearcher {
            haystack: "A..B..",
            finger: 6,
            finger_back: 6,
            needle: '.',
            utf8_size: 1,
            utf8_encoded: [
                46,
                0,
                0,
                0,
            ],
        },
        allow_trailing_empty: false,
        finished: false,
    },
)
[src/main.rs:8] iter.next() = None
[src/main.rs:9] &iter = SplitTerminator(
    SplitInternal {
        start: 6,
        end: 6,
        matcher: CharSearcher {
            haystack: "A..B..",
            finger: 6,
            finger_back: 6,
            needle: '.',
            utf8_size: 1,
            utf8_encoded: [
                46,
                0,
                0,
                0,
            ],
        },
        allow_trailing_empty: false,
        finished: false,
    },
)

I've expected the finished flag to be set when the iterator is exhausted, however it isn't.

Meta

Tested on playground's stable 1.51.0 and nightly 1.54.0-nightly (2021-05-05 bacf770f2983a52f31e3)

Likely cause

It seems this behaviour is caused by allow_trailing_empty: false: SplitInternal only sets the finished flag if allow_trailing_empty: true or there is something to return.

Should the flag be set unconditionally? Maybe like this?

if !self.finished {
    self.finished = true;

    if self.allow_trailing_empty || self.end - self.start > 0 {
        return unsafe { ... } 
    }
}

None

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions