Skip to main content

Quoting Errors

Quoting relies on advanced features of Rust, and can sometimes emit strange type errors. This page covers the current limitations and workarounds for common quoting errors.

note

The Hydro team is also working with members of the Rust language team to explore upstreaming the quoting features into Rust itself. While this effort is in the early days, we hope that upstreaming will eliminate these edge cases.

References to Local Functions

Currently, code inside a q! macro must use self:: paths when invoking a local function. For example, in this code invoking foo will not compile but self::foo works as expected:

fn foo() {}

fn uses_foo_quoted() {
q!(|| foo()) // don't do this, compiler error
q!(|| self::foo()) // works!
}

Local Imports Inside Functions

Imports (use statements) inside a function body are not visible to q!. Any symbols referenced inside q! must be imported at the module level.

fn uses_local_import() {
use some_crate::MyType;
q!(|| MyType::new()) // don't do this, error during staged compilation
}

use some_crate::MyType; // import at module level instead
fn uses_module_import() {
q!(|| MyType::new()) // works!
}

References to Free Variables in Macros

Quoted code can refer to special types of external variables called "free variables". These include primitives such as integers and strings, as well as special types such as CLUSTER_SELF_ID. Stageleft does not currently handle references to these variables directly inside macros with custom syntax. To work around this, you should first load the free variable into a local variable and then use it from the macro.

fn uses_free_variable() {
q!(move || custom_macro!(abc = CLUSTER_SELF_ID)) // don't do this, compiler error
q!(move || {
let local = CLUSTER_SELF_ID;
custom_macro!(abc = local)
}) // works!
}