Skip to content

Without critical-section feature, Rust gets confused about missing take() #704

@adamgreig

Description

@adamgreig

Currently the Peripherals::take() method is gated behind the critical-section optional dependency (and thus feature). Without the feature enabled, the method isn't available, because it requires the critical-section crate and we wanted to make that dependency optional (#651).

However it turns out if you call take() on a struct that doesn't have that method, Rust thinks you wanted to call the method on the Iterator trait that's imported by default, and then you get a pretty confusing error message about Peripherals not implementing Iterator (example):

struct Foo;

fn main() {
    let f = Foo {};
    f.take();
}
error[[E0599]](https://doc.rust-lang.org/stable/error-index.html#E0599): `Foo` is not an iterator
 --> src/main.rs:5:7
  |
1 | struct Foo;
  | ----------
  | |
  | method `take` not found for this struct
  | doesn't satisfy `Foo: Iterator`
...
5 |     f.take();
  |       ^^^^ `Foo` is not an iterator
  |
  = note: the following trait bounds were not satisfied:
          `Foo: Iterator`
          which is required by `&mut Foo: Iterator`
note: the following trait must be implemented
  = help: items from traits can only be used if the trait is implemented and in scope
  = note: the following trait defines an item `take`, perhaps you need to implement it:
          candidate #1: `Iterator`

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground` due to previous error

This seems to really throw people off because there's no indication that take() didn't exist or was feature-gated. I wonder if we should either...

  1. Make critical-section a hard dependency and always provide take(); it should build fine and only error about a missing c-s implementation if take() is actually called, in which case at least the error message is better, or
  2. Always implement a take(), but if the critical-section feature is not enabled, use compile_error!() to emit a custom compiler error instead of the very confusing one we currently get.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions