How do I use Rust macros in the same crate? [duplicate] - rust

I have two modules in separate files within the same crate, where the crate has macro_rules enabled. I want to use the macros defined in one module in another module.
// macros.rs
#[macro_export] // or not? is ineffectual for this, afaik
macro_rules! my_macro(...)
// something.rs
use macros;
// use macros::my_macro; <-- unresolved import (for obvious reasons)
my_macro!() // <-- how?
I currently hit the compiler error "macro undefined: 'my_macro'"... which makes sense; the macro system runs before the module system. How do I work around that?

Macros within the same crate
New method (since Rust 1.32, 2019-01-17)
foo::bar!(); // works
mod foo {
macro_rules! bar {
() => ()
}
pub(crate) use bar; // <-- the trick
}
foo::bar!(); // works
With the pub use, the macro can be used and imported like any other item. And unlike the older method, this does not rely on source code order, so you can use the macro before (source code order) it has been defined.
Old method
bar!(); // Does not work! Relies on source code order!
#[macro_use]
mod foo {
macro_rules! bar {
() => ()
}
}
bar!(); // works
If you want to use the macro in the same crate, the module your macro is defined in needs the attribute #[macro_use]. Note that macros can only be used after they have been defined!
Macros across crates
Crate util
#[macro_export]
macro_rules! foo {
() => ()
}
Crate user
use util::foo;
foo!();
Note that with this method, macros always live at the top-level of a crate! So even if foo would be inside a mod bar {}, the user crate would still have to write use util::foo; and not use util::bar::foo;. By using pub use, you can export a macro from a module of your crate (in addition to it being exported at the root).
Before Rust 2018, you had to import macro from other crates by adding the attribute #[macro_use] to the extern crate util; statement. That would import all macros from util. This syntax should not be necessary anymore.

Alternative approach as of 1.32.0 (2018 edition)
Note that while the instructions from #lukas-kalbertodt are still up to date and work well, the idea of having to remember special namespacing rules for macros can be annoying for some people.
EDIT: it turns out their answer has been updated to include my suggestion, with no credit mention whatsoever ๐Ÿ˜•
On the 2018 edition and onwards, since the version 1.32.0 of Rust, there is another approach which works as well, and which has the benefit, imho, of making it easier to teach (e.g., it renders #[macro_use] obsolete). The key idea is the following:
A re-exported macro behaves as any other item (function, type, constant, etc.): it is namespaced within the module where the re-export occurs.
It can then be referred to with a fully qualified path.
It can also be locally used / brought into scope so as to refer to it in an unqualified fashion.
Example
macro_rules! macro_name { ... }
pub(crate) use macro_name; // Now classic paths Just Workโ„ข
And that's it. Quite simple, huh?
Feel free to keep reading, but only if you are not scared of information overload ;) I'll try to detail why, how and when exactly does this work.
More detailed explanation
In order to re-export (pub(...) use ...) a macro, we need to refer to it! That's where the rules from the original answer are useful: a macro can always be named within the very module where the macro definition occurs, but only after that definition.
macro_rules! my_macro { ... }
my_macro!(...); // OK
// Not OK
my_macro!(...); /* Error, no `my_macro` in scope! */
macro_rules! my_macro { ... }
Based on that, we can re-export a macro after the definition; the re-exported name, then, in and of itself, is location agnostic, as all the other global items in Rust ๐Ÿ™‚
In the same fashion that we can do:
struct Foo {}
fn main() {
let _: Foo;
}
We can also do:
fn main() {
let _: A;
}
struct Foo {}
use Foo as A;
The same applies to other items, such as functions, but also to macros!
fn main() {
a!();
}
macro_rules! foo { ... } // foo is only nameable *from now on*
use foo as a; // but `a` is now visible all around the module scope!
And it turns out that we can write use foo as foo;, or the common use foo; shorthand, and it still works.
The only question remaining is: pub(crate) or pub?
For #[macro_export]-ed macros, you can use whatever privacy you want; usually pub.
For the other macro_rules! macros, you cannot go above pub(crate).
Detailed examples
For a non-#[macro_export]ed macro
mod foo {
use super::example::my_macro;
my_macro!(...); // OK
}
mod example {
macro_rules! my_macro { ... }
pub(crate) use my_macro;
}
example::my_macro!(...); // OK
For a #[macro_export]-ed macro
Applying #[macro_export] on a macro definition makes it visible after the very module where it is defined (so as to be consistent with the behavior of non-#[macro_export]ed macros), but it also puts the macro at the root of the crate (where the macro is defined), in an absolute path fashion.
This means that a pub use macro_name; right after the macro definition, or a pub use crate::macro_name; in any module of that crate will work.
Note: in order for the re-export not to collide with the "exported at the root of the crate" mechanic, it cannot be done at the root of the crate itself.
pub mod example {
#[macro_export] // macro nameable at `crate::my_macro`
macro_rules! my_macro { ... }
pub use my_macro; // macro nameable at `crate::example::my_macro`
}
pub mod foo {
pub use crate::my_macro; // macro nameable at `crate::foo::my_macro`
}
When using the pub / pub(crate) use macro_name;, be aware that given how namespaces work in Rust, you may also be re-exporting constants / functions or types / modules. This also causes problems with globally available macros such as #[test], #[allow(...)], #[warn(...)], etc.
In order to solve these issues, remember you can rename an item when re-exporting it:
macro_rules! __test__ { ... }
pub(crate) use __test__ as test; // OK
macro_rules! __warn__ { ... }
pub(crate) use __warn__ as warn; // OK
Also, some false positive lints may fire:
from the trigger-happy clippy tool, when this trick is done in any fashion;
from rustc itself, when this is done on a macro_rules! definition that happens inside a function's body: https://github.com/rust-lang/rust/issues/78894

This answer is outdated as of Rust 1.1.0-stable.
You need to add #![macro_escape] at the top of macros.rs and include it using mod macros; as mentioned in the Macros Guide.
$ cat macros.rs
#![macro_escape]
#[macro_export]
macro_rules! my_macro {
() => { println!("hi"); }
}
$ cat something.rs
#![feature(macro_rules)]
mod macros;
fn main() {
my_macro!();
}
$ rustc something.rs
$ ./something
hi
For future reference,
$ rustc -v
rustc 0.13.0-dev (2790505c1 2014-11-03 14:17:26 +0000)

Adding #![macro_use] to the top of your file containing macros will cause all macros to be pulled into main.rs.
For example, let's assume this file is called node.rs:
#![macro_use]
macro_rules! test {
() => { println!("Nuts"); }
}
macro_rules! best {
() => { println!("Run"); }
}
pub fn fun_times() {
println!("Is it really?");
}
Your main.rs would look sometime like the following:
mod node; //We're using node.rs
mod toad; //Also using toad.rs
fn main() {
test!();
best!();
toad::a_thing();
}
Finally let's say you have a file called toad.rs that also requires these macros:
use node; //Notice this is 'use' not 'mod'
pub fn a_thing() {
test!();
node::fun_times();
}
Notice that once files are pulled into main.rs with mod, the rest of your files have access to them through the use keyword.

I have came across the same problem in Rust 1.44.1, and this solution works for later versions (known working for Rust 1.7).
Say you have a new project as:
src/
main.rs
memory.rs
chunk.rs
In main.rs, you need to annotate that you are importing macros from the source, otherwise, it will not do for you.
#[macro_use]
mod memory;
mod chunk;
fn main() {
println!("Hello, world!");
}
So in memory.rs you can define the macros, and you don't need annotations:
macro_rules! grow_capacity {
( $x:expr ) => {
{
if $x < 8 { 8 } else { $x * 2 }
}
};
}
Finally you can use it in chunk.rs, and you don't need to include the macro here, because it's done in main.rs:
grow_capacity!(8);
The upvoted answer caused confusion for me, with this doc by example, it would be helpful too.
Note: This solution does work, but do note as #ineiti highlighted in the comments, the order u declare the mods in the main.rs/lib.rs matters, all mods declared after the macros mod declaration try to invoke the macro will fail.

Related

How to import/use macro from different module in the same crate?

Real life scenario:
I wanted to use crate::app::verbose_trace!("string literal") inside crate::app::args::parse module.
Reproducable scenario:
After an hour of attempts, I came with following simple example.
It exposes my misunderstanding of macros.
#[macro_use]
mod foo{
pub fn bar(){
println!("bar works")
}
#[macro_export]
macro_rules! baz{
()=> {println!("baz works")}
}
}
fn main(){
foo::bar();
foo::baz!();
// Following doesn't work either:
// use foo::baz;
// baz!();
}
Compiler complains
error[E0433]: failed to resolve: could not find `baz` in `foo`
--> src\main.rs:14:14
|
14 | foo::baz!();
| ^^^ could not find `baz` in `foo`
as if it was utterly blind :0
I read:
https://riptutorial.com/rust/example/5647/exporting-and-importing-macros
https://9to5answer.com/how-to-import-macros-in-rust
and partially:
How do you import macros in submodules in Rust?
How to import macros in Rust?
I would like to see:
A compilable version of my example.
Explanations why it did failed to compile.
Optionally:
Some other suggestions how to use marco in submodule/supermodule.
#[macro_export] exports the macro under the crate root. Thus, crate::baz!() will work, but foo::baz!() won't (and you don't need #[macro_use], it is for using the macro in another crates).
If you want to export the macro in this path, for crate local macros don't use #[macro_export] as all. Instead, export the macro like:
macro_rules! baz {
() => {
println!("baz works")
};
}
pub(crate) use baz;
For exporting the macro for use in other crates you still need #[macro_export]:
#[macro_export]
macro_rules! baz {
() => {
println!("baz works")
};
}
pub use baz;
This will export the macro both under the crate root and under foo.

Can I import super:: from a mod that's inside a fn?

I realise that this is an extremely odd thing to do but I'm writing a macro I'd like to be usable in as many places as possible. Take the following code:
mod outer {
struct OuterTestStruct {}
fn do_thing() {
struct InnerTestStruct {}
mod inner {
use super::OuterTestStruct;
use super::InnerTestStruct;
}
}
}
This doesn't compile because of the use super::InnerTestStruct line. But the use super::OuterTestStruct line works fine, so my assumption here is that super skips over the fn context and goes straight to the parent mod.
Is there any way I can get a reference to InnerTestStruct from inside mod inner? Especially without knowing any context beforehand (i.e. imagine a macro invocation inside fn do_thing(), it isn't going to know it's inside a fn)
Is there any way I can get a reference to InnerTestStruct from inside mod inner?
No, super will refer to the encompassing module, not the function scope. There is no path that can name InnerTestStruct as far as I'm aware.
Since you mention macros specifically, the Rust API Guidelines warns against this exact case:
Item macros work anywhere that items are allowed
Rust allows items to be placed at the module level or within a tighter scope like a function. Item macros should work equally well as ordinary items in all of these places. The test suite should include invocations of the macro in at least the module scope and function scope.
As a simple example of how things can go wrong, this macro works great in a module scope but fails in a function scope.
macro_rules! broken {
($m:ident :: $t:ident) => {
pub struct $t;
pub mod $m {
pub use super::$t;
}
} }
broken!(m::T); // okay, expands to T and m::T
fn g() {
broken!(m::U); // fails to compile, super::U refers to the containing module not g
}
The only fix I know is to introduce another module:
mod outer {
struct OuterTestStruct {}
fn do_thing() {
mod middle { // <----------------
struct InnerTestStruct {}
mod inner {
use super::super::OuterTestStruct;
use super::InnerTestStruct;
}
}
}
}

How to access a macro from a mod.rs within the same directory in Rust 2018? [duplicate]

I have two modules in separate files within the same crate, where the crate has macro_rules enabled. I want to use the macros defined in one module in another module.
// macros.rs
#[macro_export] // or not? is ineffectual for this, afaik
macro_rules! my_macro(...)
// something.rs
use macros;
// use macros::my_macro; <-- unresolved import (for obvious reasons)
my_macro!() // <-- how?
I currently hit the compiler error "macro undefined: 'my_macro'"... which makes sense; the macro system runs before the module system. How do I work around that?
Macros within the same crate
New method (since Rust 1.32, 2019-01-17)
foo::bar!(); // works
mod foo {
macro_rules! bar {
() => ()
}
pub(crate) use bar; // <-- the trick
}
foo::bar!(); // works
With the pub use, the macro can be used and imported like any other item. And unlike the older method, this does not rely on source code order, so you can use the macro before (source code order) it has been defined.
Old method
bar!(); // Does not work! Relies on source code order!
#[macro_use]
mod foo {
macro_rules! bar {
() => ()
}
}
bar!(); // works
If you want to use the macro in the same crate, the module your macro is defined in needs the attribute #[macro_use]. Note that macros can only be used after they have been defined!
Macros across crates
Crate util
#[macro_export]
macro_rules! foo {
() => ()
}
Crate user
use util::foo;
foo!();
Note that with this method, macros always live at the top-level of a crate! So even if foo would be inside a mod bar {}, the user crate would still have to write use util::foo; and not use util::bar::foo;. By using pub use, you can export a macro from a module of your crate (in addition to it being exported at the root).
Before Rust 2018, you had to import macro from other crates by adding the attribute #[macro_use] to the extern crate util; statement. That would import all macros from util. This syntax should not be necessary anymore.
Alternative approach as of 1.32.0 (2018 edition)
Note that while the instructions from #lukas-kalbertodt are still up to date and work well, the idea of having to remember special namespacing rules for macros can be annoying for some people.
EDIT: it turns out their answer has been updated to include my suggestion, with no credit mention whatsoever ๐Ÿ˜•
On the 2018 edition and onwards, since the version 1.32.0 of Rust, there is another approach which works as well, and which has the benefit, imho, of making it easier to teach (e.g., it renders #[macro_use] obsolete). The key idea is the following:
A re-exported macro behaves as any other item (function, type, constant, etc.): it is namespaced within the module where the re-export occurs.
It can then be referred to with a fully qualified path.
It can also be locally used / brought into scope so as to refer to it in an unqualified fashion.
Example
macro_rules! macro_name { ... }
pub(crate) use macro_name; // Now classic paths Just Workโ„ข
And that's it. Quite simple, huh?
Feel free to keep reading, but only if you are not scared of information overload ;) I'll try to detail why, how and when exactly does this work.
More detailed explanation
In order to re-export (pub(...) use ...) a macro, we need to refer to it! That's where the rules from the original answer are useful: a macro can always be named within the very module where the macro definition occurs, but only after that definition.
macro_rules! my_macro { ... }
my_macro!(...); // OK
// Not OK
my_macro!(...); /* Error, no `my_macro` in scope! */
macro_rules! my_macro { ... }
Based on that, we can re-export a macro after the definition; the re-exported name, then, in and of itself, is location agnostic, as all the other global items in Rust ๐Ÿ™‚
In the same fashion that we can do:
struct Foo {}
fn main() {
let _: Foo;
}
We can also do:
fn main() {
let _: A;
}
struct Foo {}
use Foo as A;
The same applies to other items, such as functions, but also to macros!
fn main() {
a!();
}
macro_rules! foo { ... } // foo is only nameable *from now on*
use foo as a; // but `a` is now visible all around the module scope!
And it turns out that we can write use foo as foo;, or the common use foo; shorthand, and it still works.
The only question remaining is: pub(crate) or pub?
For #[macro_export]-ed macros, you can use whatever privacy you want; usually pub.
For the other macro_rules! macros, you cannot go above pub(crate).
Detailed examples
For a non-#[macro_export]ed macro
mod foo {
use super::example::my_macro;
my_macro!(...); // OK
}
mod example {
macro_rules! my_macro { ... }
pub(crate) use my_macro;
}
example::my_macro!(...); // OK
For a #[macro_export]-ed macro
Applying #[macro_export] on a macro definition makes it visible after the very module where it is defined (so as to be consistent with the behavior of non-#[macro_export]ed macros), but it also puts the macro at the root of the crate (where the macro is defined), in an absolute path fashion.
This means that a pub use macro_name; right after the macro definition, or a pub use crate::macro_name; in any module of that crate will work.
Note: in order for the re-export not to collide with the "exported at the root of the crate" mechanic, it cannot be done at the root of the crate itself.
pub mod example {
#[macro_export] // macro nameable at `crate::my_macro`
macro_rules! my_macro { ... }
pub use my_macro; // macro nameable at `crate::example::my_macro`
}
pub mod foo {
pub use crate::my_macro; // macro nameable at `crate::foo::my_macro`
}
When using the pub / pub(crate) use macro_name;, be aware that given how namespaces work in Rust, you may also be re-exporting constants / functions or types / modules. This also causes problems with globally available macros such as #[test], #[allow(...)], #[warn(...)], etc.
In order to solve these issues, remember you can rename an item when re-exporting it:
macro_rules! __test__ { ... }
pub(crate) use __test__ as test; // OK
macro_rules! __warn__ { ... }
pub(crate) use __warn__ as warn; // OK
Also, some false positive lints may fire:
from the trigger-happy clippy tool, when this trick is done in any fashion;
from rustc itself, when this is done on a macro_rules! definition that happens inside a function's body: https://github.com/rust-lang/rust/issues/78894
This answer is outdated as of Rust 1.1.0-stable.
You need to add #![macro_escape] at the top of macros.rs and include it using mod macros; as mentioned in the Macros Guide.
$ cat macros.rs
#![macro_escape]
#[macro_export]
macro_rules! my_macro {
() => { println!("hi"); }
}
$ cat something.rs
#![feature(macro_rules)]
mod macros;
fn main() {
my_macro!();
}
$ rustc something.rs
$ ./something
hi
For future reference,
$ rustc -v
rustc 0.13.0-dev (2790505c1 2014-11-03 14:17:26 +0000)
Adding #![macro_use] to the top of your file containing macros will cause all macros to be pulled into main.rs.
For example, let's assume this file is called node.rs:
#![macro_use]
macro_rules! test {
() => { println!("Nuts"); }
}
macro_rules! best {
() => { println!("Run"); }
}
pub fn fun_times() {
println!("Is it really?");
}
Your main.rs would look sometime like the following:
mod node; //We're using node.rs
mod toad; //Also using toad.rs
fn main() {
test!();
best!();
toad::a_thing();
}
Finally let's say you have a file called toad.rs that also requires these macros:
use node; //Notice this is 'use' not 'mod'
pub fn a_thing() {
test!();
node::fun_times();
}
Notice that once files are pulled into main.rs with mod, the rest of your files have access to them through the use keyword.
I have came across the same problem in Rust 1.44.1, and this solution works for later versions (known working for Rust 1.7).
Say you have a new project as:
src/
main.rs
memory.rs
chunk.rs
In main.rs, you need to annotate that you are importing macros from the source, otherwise, it will not do for you.
#[macro_use]
mod memory;
mod chunk;
fn main() {
println!("Hello, world!");
}
So in memory.rs you can define the macros, and you don't need annotations:
macro_rules! grow_capacity {
( $x:expr ) => {
{
if $x < 8 { 8 } else { $x * 2 }
}
};
}
Finally you can use it in chunk.rs, and you don't need to include the macro here, because it's done in main.rs:
grow_capacity!(8);
The upvoted answer caused confusion for me, with this doc by example, it would be helpful too.
Note: This solution does work, but do note as #ineiti highlighted in the comments, the order u declare the mods in the main.rs/lib.rs matters, all mods declared after the macros mod declaration try to invoke the macro will fail.

Why do I need to "use std" in a module but not at the root of my crate? [duplicate]

I have the following code:
pub mod a {
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
}
I get errors when I compile this:
error[E0433]: failed to resolve. Use of undeclared type or module `std`
--> src/main.rs:4:24
|
4 | println!("{}", std::fs::remove_file("Somefilehere"));
| ^^^ Use of undeclared type or module `std`
However, removing the inner module and compiling the code it contains by itself works fine:
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
What am I missing here? I get the same errors if the module is in a separate file:
main.rs
pub mod a;
a.rs
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
By default, the compiler inserts extern crate std; at the beginning of the crate root (the crate root is the file that you pass to rustc). This statement has the effect of adding the name std to the crate's root namespace and associating it with a module that contains the public contents of the std crate.
However, in child modules, std is not automatically added in the module's namespace. This is why the compiler cannot resolve std (or anything that starts with std::) in a module.
There are many ways to fix this. First, you can add use std; in a module to make the name std refer, within that module, to the root std. Note that in use statements, the path is treated as absolute (or "relative to the crate's root namespace"), whereas everywhere else, paths are treated as relative to the current namespace (be it a module, a function, etc.).
pub mod a {
use std;
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
}
You can also use a use statement to import more specific items. For example, you can write use std::fs::remove_file;. This lets you avoid having to type the whole path to remove_file and just use the name remove_file directly within that module:
pub mod a {
use std::fs::remove_file;
#[test]
pub fn test() {
println!("{:?}", remove_file("Somefilehere")));
}
}
Finally, you can avoid using use altogether by prefixing the path with :: to ask the compiler to resolve the path from the crate's root namespace (i.e. turning the path into an absolute path).
pub mod a {
#[test]
pub fn test() {
println!("{:?}", ::std::fs::remove_file("Somefilehere"));
}
}
The recommended practice is to import types (structs, enums, etc.) directly (e.g. use std::rc::Rc;, then use the path Rc), but to use functions through an import of their parent module (e.g. use std::io::fs;, then use the path fs::remove_file).
pub mod a {
use std::fs;
#[test]
pub fn test() {
println!("{:?}", fs::remove_file("Somefilehere"));
}
}
Side note: You can also write self:: at the beginning of a path to make it relative to the current module. This is more often used in use statements, since other paths are already relative (though they are relative to the current namespace, whereas self:: is always relative to the containing module).
Nowadays, std is directly accessible from everywhere, so the code you showed is compiling as you would expect.
Furthermore, extern crate is no longer needed in Rust edition 2018. Adding a dependency to Cargo.toml makes the crate name directly available as a top-level identifier.

Use of undeclared type or module `std` when used in a separate module

I have the following code:
pub mod a {
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
}
I get errors when I compile this:
error[E0433]: failed to resolve. Use of undeclared type or module `std`
--> src/main.rs:4:24
|
4 | println!("{}", std::fs::remove_file("Somefilehere"));
| ^^^ Use of undeclared type or module `std`
However, removing the inner module and compiling the code it contains by itself works fine:
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
What am I missing here? I get the same errors if the module is in a separate file:
main.rs
pub mod a;
a.rs
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
By default, the compiler inserts extern crate std; at the beginning of the crate root (the crate root is the file that you pass to rustc). This statement has the effect of adding the name std to the crate's root namespace and associating it with a module that contains the public contents of the std crate.
However, in child modules, std is not automatically added in the module's namespace. This is why the compiler cannot resolve std (or anything that starts with std::) in a module.
There are many ways to fix this. First, you can add use std; in a module to make the name std refer, within that module, to the root std. Note that in use statements, the path is treated as absolute (or "relative to the crate's root namespace"), whereas everywhere else, paths are treated as relative to the current namespace (be it a module, a function, etc.).
pub mod a {
use std;
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
}
You can also use a use statement to import more specific items. For example, you can write use std::fs::remove_file;. This lets you avoid having to type the whole path to remove_file and just use the name remove_file directly within that module:
pub mod a {
use std::fs::remove_file;
#[test]
pub fn test() {
println!("{:?}", remove_file("Somefilehere")));
}
}
Finally, you can avoid using use altogether by prefixing the path with :: to ask the compiler to resolve the path from the crate's root namespace (i.e. turning the path into an absolute path).
pub mod a {
#[test]
pub fn test() {
println!("{:?}", ::std::fs::remove_file("Somefilehere"));
}
}
The recommended practice is to import types (structs, enums, etc.) directly (e.g. use std::rc::Rc;, then use the path Rc), but to use functions through an import of their parent module (e.g. use std::io::fs;, then use the path fs::remove_file).
pub mod a {
use std::fs;
#[test]
pub fn test() {
println!("{:?}", fs::remove_file("Somefilehere"));
}
}
Side note: You can also write self:: at the beginning of a path to make it relative to the current module. This is more often used in use statements, since other paths are already relative (though they are relative to the current namespace, whereas self:: is always relative to the containing module).
Nowadays, std is directly accessible from everywhere, so the code you showed is compiling as you would expect.
Furthermore, extern crate is no longer needed in Rust edition 2018. Adding a dependency to Cargo.toml makes the crate name directly available as a top-level identifier.

Resources