Closed joshuabach closed 4 years ago
I ran into the same bug, it's still present in 0.1.31 and the workaround still works.
Ran into this issue on 0.1.36
.
Just to be clear for everyone who arrived here with the same error, the work workaround is to first assign the table name with let, and then use that in the macro:
Instead of:
println!("Associated:{}", Self::ASSOCIATED);
Use:
let a = Self::ASSOCIATED;
println!("Associated:{}", a);
@the-notable: Do you mean this issue has not been fixed yet? (0.1.36 is a newer version than 0.1.32 (#100) which closed this issue)
@taiki-e The following code produced this error on both versions 0.1.36
and 0.1.39
EDIT: I see this issue was related to trait impl rather than trait declarations. I'm having this issue with trait declarations, which were supposed to be fixed in #74 ?
pub trait Model {
fn table_name() -> &'static str;
}
#[async_trait]
pub trait FindAll: Model {
async fn find_all<T, Q: Queryable>(q: &mut Q) -> Result<Vec<T>> {
let sql = format!("SELECT * FROM {}", Self::table_name());
find(q, sql.as_str()).await
}
}
error[E0433]: failed to resolve: use of undeclared type or module `AsyncTrait`
--> src/model/mod.rs:77:47
|
77 | let sql = format!("SELECT * FROM {}", Self::table_name());
| ^^^^ use of undeclared type or module `AsyncTrait`
This, however, compiles:
pub trait Model {
fn table_name() -> &'static str;
}
#[async_trait]
pub trait FindAll: Model {
async fn find_all<T, Q: Queryable>(q: &mut Q) -> Result<Vec<T>> {
// Assign tn with let because #[async_trait] macro won't work with Self inside other macros
let tn = Self::table_name();
let sql = format!("SELECT * FROM {}", tn);
find(q, sql.as_str()).await
}
}
@the-notable Thanks. I'll look into that.
Ok, this is due to HasSelf
doesn't check Self
inside macros.
First, here is minimized repro:
macro_rules! mac {
($($tt:tt)*) => {
$($tt)*
};
}
pub trait Trait1 {
fn func1();
}
#[async_trait::async_trait]
pub trait Trait2: Trait1 {
async fn func2() {
mac!(Self::func1());
}
}
And the following async function is generated:
async fn __func2() {
AsyncTrait::func1();
}
But the async function that should be generated (the function generated when macro does not exist) here is:
async fn __func2<AsyncTrait: ?Sized + Trait2>() {
<AsyncTrait>::func1()
}
The type parameter AsyncTrait
is generated when the trait method has the self
argument or when Self
keyword is used in the method. So that means HasSelf
that detects Self
keyword is not working for the macro.
I'll send a fix.
Filed #124
Issue #73 only revealed part of the problem, and only part of it was fixed.
Since Merge Request #74
Self
inside macro invocation works when used in the trait declaration, but the issue persists in the trait impl. See this example:Compiler output:
Tested with 0.1.30.
Workaround from original issue (
let
-binding) also works.