# Maybe-RFC: trait for \`as\` casting

**URL:** <https://internals.rust-lang.org/t/maybe-rfc-trait-for-as-casting/10419>\
**Category:** language design\
**Created:** [June 17, 2019, 6:43pm UTC](https://internals.rust-lang.org/t/maybe-rfc-trait-for-as-casting/10419 "2019-06-17T18:43:17Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![CodeSandwich](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/codesandwich/32/3479_2.png) [@CodeSandwich](https://internals.rust-lang.org/u/CodeSandwich)\
**Post date:** [June 17, 2019, 6:43pm UTC](https://internals.rust-lang.org/t/maybe-rfc-trait-for-as-casting/10419/1 "2019-06-17T18:43:17Z")

</div>

This is a maybe-RFC, because I’m not even sure if the idea is actually as interesting as it seems to me.

# Idea

To create an `As` trait, which represents possibility of casting with `as` keyword:

```rust
trait As<T> {
    fn as(self) -> T;
}

```

By default the trait is defined in stdlib for all types that can be casted with an `as` keyword.

# Motivation

Currently there’s no way to define a type that is castable to another one. One can’t write a generic structure that holds anything castable to u32. Or a function that accepts fn item that can be casted to a specific fn pointer.

Another thing is elevation of `as` keyword to a fully functional operator, that can be defined by user for types, same as `+`, `[]` and `?`. Automatic coercion between custom types becomes a thing.

This potentially makes the experimental `CoerceUnsized` trait fully covered and obsolete.

---

<div class="post-metadata">

**Author:** ![H2CO3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/h2co3/32/2849_2.png) [@H2CO3](https://internals.rust-lang.org/u/H2CO3)\
**Post date:** [June 17, 2019, 7:18pm UTC](https://internals.rust-lang.org/t/maybe-rfc-trait-for-as-casting/10419/2 "2019-06-17T19:18:03Z")

</div>

> [@CodeSandwich](#):
>
> Currently there’s no way to define a type that is castable to another one

Why aren't `From` and `Into` good enough for this purpose? These are the standard traits with which user-defined conversions are supposed to be defined.

---

<div class="post-metadata">

**Author:** ![CodeSandwich](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/codesandwich/32/3479_2.png) [@CodeSandwich](https://internals.rust-lang.org/u/CodeSandwich)\
**Post date:** [June 17, 2019, 9:00pm UTC](https://internals.rust-lang.org/t/maybe-rfc-trait-for-as-casting/10419/3 "2019-06-17T21:00:01Z")

</div>

`From` and `Into` are definitely enough. Yet some conversions are defined with `as` and that gives them automatic coercion.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [June 17, 2019, 9:00pm UTC](https://internals.rust-lang.org/t/maybe-rfc-trait-for-as-casting/10419/4 "2019-06-17T21:00:02Z")

</div>

This has come up many times; the core problem is that `as` is too random in the kinds of things that it does to be usable generically.

Personally, I’d like to see subsets, like the `WrappingFrom` in

> <https://github.com/rust-lang/rfcs/pull/2484>

Since that at least has a justifiable semantics instead of “do something to turn a thing into a thing and who knows what will happen”.

---

<div class="post-metadata">

**Author:** ![197g](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/197g/32/7276_2.png) [@197g](https://internals.rust-lang.org/u/197g)\
**Post date:** [June 18, 2019, 6:44am UTC](https://internals.rust-lang.org/t/maybe-rfc-trait-for-as-casting/10419/5 "2019-06-18T06:44:20Z")

</div>

Why a new trait in particular? For integers a wrapper type alone could suffice.

```rust
struct WrappingU16(u16);

impl From<WrappingU16> for u8 { … }

impl u16 {
    pub fn wrapping(self) -> WrappingU16 { WrappingU16(self) }
}

let x: u16 = 0;
let y: u8 = x.wrapping().into();

```

---

<div class="post-metadata">

**Author:** ![CodeSandwich](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/codesandwich/32/3479_2.png) [@CodeSandwich](https://internals.rust-lang.org/u/CodeSandwich)\
**Post date:** [June 18, 2019, 8:01am UTC](https://internals.rust-lang.org/t/maybe-rfc-trait-for-as-casting/10419/6 "2019-06-18T08:01:26Z")

</div>

The wrapper is going to work in non-generic case, but it’s a workaround adding custom cruft to code. The new trait is clean, global and generic solution. At least it’s supposed to be.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [June 20, 2019, 3:58am UTC](https://internals.rust-lang.org/t/maybe-rfc-trait-for-as-casting/10419/7 "2019-06-20T03:58:13Z")

</div>

> [@197g](#):
>
> Why a new trait in particular? For integers a wrapper type alone could suffice.

Because coherence. (`std::num::Wrapping` isn't fundamental.)

It's legal to

```rust
impl From<i32> for Foo { ... }

```

But using wrapping you get

```rust
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
 --> src/lib.rs:6:1
  |
6 | impl From<Wrapping<i32>> for Wrapping<Foo> {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate

```

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [September 18, 2019, 4:05am UTC](https://internals.rust-lang.org/t/maybe-rfc-trait-for-as-casting/10419/8 "2019-09-18T04:05:07Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
