Rfcs: Create an empty "Primitive" trait implemented by primitive (and only primitive) types to improve inferring "as" availability in generics

Created on 13 Jan 2018  路  8Comments  路  Source: rust-lang/rfcs

I've been trying to do something along the lines of:

fn foo<T> (buffer: &[u8]) {
  let foo: T = SomeTValue();
  &[0..foo as usize]
}

And discovered that as won't work there and there seems to be no way to add a 'where' bound to the T type to make sure the compiler accepts "as" here knowing that it'll work because it cannot infer that T is a primitive type.

Having a trait that allows type bounds would be handy here to let the compiler know that the code should work.

T-lang T-libs

Most helpful comment

try_into doesn't cut it either

error: use of unstable library feature 'try_from' (see issue #33417)
 --> src/main.rs:3:5
  |
3 | use std::convert::TryInto;
  |     ^^^^^^^^^^^^^^^^^^^^^

error: use of unstable library feature 'try_from' (see issue #33417)
   --> src/main.rs:219:72
    |
219 |       let upper_bound: usize = <T>::from_gvariant(buffer, upper_index).try_into().expect("pointer size not supported");
    |                                                                        ^^^^^^^^

error: use of unstable library feature 'try_from' (see issue #33417)
   --> src/main.rs:220:72
    |
220 |       let lower_bound: usize = <T>::from_gvariant(buffer, lower_index).try_into().expect("pointer size not supported");
    |                                                                        ^^^^^^^^

error[E0277]: the trait bound `usize: std::convert::From<u16>` is not satisfied
   --> src/main.rs:231:12
    |
231 |     return get_value_slice_for_size::<u16> (buffer, index);
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<u16>` is not implemented for `usize`
    |
    = help: the following implementations were found:
              <usize as std::convert::From<u8>>
    = note: required by `get_value_slice_for_size`

error[E0277]: the trait bound `usize: std::convert::From<u32>` is not satisfied
   --> src/main.rs:234:12
    |
234 |     return get_value_slice_for_size::<u32> (buffer, index);
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<u32>` is not implemented for `usize`
    |
    = help: the following implementations were found:
              <usize as std::convert::From<u8>>
    = note: required by `get_value_slice_for_size`

error[E0277]: the trait bound `usize: std::convert::From<u64>` is not satisfied
   --> src/main.rs:237:12
    |
237 |     return get_value_slice_for_size::<u64> (buffer, index);
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<u64>` is not implemented for `usize`
    |
    = help: the following implementations were found:
              <usize as std::convert::From<u8>>
    = note: required by `get_value_slice_for_size`

error: aborting due to 6 previous errors

All 8 comments

I doubt Primitive would be specific enough for this use case since u128: Primitve, but this works:

fn foo<T: Into<usize>> (buffer: &[u8]) {
  &[0..SomeTValue::<T>().into()]
}

I think the search for the ideal numeric traits arrangement is ongoing.

That certainly doesn't work as you get something like this when you try to use it on u16/u32/u64:

236 |     return get_value_slice_for_size::<u64> (buffer, index);
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<u64>` is not implemented for `usize`

You make a good point about about Fundamental not being enough in this particular case (f64 being prolly a better example than u128 as a 128 architecture might actually exist as a target), perhaps my particular suggestion is not a good one, but certainly there is something here that needs fixing as "as" is something the compiler accepts for all these types. At the moment I find myself doing this ugly approach to satisfy the compiler:

let lower_bound = match mem::size_of::<T> () {
        1 => { <u8>::from_gvariant(buffer, lower_index) as usize }
        2 => { <u16>::from_gvariant(buffer, lower_index) as usize }
        4 => { <u32>::from_gvariant(buffer, lower_index) as usize }
        8 => { <u64>::from_gvariant(buffer, lower_index) as usize }
        _ => { panic!("pointer size bigger than 64 bit not supported"); }
      };

Would TryInto<usize> work for you?

It's odd that usize: From<u8> but not From<u16> or From<u32>. We cannot have usize: From<u64> anyways due to 32 bit platforms. Anyways .try_into().expect("excessed pointer size") works.

try_into doesn't cut it either

error: use of unstable library feature 'try_from' (see issue #33417)
 --> src/main.rs:3:5
  |
3 | use std::convert::TryInto;
  |     ^^^^^^^^^^^^^^^^^^^^^

error: use of unstable library feature 'try_from' (see issue #33417)
   --> src/main.rs:219:72
    |
219 |       let upper_bound: usize = <T>::from_gvariant(buffer, upper_index).try_into().expect("pointer size not supported");
    |                                                                        ^^^^^^^^

error: use of unstable library feature 'try_from' (see issue #33417)
   --> src/main.rs:220:72
    |
220 |       let lower_bound: usize = <T>::from_gvariant(buffer, lower_index).try_into().expect("pointer size not supported");
    |                                                                        ^^^^^^^^

error[E0277]: the trait bound `usize: std::convert::From<u16>` is not satisfied
   --> src/main.rs:231:12
    |
231 |     return get_value_slice_for_size::<u16> (buffer, index);
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<u16>` is not implemented for `usize`
    |
    = help: the following implementations were found:
              <usize as std::convert::From<u8>>
    = note: required by `get_value_slice_for_size`

error[E0277]: the trait bound `usize: std::convert::From<u32>` is not satisfied
   --> src/main.rs:234:12
    |
234 |     return get_value_slice_for_size::<u32> (buffer, index);
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<u32>` is not implemented for `usize`
    |
    = help: the following implementations were found:
              <usize as std::convert::From<u8>>
    = note: required by `get_value_slice_for_size`

error[E0277]: the trait bound `usize: std::convert::From<u64>` is not satisfied
   --> src/main.rs:237:12
    |
237 |     return get_value_slice_for_size::<u64> (buffer, index);
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<u64>` is not implemented for `usize`
    |
    = help: the following implementations were found:
              <usize as std::convert::From<u8>>
    = note: required by `get_value_slice_for_size`

error: aborting due to 6 previous errors

Num has added a trait that fits the use case described: https://github.com/rust-num/num-traits/pull/17, if you're really looking for the as conversion operator.

I thought of something similar, here is my idea:
Permit to use the as keyword on every type that implement From<T>.
This could be like the +, -, * and *(for deref) operators for example.

The From trait is in the core so this doesn't seem to be a problem at this level.

What do you think ?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

torkleyy picture torkleyy  路  3Comments

p-avital picture p-avital  路  3Comments

marinintim picture marinintim  路  3Comments

yongqli picture yongqli  路  3Comments

mqudsi picture mqudsi  路  3Comments