Rust 1.63 stabilized const std::sync::Mutex::new(). Till date to have global flag preventing parallel execution would look like (example):
use once_cell::sync::Lazy;
static GLOBAL_FLAG: Lazy<Mutex<()>> = Lazy::new(Default::default);
while in since 1.63 it can look like this and the dependency isn't required anymore in Cargo.toml:
static GLOBAL_FLAG: Mutex<()> = Mutex::new(());
Now, the question is how to make use of both conditionally, depending on either:
which version of the compiler is used to build the crate
or
whether the feature is stable (I struggle to find it's correct name at the moment)?
I was looking at cfg_rust_features crate, but the part where dependency isn't required by Cargo.toml remains mystery. Any hints welcome.
This is typically accomplished by:
Detecting the Rust version (using rustversion/rustc_version) or the required feature (using autocfg),
Making the fallback dependency (once_cell) optional, and
Emitting an error if the required Rust feature is missing and the fallback dependency is also missing.
For example, using rustversion:
#[rustversion::since(1.63)]
mod private {
use std::sync::Mutex;
pub static GLOBAL_FLAG: Mutex<()> = Mutex::new(());
}
#[rustversion::before(1.63)]
#[cfg(feature = "once_cell")]
mod private {
use once_cell::sync::Lazy;
use std::sync::Mutex;
pub static GLOBAL_FLAG: Lazy<Mutex<()>> = Lazy::new(Default::default);
}
#[rustversion::before(1.63)]
#[cfg(not(feature = "once_cell"))]
compile_error!(
"The \"once_cell\" feature must be enabled for Rust compiler versions prior to 1.63."
);
When compiling on 1.62 without once_cell, this emits
error: The "once_cell" feature must be enabled for Rust compiler versions prior to 1.63.
--> src/main.rs:18:1
|
18 | / compile_error!(
19 | | "The \"once_cell\" feature must be enabled for Rust compiler versions prior to 1.63."
20 | | );
| |_^
Note: the use of mod private seen above is not strictly necessary, but it reduces the number of attributes and ensures that the relevant compile error is the only error emitted. You can pub use private::GLOBAL_FLAG to put it back in scope.
Related
Let's assume I have the following feature defined in Cargo.toml:
[features]
my_feature = []
And the following code lives in src/lib.rs:
#[cfg(feature = "my_feature")]
fn f() { /* ... */ }
#[cfg(not(feature = "my_faeture"))] // <-- Mind the typo!
fn f() { /* ... */ }
How can I enforce, that the feature-strings are matched against the list of both explicitly defined and implicitly available features in Cargo.toml so that for instance typos could be avoided?
When RFC 3013, "Checking conditional compilation at compile time", is implemented, there will be warnings for a #[cfg] referring to a feature name that is not declared by Cargo, just as you're asking for. However, the implementation only just got started (Sep 28, 2021).
The means of operation described in the RFC is just as you suggested, ‘cargo would pass down the flags to rustc’.
It may be worth noting that this will not check all conditions appearing in the source text; as described in the RFC:
This lint will not be able to detect invalid #[cfg] tests that are within modules that are not compiled, presumably because an ancestor mod is disabled.
So, it will not confirm that all #[cfg(feature)] are valid on a single cargo check — you will need to test with your various features or combinations of features. But those are the same combinations that you would need anyway to check for compile errors in all of the regular source code that could be enabled; once you do that, the lint will assure you that you don't have any #[cfg(feature)] that are never enabled due to a typo.
I'm very new to rust's syntax of using libraries. Well, mostly new to rust overall.
I've included a library, that is unfinished, and seemingly doesn't work. The library is called "hours", the lib.rs contains the following:
// #[derive(Clone, Debug, PartialEq, Eq)]
pub struct Hours {
pub rules: Vec<types::RuleSequence>,
pub tz: Tz,
}
impl Hours {
pub fn from(s: &str, tz: Tz) -> Result<Self, String> {
//... abbreviated
}
pub fn at(self: &Self, dt: &DateTime<Tz>) -> types::Modifier {
//... abbreviated
}
}
It is included in Cargo.toml: relevant lines:
edition = "2018"
[dependencies]
hours = "0.0.1"
I want to know if it is possible to include and use the from() function, so far, I'm without luck. Here's what I tried:
use hours;
fn main() {
//... abbreviated
let hours = Hours::from(example_hrs, Amsterdam).unwrap();
}
Gives compile error: Hours::from(example_hrs, Amsterdam).unwrap(); ^^^^^ use of undeclared type or moduleHours``
use hours::Hours;
fn main() {
//... abbreviated
let hours = Hours::from(example_hrs, Amsterdam).unwrap();
}
Gives compile error: use hours::Hours; ^^^^^^^^^^^^ no ``Hours`` in the root
use hours;
fn main() {
//... abbreviated
let hours = hours::Hours::from(example_hrs, Amsterdam).unwrap();
}
Gives compile error: hours::Hours::from(example_hrs, Amsterdam).unwrap(); ^^^^^ could not findHoursinhours``
Is there any way to include and use this library? Do I need to change the library, or am I simply using it wrong?
Problem in here, the code in repository link you've shared doesn't match with the dependency in crates.io and naturally Rust can't find the required api components. In this case owner of the crate hasn't published the code in gitlab yet.
To see that you can quickly check the source from the docs.rs. This is the link for the required dependency docs.rs/crate/hours/0.0.1/source/.
If you want to use the current code in the repository
you may have it locally by downloading(or using git clone) then you can use it by specifying the path in cargo.toml
Or define git repository directly in cargo toml.
hours = { git = "https://gitlab.com/alantrick/hours.git", rev="7b7d369796c209db7b61db71aa7396f2ec59f942"}
Adding revision number or tag might help since the updates on master branch may break the compatibility.
Why this source in docs.rs is accurate with crates.io ?
Please check the about section in docs.rs :
Docs.rs automatically builds crates' documentation released on
crates.io using the nightly release of the Rust compiler
This means it is synchronized with crates.io.
To be sure you can also check the crate's source from a local repository cache.
## Note that this path is built with default cargo settings
$HOME/.cargo/registry/src/github.com-1ecc6299db9ec823/hours-0.0.1
^^^^^^^^^^^^^^^^^^^^^^^^^^^ github reigstry for crates io
Why crate's repository link in crates.io doesn't match with the crate's source
Please check the publishing crate reference, repository information is specified in package's metadata(in cargo.toml).
According to package metadata reference these information are used for :
These URLs point to more information about the package. These are
intended to be webviews of the relevant data, not necessarily compatible
with VCS tools and the like.
documentation = "..."
homepage = "..."
repository = "..."
You may also check the popular crates as well, they point their github(usually) main page which points master branch, not a tag of the current version.
I've got a toy project that's using the Amethyst game engine. I'm trying to write my own System for collecting user input, similar to the FlyMovementSystem and ArcBallRotationSystem they have implemented here.
It appears the right way to go about collecting mouse movements is via an EventChannel<Event>, where Event comes from the winit crate, which Amethyst depends on, but does not re-export.
What's the "right" way to reference the same winit::Event that Amethyst does?
Should I add winit to my Cargo.toml file? If so, what is the recommended way to specify the version? (Is there some keyword I can use instead of a specific version number, to allow me to "inherit" the dependency from Amethyst?)
Is referencing sub-dependencies actually discouraged? If so, what should I be doing instead?
There is currently no great solution to this problem. The best workaround is to add a direct dependency on the same version of the transitive dependency:
[dependencies]
foo = "0.1"
bar = "0.2" # `foo` depends on bar 0.2 and we need to keep these in sync
You can use tools like cargo tree to manually identify the versions needed by foo and keep your Cargo.toml up to date. I highly recommend adding a comment specifying why you've picked a specific version.
If the crate is very difficult to use without also using the underlying dependency alongside it, I'd also encourage you to file an issue with the parent crate to request that they re-export what is needed. A good example of this is the Tokio crate, which re-exports large chunks of the futures crate.
Similar to your idea, I proposed having a way to use the same version as a dependency. Instead, the Cargo team opted to add the distinction of public and private dependencies. While this will be a better solution from an engineering point of view, very little progress has been made on the implementation of it.
See also:
Why is a trait not implemented for a type that clearly has it implemented?
I'm leaving #Shepmaster's answer as the accepted one, as it answers the general question I was going for. But thanks to a gentle push from #trentcl, in case anyone found this question specifically for its relation to Amethyst, here's what I ended up doing.
Don't try to get the winit::Events at all.
When you attach an InputBundle<AX, AC> to your GameData, it sets up an InputSystem<AX, AC>, which re-publishes winit::Events in the form of InputEvent<AC>.
It does this by setting up an EventChannel<InputEvent<AC>> as a Resource, which you can access via the Read type in the ECS system. EventChannels and their usage are explained in the Amethyst Book.
I've since switched to a different approach for handling my user input, but here's roughly what it looked like (note: Amethyst a little after v0.10.0):
pub struct MouseMovementSystem {
reader: Option<ReaderId<InputEvent<()>>>, // AC = ()
}
impl<'s> System<'s> for MouseMovementSystem {
type SystemData = (
Read<'s, EventChannel<InputEvent<()>>>,
/* and others */
}
fn run(&mut self, (events, /* and others */): Self::SystemData) {
let foo = events.read(self.reader.as_mut().unwrap())
.yadda_yadda(/* ... */); // event processing logic
do_stuff(foo);
}
fn setup(&mut self, res: &mut Resources) {
use amethyst::core::specs::prelude::SystemData;
Self::SystemData::setup(res);
self.reader = Some(res.fetch_mut::<EventChannel<InputEvent<()>>>().register_reader());
}
}
I am using raw-cpuid crate for a project. It uses raw::Slice structure in processor_brand_string() function of ExtendedFunctionInfo structure.
let slice = raw::Slice { data: brand_string_start, len: 3*4*4 };
The above statement doesn't compile. It aborts with this error
cannot find struct, variant or union type `Slice` in module `raw`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/raw-cpuid-2.0.0/src/lib.rs:435:25
|
435 | let slice = raw::Slice { data: brand_string_start, len: 3*4 };
| ^^^^^^^^^^ not found in `raw`
The crate uses no_std attribute. The Rust book says
When we’re using the standard library, Rust automatically brings std
into scope, allowing you to use its features without an explicit
import. By the same token, when using #![no_std], Rust will bring core
into scope for you, as well as its prelude. This means that a lot of
code will Just Work.
I checked the core crate and it has Slice structure in the raw module. I have searched for any resolution of this error but I couldn't find one and me being new to Rust am unable to figure out what to do. I don't think many have used this crate but any help is appreciated. Thanks
This question already has an answer here:
Is it possible to conditionally enable an attribute like `derive`?
(1 answer)
Closed 2 years ago.
I want to add a feature to my crate that will optionally make certain structs serializable, and in particular, I want to use Serde's custom derive macros. The Serde dependencies are optional and extern crate declarations are conditionally included behind the feature. Consider the following:
#[derive(Eq, PartialEq, Serialize)]
struct MyStruct {
a: u8,
b: u8
}
With the feature flag enabled, it all works fine. With it disabled, I get this warning:
error: '#[derive]' for custom traits is not stable enough for use. It is deprecated and will be removed in v1.15 (see issue #29644)
Is there a way to conditionally include derived traits? I'm using Rust 1.15 stable.
Should I submit an issue for the error message? It seems misleading.
Like many other pieces of feature-based conditional compilation, use cfg_attr:
#[cfg_attr(feature = "example", derive(Debug))]
struct Foo;
fn main() {
println!("{:?}", Foo);
}
With this, cargo run will fail to compile as Debug is not implemented for Foo, but cargo run --features example will compile and run successfully.