Skip to content
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

request: improve string indexing error message #56740

Closed
steven807 opened this issue Dec 12, 2018 · 4 comments · Fixed by #57350
Closed

request: improve string indexing error message #56740

steven807 opened this issue Dec 12, 2018 · 4 comments · Fixed by #57350
Labels
A-diagnostics Area: Messages for errors, warnings, and lints E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-help-wanted Call for participation: Help is requested to fix this issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@steven807
Copy link
Contributor

The following buggy code:

fn f() {
    let s = "hello";
    let c = s[0];
}

produces the error:

error[E0277]: the type `str` cannot be indexed by `{integer}`
 --> src/main.rs:3:13
  |
3 |     let c = s[0];
  |             ^^^^ `str` cannot be indexed by `{integer}`
  |
  = help: the trait `std::ops::Index<{integer}>` is not implemented for `str`

This is usefully documented in TRPL (ch08-02-strings), but that is not easily discoverable from the error. Meanwhile, the error itself is a natural one that programmers from many languages (C, C++, etc) might run into. Speaking as someone who spent some time assuming that the issue was related to slices/references/usize (i.e. various new, Rust-specific concepts), not strings and UTF-8 encoding, I wonder whether a special case might be produced, replacing error E0277, when the types involved are specifically strings/strs and integers.

Meta

rustc --version --verbose:

rustc 1.32.0-nightly (4a45578bc 2018-12-07)
binary: rustc
commit-hash: 4a45578bc58ff262864f72680cc02e83f5d2f5b3
commit-date: 2018-12-07
host: x86_64-apple-darwin
release: 1.32.0-nightly
LLVM version: 8.0
@estebank estebank added A-diagnostics Area: Messages for errors, warnings, and lints A-docs Area: Documentation for any part of the project, including the compiler, standard library, and tools E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. labels Dec 12, 2018
@estebank
Copy link
Contributor

We should add a note pointing to https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings in the following code

#[rustc_on_unimplemented(
message="the type `{Self}` cannot be indexed by `{Idx}`",
label="`{Self}` cannot be indexed by `{Idx}`",
)]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "]")]
#[doc(alias = "[")]
#[doc(alias = "[]")]
pub trait Index<Idx: ?Sized> {
/// The returned type after indexing.
#[stable(feature = "rust1", since = "1.0.0")]
type Output: ?Sized;
/// Performs the indexing (`container[index]`) operation.
#[stable(feature = "rust1", since = "1.0.0")]
fn index(&self, index: Idx) -> &Self::Output;
}

rustc_on_unimplemented lets you customize the output of E0277 errors. The example has a similar case to this one, but the additional code should be something along the lines of

    on(
        _Self="&str",
        note="consider reading the appropriate chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
    ),
    on(
        _Self="str",
        note="consider reading the appropriate chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
    ),
    on(
        _Self="std::string::String",
        note="consider reading the appropriate chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
    ),

This will cause an extra note to be displayed for this case.

Beyond changing the code, you will also need to add a new test case with the repro case above and update all of the tests (running ./x.py test src/test/ui --stage 1 --bless and possibly updating the test comments for any remaining failing tests).

@estebank estebank added the E-help-wanted Call for participation: Help is requested to fix this issue. label Dec 12, 2018
@jromer94
Copy link

I would like to work on this.

@estebank
Copy link
Contributor

@jromer94 do not hesitate to reach out either here or on zulip if you need help!

@estebank
Copy link
Contributor

Possible proposed output from #57055:

error[EXXXX]: cannot index `String` or string slice (`str`)
 --> main.rs:2:24
  |
  |     let _value = "test"[0];
  |                        ^^^ cannot index here
  |
  |
  = help: consider using `.chars()` or `.to_bytes()

@steveklabnik steveklabnik added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed A-docs Area: Documentation for any part of the project, including the compiler, standard library, and tools labels Dec 27, 2018
Centril added a commit to Centril/rust that referenced this issue Jan 18, 2019
Better error note on unimplemented Index trait for string

fixes rust-lang#56740

I've tried to compile suggestion from comments in the issue rust-lang#56740, but unsure of it. So I'm open to advice :)

Current output will be like this:
```rust
error[E0277]: the type `str` cannot be indexed by `{integer}`
  --> $DIR/str-idx.rs:3:17
   |
LL |     let c: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}`
   |                 ^^^^ `str` cannot be indexed by `{integer}`
   |
   = help: the trait `std::ops::Index<{integer}>` is not implemented for `str`
   = note: you can use `.chars().nth()` or `.bytes().nth()`
           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
```

`x.py test src/test/ui` succeeded and I've also tested output manually by compiling the following code:
```rust
fn _f() {
    let s = std::string::String::from("hello");
    let _c = s[0];

    let s = std::string::String::from("hello");
    let mut _c = s[0];

    let s = "hello";
    let _c = s[0];

    let s = "hello";
    let mut _c = &s[0];
}
```

Not sure if some docs should be changed too. I will also fix error message in the [Book :: Indexing into Strings](https://github.com/rust-lang/book/blob/db53e2e3cdf77beac853df6f29db4b3b86ea598c/src/ch08-02-strings.md#indexing-into-strings) if that PR will get approved :)
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-help-wanted Call for participation: Help is requested to fix this issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants