Skip to content

str::split_terminator is never finished #84974

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
WaffleLapkin opened this issue May 6, 2021 · 2 comments · Fixed by #95644
Closed

str::split_terminator is never finished #84974

WaffleLapkin opened this issue May 6, 2021 · 2 comments · Fixed by #95644
Labels
C-bug Category: This is a bug.

Comments

@WaffleLapkin
Copy link
Member

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
@WaffleLapkin WaffleLapkin added the C-bug Category: This is a bug. label May 6, 2021
@nagisa
Copy link
Member

nagisa commented May 6, 2021

What's the actual issue? Does the iterator produce the wrong results?

The debug output here is printing out internal implementation details and it is perfectly fine for the implementation to utilize them in whatever way it wishes to do so.

@WaffleLapkin
Copy link
Member Author

The issue actually showed up while I was changing as_str split methods (see #77998 (comment)).

The new method returns None if self.finished and Some(...) otherwise. So for exhausted SplitTerminator the method returned Some(""), instead of None.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
C-bug Category: This is a bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants