use of undeclared crate or module `proc_macro2` [closed] - rust

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed last month.
Improve this question
I just tried defining a derive macro using the proc_macro2 module, using the copy-pasted code from the proc_macro2 documentation:
extern crate proc_macro;
#[proc_macro_derive(MyTrait)]
pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = proc_macro2::TokenStream::from(input);
let output: proc_macro2::TokenStream = {
/* transform input */
};
proc_macro::TokenStream::from(output)
}
However, when trying to compile the preceding example, I obtain the lovely error
13 | let output: proc_macro2::TokenStream = {
| ^^^^^^^^^^^ use of undeclared crate or module `proc_macro2`
|
The Cargo.toml file contains the line proc-macro2 = "1.0" and this indeed made a proc-macro2-1.0.49 directory appear under ~/.cargo/registry/src.
I also tried appending extern crate proc_macro2, to no avail (“error[E0463]: can't find crate for proc_macro2”). (Strangely, doing a strace on the compiler shows that it does read the crate files).
rustc version is 1.66.0.
What did I miss?
Edit: found it. This proc-macro crate was a subcrate of a main (binary) one and of course I was adding proc-macro2 to the wrong Cargo.toml file.

Related

Rust compiler error - "maybe missing crate ..." [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have a project with multiple files which all depend on each other which worked fine. I added another file and added the use crate::asteroid::Asteroid syntax to another file.
When I compile it says
unresolved import "crate::asteroid"
This worked with all the other files. What is wrong?
Project layout:
/src/
asteroid.rs
command.rs
direction.rs
game.rs
main.rs
point.rs
ship.rs
The use keyword will import only the path specified, so when you use crate::asteroid::Asteroid only the Asteroid object will be imported, but not crate::asteroid. In order to import both, you can use:
use crate::asteroid::{ self, Asteroid };
Here self is referring to crate::asteroid. You will then be able to access both asteroid and Asteroid

C library cannot be linked when main.rs and lib.rs coexist

Basic setup
A simple C function that is called from Rust via FFI, and a static library (Windows) that is linked in build.rs.
// api.c
int increment(int value) {
return value + 1;
}
// main.rs
extern {
fn increment(value: i32) -> i32;
}
fn main() {
let num = unsafe { increment(4) };
println!("The incremented number is {}", num);
}
// build.rs
fn main() {
println!("cargo:rustc-link-search=src/ffi");
println!("cargo:rustc-link-lib=static=api");
}
With this directory structure:
Cargo.toml
Cargo.lock
build.rs
src
+-- main.rs
+-- ffi
+-- api.c
+-- api.lib
Cargo.toml has nothing but a crate name, version, author and Rust edition.
So far, this works perfectly, and "The incremented number is 5" is printed as expected.
The problem
Now I add an empty lib.rs file, so I can use my crate as both a library and a binary:
Cargo.toml
Cargo.lock
build.rs
src
+-- lib.rs <-- NEW
+-- main.rs
+-- ffi
+-- api.c
+-- api.lib
I do not change Cargo.toml.
This alone makes the link step fail (MSVC linker):
error LNK2019: Unresolved external symbol "increment" referenced in function "_ZN16my_crate4main17h887bd80180495b7eE"
The error persists even if I explicitly specify the presence of both a library and binary in Cargo.toml and run using cargo run --bin my_main:
[lib]
name = "my_lib"
path = "src/lib.rs"
[[bin]]
name = "my_main"
path = "src/main.rs"
I also made sure that build.rs is still executed in the binary case, by letting it panic to abort the build.
I'm aware that I could solve it by splitting the crate, but I'd like to understand what exactly happens. So:
Why does the presence of an empty lib.rs cause the linker to fail?
And is there a way to make it succeed, in a single crate?
In the presence of both a binary and a Rust library in a single crate, Rust statically links the binary against the Rust library itself, as if the library were any other external crate (e.g. from crates.io). I assume to prevent errors due to duplicate symbols, or possibly just to avoid code bloat or extra work, it appears to avoid linking any external artifacts directly against the binary, and does not make an effort to determine if the code in question is even available in lib.rs before making this judgment. Normally this happens in the background without you noticing (i.e. it's doing this to the Rust standard library, your system standard libraries, and external crates as well for everything you compile), but when you introduce custom FFI dependencies it becomes obvious.
If you change your lib.rs to
extern {
pub fn increment(value: i32) -> i32;
}
And your main.rs to
fn main() {
let num = unsafe { libname::increment(4) };
println!("The incremented number is {}", num);
}
Where libname is either the name of your library as listed in Cargo.toml or the project name if that's not specificed, it will compile and run properly. Indeed, this follows no matter how complex you get. You can bury the FFI function a million modules deep and include it from wherever, but it will fail with the same error if you reference a definition of an extern "C" function without going through the master library crate first.
I don't know if there's any way (in build.rs or otherwise) to insist that Rust statically links a library either twice against the two different targets, or else only against the binary itself, but if there is it's not well documented or obvious.
That said, in most cases this is unlikely to be a problem, since if you're making your functionality usable as a library, it's likely you'll have the common code, including FFI, in there anyway. It could conceivably be an issue if you have a C dependency (e.g. for device access) that only makes sense in the binary, but I think that case is rare enough it's reasonable to force you to split the crates using workspaces if that's your specific situation.

Why does Rust Analyser disagree with the compiler? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I'm using the latest stable version: rustc 1.46.0 (04488afe3 2020-08-24).
Rust Analyser needs the import:
use chrono::offset::TimeZone;
in order to accept the expression:
Utc.ymd(1970, 1, 1).and_hms_milli(0, 0, 0, 200)
(It highlights the .ymd as {unknown}.)
If I add the import, the compiler issues a warning:
Compiling foo v0.1.0 (/home/fadedbee/foo)
warning: unused import: `chrono::offset::TimeZone`
--> src/bar.rs:2:5
|
2 | use chrono::offset::TimeZone;
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
How can I make Rust Analyser (in vscode), and the compiler, both happy?
Update:
As rodrigo correctly deduced, the only uses of .ymd are within a #[cfg(test)] section.

Rust integration test can't `use` library [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
Working to include integration tests to my project but I'm unable to import the library. I thought the new rules would allow me to just write a use statement but it isn't going very well :)
The code below shows the related components. Isn't this supposed to be valid?
Cargo.toml
[package]
name = "myswankynewpackage"
version = "0.1.0"
authors = ["Me Myself <me.myself#gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
tests/tests.rs
use myswankynewpackage;
// Also tried extern crate
// extern crate myswankynewpackage;
#[cfg(test)]
mod integration {
use super::*;
mod module{
#[test]
fn module_test() {
}
}
}
I get an error saying it can't find the crate
error[E0432]: unresolved import `myswankynewpackage`
--> tests/tests.rs:1:5
|
1 | use myswankynewpackage;
| ^^^^^^^^^^^^^^^^^^ no `myswankynewpackage` external crate
So, I noticed that OP says the actual Cargo.toml matches the given one "except [OP is] ... using a couple of libraries."
I think what's causing problems is the libraries - if you have libraries (with a different name), you need to use the name of the library in the use statement. ie:
Cargo.toml
[package]
name = "myswankynewpackage"
version = "0.1.0"
authors = ["Me Myself <me.myself#gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
tests/tests.rs
[lib]
name = "myswankynewlib"
path = "src/lib.rs"
tests/tests.rs
// WRONG!
// use myswankynewpackage;
// RIGHT!
use myswankynewlib;
...
I had a similar error message, and originally found this post when searching before I realized the issue. So even if this WASN'T the original poster's problem, perhaps this answer will help others...

Is there a way of resolving a crate naming conflict? [duplicate]

I have a crate foo_sys. In Rust 2015 I used extern crate foo_sys as foo for convenience, but in Rust 2018 extern crate isn't needed anymore and I don't want to use it only for aliasing. When dropping extern crate, I get
error[E0463]: can't find crate for foo
This can be achieved with the rename-dependency Cargo feature, available in Rust 1.31. With this feature, it's possible to provide a package attribute to the dependencies:
The rename-dependency feature allows you to import a dependency with a different name from the source. This can be useful in a few scenarios:
Depending on crates with the same name from different registries.
Depending on multiple versions of a crate.
Avoid needing extern crate foo as bar in Rust source.
Instead of writing
[dependencies]
foo_sys = "0.2"
the package key can be added to the dependency in Cargo.toml:
[dependencies]
foo = { package = "foo_sys", version = "0.2" }
WARNING: Cargo prior to Rust 1.26.0 may download the wrong dependency when using this feature!
The idiomatic solution is to rename the crate in Cargo.toml. See the answer by Tim Diekmann for more information about that.
But if you don't want to use Cargo.toml renaming for some reason, you can still use the old syntax. It's soft-deprecated, but not removed. So this still works:
extern crate foo_sys as foo;
(Playground example)

Resources