core::ops::Fn not available in no_std project

Hi,

I am working on an no_std library, and I want to use the Fn trait (or FnOnce/FnMut) of core::ops but the compiler can't find it.

It looks like there is the rust1 feature to activate but I can't find a way to activate it.

Is there a way to do it ? Is there a reason as for why I can't access it ?

You might want to show some code, because core::ops::Fn is available in no_std.

core::ops is part of the prelude, as long as core is available, the Fn family of traits are available. you must have other unusual setups preventing you from importing core. are you sure you are just #![no_std], not #![no_core] or something?

I'm building for riscv64 embedded, the config.toml is looking like this :

[build]
target = ["./target.json"]

[unstable]
build-std = ["core", "alloc"]

[target.riscv64gc-unknown-none-elf]
rustflags = [
    "-C", "link-arg=-Tmemory.x",
    "-C", "link-arg=-Tlink.x",
]

The target.json :

{
  "arch": "riscv64",
  "cpu": "generic-rv64",
  "crt-objects-fallback": "false",
  "data-layout": "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
  "eh-frame-header": false,
  "emit-debug-gdb-scripts": false,
  "features": "+i,+a,+m,+f,+d,+c",
  "linker": "rust-lld",
  "linker-flavor": "gnu-lld",
  "llvm-abiname": "lp64d",
  "llvm-target": "riscv64",
  "max-atomic-width": 64,
  "metadata": {
    "description": "Bare RISC-V (RV64IMAFDC ISA)",
    "host_tools": false,
    "std": false,
    "tier": 3
  },
  "panic-strategy": "abort",
  "relocation-model": "static",
  "target-pointer-width": 64,
  "code-model": "medium",
  "function-sections": false
}

I'm on rust 1.90.0 stable.

The build.rs I am using to generated C bindings from headers :


fn main() {
	let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
	fs::write(out_dir.join("memory.x"), include_bytes!("memory.x")).unwrap();
	println!("cargo:rustc-link-search={}", out_dir.display());
	println!("cargo:rerun-if-changed=memory.x");
	println!("cargo:rerun-if-changed=build.rs");

	let libclang_include =
		env::var("LIBCLANG_PATH").expect("LIBCLANG_PATH environment variable not set");

	// Create output directory if it doesn't exist
	let out_dir = Path::new("src/bindings");
	fs::create_dir_all(out_dir).expect("Failed to create output directory");

	// for entry in fs::read_dir("./headers").unwrap() {
	let path = Path::new("headers/wrapper.h");
	if path.extension().map_or(false, |ext| ext == "h") {
		println!("cargo:rerun-if-changed={}", path.display());

		let out_path = out_dir.join("generated.rs");

		let bindings = bindgen::Builder::default()
			.header(path.to_str().unwrap())
			.use_core()
			.generate_cstr(true)
			.merge_extern_blocks(true)
			.layout_tests(false)
			.clang_args(&[
				"--target=riscv64-unknown-none",
				&format!("-I{}", libclang_include),
			])
			.formatter(Formatter::Prettyplease)
			.generate()
			.expect(&format!("Failed to generate bindings for {:?}", path));

		bindings
			.write_to_file(&out_path)
			.expect(&format!("Failed to write bindings to {:?}", out_path));
	}
	// }
}

I have access to the AsyncFn trait but not the Fn trait.

My lib.rs is something like this :

#![no_std]
#![feature(unboxed_closures)]

extern crate alloc;

#[panic_handler]
pub fn panic(info: &core::panic::PanicInfo) -> ! {
	loop {}
}
pub fn testing<F: Fn() -> i32> () { // This cause the Cannot find trait Fn in this scope error 
}

I am generating a "staticlib" because I need to link it to C code after.

I don't know if you may need anything else, I can use the Fn trait in another project with no_std just fine so it must be something with my build configuration

you are using a custom target, and build-std at the same time, I have no experience on such special setup.

well, that's really strange, if I were to expect some difference between these two, I would probably guess the opposite.

I see you use the unboxed_closures feature, could that have caused the bug? if you remove this feature, do you still get the same error?

or alternatively, if you use the desugarred Fn trait syntax, does it compile?

pub fn testing<F: Fn<(), Output = i32>> () {
}

I think the full compile error would be helpful to pin point the root cause, and it would be even better if you enables verbose output. for example, try run these commands and post the output (if the output were too long, consider use pastebin or gist and post the link instead):

$ cargo clean
$ cargo -vv build

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.