Skip to content

alloc methods are available in #![no_std] when running tests, despite not being imported. #99637

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ilyvion opened this issue Jul 23, 2022 · 3 comments
Labels
A-libtest Area: `#[test]` / the `test` library C-bug Category: This is a bug. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Comments

@ilyvion
Copy link

ilyvion commented Jul 23, 2022

I was messing around in a test in a #[no_std] crate and discovered that this code:

#![no_std]

#[test]
fn foo() {
    let b = b"hello";
    let _v = b.to_vec();
}

(playground link)

compiles, which really surprised me, because [T]::to_vec() is defined in the alloc crate, and as you can see, I don't have any extern alloc; directive. It's even more surprising in that it only works in functions marked either #[test] or #[cfg(test)]. If you put it on a regular function (just remove #[test] from above), you get the expected error:

error[E0599]: no method named `to_vec` found for reference `&[u8; 5]` in the current scope
 --> src\lib.rs:5:16
  |
5 |     let _v = b.to_vec();
  |                ^^^^^^ method not found in `&[u8; 5]`

I expected this error to also happen in #[cfg(test)], but it doesn't. This is unexpected and surprising.

What makes it even more surprising is that alloc isn't actually in scope, because if you change let _v to let _v: alloc::Vec<_> in the code above, you'll be told as much.

@ilyvion ilyvion added the C-bug Category: This is a bug. label Jul 23, 2022
@ehuss
Copy link
Contributor

ehuss commented Jul 23, 2022

I think this is similar to #90907. This isn't exactly related to #[test], other than the fact that libtest gets linked in and it depends on std/alloc.

For example:

// foo.rs
#![no_std]
pub fn foo() {
    bar::x();
    let b = b"hello";
    let _v = b.to_vec();
}
// bar.rs
#![no_std]
extern crate alloc;

pub fn x() {}
rustc bar.rs --crate-type=rlib
# This succeeds
rustc foo.rs --crate-type=rlib --extern bar=libbar.rlib

@ilyvion
Copy link
Author

ilyvion commented Jul 24, 2022

I don't know if anyone else agrees, but this feels like some kind of boundary violation to me. If nothing else it cost me a bunch of time because I knew I wasn't supposed to have .to_vec() available to me, and yet it just kept on working. 😅

@ilyvion
Copy link
Author

ilyvion commented Jul 25, 2022

I'm seeing more strange behavior related to this odd alloc "leak." I had this problem:

error: cannot find macro `format` in this scope
   --> src\range_type.rs:246:14
    |
246 |             &format!("{}", invalid_deserialized_error.unwrap_err()),

(which makes sense, we're in #![no_std] right?) So I changed it to alloc::format!, but still:

error[E0433]: failed to resolve: use of undeclared crate or module `alloc`
   --> src\range_type.rs:246:14
    |
246 |             &alloc::format!("{}", invalid_deserialized_error.unwrap_err()),
    |              ^^^^^ use of undeclared crate or module `alloc`

Right! I forgot to add extern crate alloc;! But uh...:

warning: unused extern crate
   --> src\range_type.rs:161:5
    |
160 | /     #[warn(unused)]
161 | |     extern crate alloc;
    | |     ^^^^^^^^^^^^^^^^^^-
    | |_______________________|
    |                         help: remove it

It finally compiles with extern crate alloc; there, though. (I have #[warn(unused)] there because my crate-wide setting is #![deny(unused)]; although I'll be making the warn into allow after making this report, because it clearly isn't truly unused.)

The compiler seems to have a hard time deciding whether or not alloc really is available here. It yells at me when I have it there and it yells at me when I don't have it there.

@Enselic Enselic added A-libtest Area: `#[test]` / the `test` library T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jul 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-libtest Area: `#[test]` / the `test` library C-bug Category: This is a bug. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
Status: No status
Development

No branches or pull requests

4 participants