Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Blanket impls for &mut can cause trait methods to be preferred over inherent methods. #341

Closed
Dirbaio opened this issue Dec 21, 2021 · 4 comments

Comments

@Dirbaio
Copy link
Member

Dirbaio commented Dec 21, 2021

I found one ugly side effect of the &mut blanket impls while experimenting updating stm32f4xx-hal's GPIO.

it's making the trait methods take priority over the inherent methods in some cases: Dirbaio/stm32f4xx-hal@091d945#diff-a49fe1ed5910761241be27a9c10bb8e11cac30ec0a80b839278ae3a1630384bcR102

It seems to be a consequence of the autoderef rules: rust-lang/rust#26007 . It happens when you mix &self with &mut self. Since the blanket impl is for &mut self, it matches "first" before Rust tries to autoderef.

I don't think this is especially bad. It might be annoying in HAL code, but non-generic end user code won't be importing the traits if they're indending to call inherent methods.

What should we do?

  • Change StatefulOutputPin to require &mut self
  • Remove that blanket impl.
  • Nothing.
@eldruin
Copy link
Member

eldruin commented Dec 21, 2021

Ugh. Ugly indeed. Nice catch, though.
What I would not do would be to change the StatefulOutputPin to get a &mut self since the methods have no side effects.
Now, why do we have a blanket impl for &mut T if the StatefulOutputPin methods only need &self?
Was this an oversight or would the blanket impl not be selected somehow due to the trait being StatefulOutputPin : OutputPin (and OutputPin requiring &mut self)?

@Dirbaio
Copy link
Member Author

Dirbaio commented Dec 21, 2021

Now, why do we have a blanket impl for &mut T if the StatefulOutputPin methods only need &self?

StatefulOutputPin requires OutputPin, so impl StatefulOutputPin for &T would require impl OutputPin for &T which can't be because OutputPin requires &mut self.

Perhaps another option is to make StatefulOutputPin not require OutputPin, and add a blanket impl for &T....? I'm not sure it fixes all cases of accidentally prioritzing the trait method though.

@Dirbaio
Copy link
Member Author

Dirbaio commented Dec 14, 2023

fixed by #547

@GrantM11235
Copy link
Contributor

For future reference, #547 didn't fix this, and it now affects InputPin as well as StatefulOutputPin.

We decided that this is okay because the problem is rare and the solution is easy: replace self.is_set_high() with (*self).is_set_high()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants