RFC 1358 suggested an alignment attribute #[repr(align="N")] and it was accepted. Rust issue 33626 incorporated the feature into the nightly version.
I'm unable to use this feature with rustc 1.19.0-nightly (777ee2079 2017-05-01). If I compile without the feature gate (#![feature(repr_align)]):
#[repr(align="16")]
struct Foo {
bar: u32,
}
I get the following error statement:
error: the struct `#[repr(align(u16))]` attribute is experimental (see issue #33626)
--> foo.rs:3:1
|
3 | / struct Foo {
4 | | bar: u32,
5 | | }
| |_^
|
= help: add #![feature(repr_align)] to the crate attributes to enable
When I compile with the feature gate, the error message says:
error[E0552]: unrecognized representation hint
--> foo.rs:3:8
|
3 | #[repr(align="16")]
| ^^^^^^^^^^
I also tried the version suggested by the first error message (even though it does not comply with the issue), but still without success. What is the correct way to use the alignment feature?
You can make that feature work when combined with
attribute literals (Playground):
#![feature(repr_align)]
#![feature(attr_literals)]
#[repr(align(16))]
struct Foo {
bar: u32,
}
This is known to work in the latest development version (PR #41673). Searching "repr align" in the Rust compiler's codebase,
all occurrences rely on attribute literals, so it seems likely that the documented form repr(align="N") is not yet supported.
Related
I want to be able to use Option<NonZeroU8> for its compact repr, but still be able to use 0.
Is there a way to use u8::MAX as the non-representable value instead of 0?
To truly get the niche optimization directly, you'd have to use the super unstable rustc_ attributes.
#![feature(rustc_attrs)]
#[rustc_layout_scalar_valid_range_start(0)]
#[rustc_layout_scalar_valid_range_end(254)]
struct NonMaxU8(u8);
fn main() {
dbg!(std::mem::size_of::<Option<NonMaxU8>>());
}
[src/main.rs:8] std::mem::size_of::<Option<NonMaxU8>>() = 1
I say "super unstable" because these attributes will never be stabilized, at least not in their current form. Using them without feature(rustc_attrs) will emit the following message:
error[E0658]: the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable niche optimizations in libcore and libstd and will never be stable
--> src/main.rs:3:1
|
3 | #[rustc_layout_scalar_valid_range_start(0)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
error[E0658]: the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable niche optimizations in libcore and libstd and will never be stable
--> src/main.rs:4:1
|
4 | #[rustc_layout_scalar_valid_range_end(254)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
There have been asks for compiler support for ranged integers, like the discussion here, but I don't think anything has been formally proposed as of yet.
There is the nonmax crate that provides this. See NonMaxU8 specifically. This works because it uses NonZeroU8 internally and does the appropriate conversion upon creation and the .get() method.
If you wanted a different variant, not just zero or max, you can easily make your own. The nonmax crate uses an XOR strategy to zero-out the non-representable value or use a modular arithmetic method like is suggested in the comments:
pub struct NonTenU8(NonZeroU8);
impl NonTenU8 {
const UNREPRESENTABLE: u8 = 10;
/// Creates a u8 value that cannot be ten.
pub fn new(value: u8) -> Option<Self> {
NonZeroU8::new(value ^ Self::UNREPRESENTABLE).map(Self)
// NonZeroU8::new(value.wrapping_sub(Self::UNREPRESENTABLE)).map(Self)
}
pub fn get(&self) -> u8 {
self.0.get() ^ Self::UNREPRESENTABLE
// self.0.get().wrapping_add(Self::UNREPRESENTABLE)
}
}
I want to define an enum using a macro. The enum needs to implement the strum traits {Display, EnumIter, EnumString}. I also want to keep the warnings missing_copy_implementations, missing_debug_implementations on. I came up with the following snippet:
#![warn(
missing_copy_implementations,
missing_debug_implementations,
)]
macro_rules! define_fruits {
{$($fruit:ident -> $name:literal),* $(,)?} => {
#[derive(Display, EnumIter, EnumString, Clone, Copy, Debug)]
pub enum Fruits {
$(
#[strum(to_string = $name)]
$fruit,
)*
}
};
}
define_fruits! {
Apple -> "green",
Orange -> "orange",
}
The above works fine except I get the warnings:
|
4 | missing_copy_implementations,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this warning originates in the macro `define_fruits` (in Nightly builds, run with -Z macro-backtrace for more info)
and similar for missing_debug_implementations.
These warnings go away when I remove Display, EnumIter, EnumString from my enum. They also go away if I define the same enum outside of a macro.
I cannot seem to find a way to get rid of the warnings in the above scenario, can someone help?
TL/DR: the problem is with derive(EnumIter), which isn't compatible with these lints. I've opened the issue on strum repository asking for possible changes.
To see what really happens, let's try to cargo expand the current code. After some simplification and stubbing out the unnecessary parts, we can see the following structure:
///An iterator over the variants of [Self]
pub struct FruitsIter {
idx: usize,
back_idx: usize,
marker: PhantomData<()>,
}
This is a type you get when you call IntoEnumIterator::iter derived for your enum. There's no Copy or Debug implementation for this struct - they are neither derived nor explicitly added by strum, so the lint sees the violation and fires.
A hint on the problem source can be seen when looking at the exact error, as provided by cargo check (or at the eror highlighting from rust-analyzer):
warning: type could implement `Copy`; consider adding `impl Copy`
--> src/lib.rs:10:27
|
10 | #[derive(Display, EnumIter, EnumString, Clone, Copy, Debug)]
| ___________________________^
11 | | pub enum Fruits {
| |___________^
Note that the span of the "erroneous" code starts from the EnumIter - since that's the token which the FruitsIter's span is tied to, warning on the FruitsIter is shown as a warning on the derive(EnumIter). And indeed, if we drop this derive - warning disappears.
There's nothing you can do with this, I'm afraid, aside from explicitly allowing these lints for the whole module containing your enum. This is something that should probably be fixed by the strum maintainers.
I've tried:
#[enum_dispatch(BarTrait, BazTrait)]
pub enum Foo {
VariantZero,
...
}
It seems to ignore any traits after the first, silently.
This causes errors, as in this case the compiler doesn't seem to believe that Foo implements BazTrait.
Update: #kmdreko's code works properly so long as BazTrait is in the same crate as Foo.
When BazTrait is in a different crate, which also uses enum_dispatch, BazTrait is ignored and causes two errors of the form:
error[E0599]: no method named `baz` found for enum `Foo` in the current scope
--> src/main.rs:53:9
|
45 | enum Foo {
| -------- method `baz` not found for this
...
53 | foo.baz();
| ^^^ method not found in `Foo`
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `baz`, perhaps you need to implement it:
candidate #1: `mylib::BazTrait`
It is important to note that there is no error at either #[enum_dispatch(BarTrait, BazTrait)] or pub enum Foo {.
The #[enum_dispatch] attribute does not work across crates:
Unfortunately, procedural macros in Rust are limited in a few ways that will make what you're trying to achieve impossible - notably, they are run independently per-crate, so there's no way for information from one crate to affect an implementation in another.
From the author of enum_dispatch in an unrelated issue.
This question already has an answer here:
Why do I need to import a trait to use the methods it defines for a type?
(1 answer)
Closed 2 years ago.
I'm stuck on the first example given in the Rust book, the guessing game. I just cannot find the gen_range method on thread_rng() to generate the number. The only methods that show up are fill_bytes, next_u32, next_u64 and try_fill_bytes, and if I try to write it anyway I get an error saying the method doesn't exist. However, when I tried the random function, which according to the documentation is simply a shortcut for thread_rng().gen(), it works. I've tried other functions, updating and reinstalling everything but it still doesn't work and I really don't know what to do.
Welcome to Stack Overflow. In the future, please try to add more information to your question, including relevant links (which doc are you talking about), source code and error messages. This will make it easier for us to give relevant and useful answers.
I'm assuming you're doing something like this:
use rand::thread_rng;
fn main() {
let x = thread_rng().gen_range(0, 10);
println!("{}", x);
}
Playground
Which gives the following error:
error[E0599]: no method named `gen_range` found for struct `rand::rngs::thread::ThreadRng` in the current scope
--> src/main.rs:4:26
|
4 | let x = thread_rng().gen_range(0, 10);
| ^^^^^^^^^ method not found in `rand::rngs::thread::ThreadRng`
|
::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.7.3/src/lib.rs:212:8
|
212 | fn gen_range<T: SampleUniform, B1, B2>(&mut self, low: B1, high: B2) -> T
| ---------
| |
| the method is available for `std::boxed::Box<rand::rngs::thread::ThreadRng>` here
| the method is available for `std::sync::Arc<rand::rngs::thread::ThreadRng>` here
| the method is available for `std::rc::Rc<rand::rngs::thread::ThreadRng>` here
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
1 | use rand::Rng;
|
Note that the Rust compiler is very good in giving suggestions for ways to fix your code. In this case, the last line from the error suggests adding use rand::Rng;, and now it works:
use rand::Rng;
use rand::thread_rng;
fn main() {
let x = thread_rng().gen_range(0, 10);
println!("{}", x);
}
Playground
This is because the gen_range method is not implemented directly on the ThreadRng struct, but instead it is implemented in the general Rng trait, which makes it automatically available for all random number generators. However methods from traits are only available if the trait itself is available, hence the need to import rand::Rng first.
You can try installing the the following version, works for me in this version.
Add this to your Cargo.toml dependencies:
rand = "0.7.3"
Import:
use rand::Rng;
Usage:
rand::thread_rng().gen_range(0, 10);
I am trying to output the contents of a syn::Expr to the console, but get the following error:
error[E0599]: no method named `to_string` found for type `&syn::Expr` in the current scope
--> derive/src/lib.rs:165:40
|
165 | println!("Expression: {:#?}", expr.to_string());
| ^^^^^^^^^
|
= note: the method `to_string` exists but the following trait bounds were not satisfied:
`syn::Expr : std::string::ToString`
`&syn::Expr : std::string::ToString`
`syn::Expr : std::string::ToString`
It is not clear to me what "trait bounds" are or how to satisfy them. Are there any easy ways to output the contents of this variable?
syn::Expr is documented as implementing the Debug trait, so you use the Debug formatter:
extern crate syn; // 0.15.4
fn example(expr: syn::Expr) {
println!("{:#?}", expr);
}
However, all Debug implementations in syn are guarded by the Cargo feature extra-traits. So in order to use those Debug impls, you have to specifically enable that feature in your Cargo.toml:
[dependencies]
syn = { version = "0.15", features = ["extra-traits"] }
You can read more about syn's optional Cargo features in their README.
See also:
How do I print variables in Rust and have it show everything about that variable, like Ruby's .inspect?
What is the difference between println's format styles?
Should I implement Display or ToString to render a type as a string?
Does println! borrow or own the variable?