Conditional compilation based on proc_macro - rust

Is it possible to somehow detect in a crate that it's used in proc_macro and include some items based on that?
Let's say I have a token_parser crate with a Token enum:
pub struct Group;
pub struct Ident;
pub struct Punct;
pub struct Literal;
pub enum Token {
Group(Group),
Ident(Ident),
Punct(Punct),
Literal(Literal)
}
It's intended to be a wrapper for a proc_macro::TokenTree, so I want to be able to use it inside a proc_macro crates. I don't want to manualy implement a converting logic in every crate, so I want something like this:
#[cfg(proc_macro)]
impl From<proc_macro::TokenTree> for Token {
fn from(token: proc_macro::TokenTree) -> Self
{
todo!()
}
}
while still having an option to use token_parser crate in normal crates.
P.S I'm aware of proc_macro2 crate. I will probably use it (or even syn) in the end, for now I'm just trying to understand how to do something like that myself properly.

There are primarily two ways I would reach for based on how I want to enable such functionality.
feature for project-based enabling
If you want it only available when opted for, that's a fantastic case to use a cargo feature. Crates that want to use such functionality can then choose to enable this feature while other crates can choose to not enable the feature. Whether this feature should be default typically depends on how the library author believes it should/is used most of the time.
cfg for platform-based enabling
As you may have seen from reading the proc_macro2 source, they conditionally enable a cfg in their build script1. On the wasm32 platform target it is disabled, otherwise it is enabled. This way is very useful in cases where enabling functionality mostly depends on the platform.

Related

What's the best way to use `test::TestDescAndFn` without using libtest?

I'm working on a custom test-runner for a custom target, that doesn't have libtest available. However I would like to use the TestDescAndFn struct, which is defined in libtest, in my own test-runner. TestDescAndFn provides information about the tests such as if it should panic or not, the name of the test and others, so having this information would be really useful compared to just using #[test_case].
Since the #[test] annotation is resolved at compile-time and simply generates a test harness that calls a (custom) test-runner I can define with #![test_runner(my_test_runner)], I don't think I really need libtest aside from TestDescAndFnand the enums it contains. Is there any "good" way to use the definitions from libtest for TestDescAndFn, TestDesc etc., without actually building libtest?
The test crate provides TestDescAndFn and is provided by the compiler. So, your custom framework crate might do something like this:
#![feature(test)]
// provided by compiler, no need to specify dependency in Cargo.toml
extern crate test;
use ::test::TestDescAndFn;
pub fn run_tests(tests: &[&TestDescAndFn]) {
// ...
}
and then your crate under test would do this:
#![feature(custom_test_frameworks)]
#![test_runner(::my_framework::run_tests)]
// crate with #[test] as normal

Rust: the usage of "self" when bringing paths into scope

mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
use self::front_of_house::hosting;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
hosting::add_to_waitlist();
hosting::add_to_waitlist();
}
The code is from Rust Book. In this case, if using the relative path, why bother to use self? I find that use front_of_house::hosting works well here.
So, any necessary reason to introduce self here?
The outcome of use front_of_house::hosting depends on the context. If the crate root contains extern crate front_of_house or front_of_house is a dependency in Cargo.toml, this will refer to hosting in that crate. In your case, however, there is the local module front_of_house, which takes priority over external crates. Conveniently, it's located just before the code that uses it, so it's obvious that it's the actual module being used. In larger files, however, there is a chance that the source of a module is ambiguous, i.e. if there is a dependency named the same as a local module. In that case, the extra self adds clarity to the code, helping you differentiate between dependencies and local modules. If, in that case, you wanted to use the dependency, you'd use ::front_of_house::hosting, which unconditionally refers to the dependency and fails if there isn't one named like that.

How to properly reference the same code as a dependency of a dependency?

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());
}
}

Conditionally derive based on feature flag [duplicate]

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.

How to link to other fns/structs/enums/traits in rustdoc?

I'm building a Rust library and want to give it some polish. In the rustdoc, I'd sometimes like to link to other parts of the library within the docs, e.g. fns, traits or structs. What is the official syntax for this?
As of Rust 1.48, you can now rely on RFC 1946. This adds the concept of intra-documentation links. This allows using Rust paths as the URL of a link:
[Iterator](std::iter::Iterator)
[Iterator][iter], and somewhere else in the document: [iter]: std::iter::Iterator
[Iterator], and somewhere else in the document: [Iterator]: std::iter::Iterator
The RFC also introduces "Implied Shortcut Reference Links". This allows leaving out the link reference, which is then inferred automatically.
[std::iter::Iterator], without having a link reference definition for Iterator anywhere else in the document
[`std::iter::Iterator`], without having a link reference definition for Iterator anywhere else in the document (same as previous style but with back ticks to format link as inline code)
As a concrete example, this source code:
//! Check out [ExampleStruct], especially [this
//! method](ExampleStruct::foo), but [the trait method][trait] is also
//! cool. There is also [an enum variant you can
//! use](nested::ExampleEnum::Beta).
//!
//! [trait]: ExampleTrait::bar
pub struct ExampleStruct;
impl ExampleStruct {
pub fn foo(&self) {}
}
pub trait ExampleTrait {
fn bar();
}
pub mod nested {
pub enum ExampleEnum {
Alpha,
Beta,
}
}
Produces this documentation:
Specifically, this HTML is generated:
<p>Check out ExampleStruct, especially this method, but the trait method is also cool. There is also an enum variant you can use.</p>
As of Rust 1.48, Rustdoc now supports direct intra-doc links.
Pre Rust 1.48:
Rustdoc seems to generate mostly deterministic filenames for constituent elements of a crate. Therefore if you have an enum named Complex you can generally link to it using:
[Complex](enum.Complex.html)
Similarly a struct called Point would look like:
[Point](struct.Point.html)
This should carry over to most definitions (fn, trait, and so on).
For referencing elements of a crate at different nesting levels, you can use relative paths (where each module is its own folder):
[Point](../model/struct.Point.html)
or use absolute paths:
[Point](/crate_name/model/struct.Point.html)
More of these "conventions", including anchors for specific fields, etc., can be deduced if one builds docs (cargo doc --no-deps --open) and navigates to the field or item they want and takes note of the URL. Remember that only pub items are published to docs.
If one wants to link some specific part of a struct e.g., a method named foo in the same struct (using stable rust, not nightly)
[foo](#method.foo)
or if it is in another struct
[foo](struct.OtherStruct.html#method.foo)
In Rust 1.49 nightly it works (1.48 stable not released yet):
[super::structs::WebApiResponse]
[mycrate::structs::WebApiResponse]
etc.
Read here
Since the documentation is written in Markdown, just use the Markdown syntax for Hyperlinks; i.e.
[anchor text](URL)
Also, take a look at this: https://doc.rust-lang.org/book/documentation.html

Resources