rust-embedded / rust-embedded/svd2rust

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

Open
#704 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Rust
Stars
857
Forks
164
PR merge metrics
No merged PRs in 30d

Description

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.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the Rust Playground example and inspect how the generated Peripherals::take() method is gated by the critical-section feature. Compare the two proposed approaches and determine which behavior maintainers want when the feature is disabled. Done means the chosen behavior is implemented and the resulting compiler diagnostic is no longer misleading.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
embedded-iot, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.