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

Conversion traits should emphasize their intended use and limitations #29701

Closed
Gankra opened this issue Nov 8, 2015 · 8 comments
Closed

Conversion traits should emphasize their intended use and limitations #29701

Gankra opened this issue Nov 8, 2015 · 8 comments
Labels
A-docs Area: documentation for any part of the project, including the compiler, standard library, and tools C-enhancement Category: An issue proposing an enhancement or a PR with one. P-medium Medium priority

Comments

@Gankra
Copy link
Contributor

Gankra commented Nov 8, 2015

The conversion traits, in my books, serve one primary role: convenient generic one-time conversions to a concrete type to make APIs "just work". For instance, fn foo<P: AsRef<Path>>(path: P) "just works" for the various kinds of string.

Invoking them in this kind of generic context is pretty much guaranteed to work because of the magic of trait resolution in generic contexts. However outside of this context, they can and will behave in wild and uncontrolled ways. There are two major issues I see:

  1. In concrete contexts, the pervasiveness of implementations of this trait means it will basically always do something, but deref coercions and inference mean that it's unlikely to be the thing you want, nor is it likely to do it in a stable manner. So for instance,

let x = y.as_ref() may plausibly yield y, &y, &*y, &**y, or some particular concrete impl depending on the type of y (and x?).

  1. You can't trust traits. Just because something implements AsRef and AsMut, doesn't mean they agree. Just because you called AsRef once before, doesn't mean the next call will yield the same result. These traits are for conversions -- not for building some kind of generic polymorphism framework on top of.
@Gankra Gankra added the A-docs label Nov 8, 2015
@Gankra
Copy link
Contributor Author

Gankra commented Nov 8, 2015

cc @aturon @SimonSapin

@SimonSapin
Copy link
Contributor

Sounds fair enough.

@SimonSapin
Copy link
Contributor

For context: this library has a struct that holds a value of generic type T that represents a bytes buffer. The first version used T: AsRef<[u8]> + AsMut<[u8]> until @bluss pointed out that bad impls could violate assumptions that library makes in unsafe code. I changed the bound to a custom unsafe trait.

@steveklabnik
Copy link
Member

part of #29349

@steveklabnik
Copy link
Member

@gankro Which traits should be included in this audit?

  • AsRef/AsMut
  • From/Into

Anything else?

@Gankra
Copy link
Contributor Author

Gankra commented Jan 9, 2016

Discussing Borrow/ToOwned might also be relevant? In particular when to use Borrow vs AsRef.

@gsnoff
Copy link

gsnoff commented Jun 29, 2016

There might be some traits that would just require consistency of the results of its method(s) to be deemed "trustworthy", and only the values of the arguments would be enough for calculating the results, neither any side effects need to occur. This looks suspiciously similar to limitations imposed on CTFE code - its results have to be consistent, it only has access to input arguments and can't cause side effects.

Basically, once CTFE is introduced in Rust (see rust-lang/rfcs#322), it might be reasonable to mark those methods in such traits as const fn, imposing the corresponding restrictions on its implementations. This is most likely going to break a few things in the ecosystem, however I'm not sure if the tradeoffs of this change would be really significant.

EDIT: Given that the current RFC for const fn has quite a lot of limitations imposed on allowed code and, consequently, possible use cases (no mutable references for non-zero-sized types means no const for AsMut, no control flow primitives means certain kinds of virtualization like enum pattern matching being impossible, &c.), this could be yet another incentive for adding a pure fn RFC which would not suffer from such limitations (see rust-lang/rfcs#1631).

@steveklabnik steveklabnik added the A-docs Area: documentation for any part of the project, including the compiler, standard library, and tools label Mar 10, 2017
@steveklabnik steveklabnik added the P-medium Medium priority label May 24, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 24, 2017
@steveklabnik
Copy link
Member

It is unclear to me how relevant this issue is today. It's been open for a really long time with no comments. We've re-done std::convert in the meantime. If there's any specific traits that need better explanations, please open new issues with details of what needs clarified. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-docs Area: documentation for any part of the project, including the compiler, standard library, and tools C-enhancement Category: An issue proposing an enhancement or a PR with one. P-medium Medium priority
Projects
None yet
Development

No branches or pull requests

5 participants