-
Notifications
You must be signed in to change notification settings - Fork 4
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
Fully qualify Static
associated type in ToStatic
derive macro
#93
Fully qualify Static
associated type in ToStatic
derive macro
#93
Conversation
Minimal reproducible code:
|
I added a test case above, which failed for some recursive types.
However, I cannot add |
@xkikeg I like the idea of fully qualifying the When I expand the test case with #[derive(ToStatic)]
struct Foo<T: IntoBoundedStatic + ToBoundedStatic>(T); I get: struct Foo<T: IntoBoundedStatic + ToBoundedStatic>(T);
impl<T: IntoBoundedStatic + ToBoundedStatic + ToBoundedStatic> ToBoundedStatic for Foo<T>
where
T::Static: IntoBoundedStatic + ToBoundedStatic,
{
type Static = Foo<<T as ToBoundedStatic>::Static>;
fn to_static(&self) -> Self::Static {
Foo(self.0.to_static())
}
}
impl<T: IntoBoundedStatic + ToBoundedStatic + IntoBoundedStatic> IntoBoundedStatic for Foo<T>
where
T::Static: IntoBoundedStatic + ToBoundedStatic,
{
type Static = Foo<<T as IntoBoundedStatic>::Static>;
fn into_static(self) -> Self::Static {
Foo(self.0.into_static())
}
} When still fails with (different to the error you reported):
It works if I do:
|
I think this test case also highlights a bug; note the duplicate bound on: impl<T: IntoBoundedStatic + ToBoundedStatic + IntoBoundedStatic> IntoBoundedStatic for Foo<T> Even if we simplify the test case to be: #[derive(ToStatic)]
struct Foo<T: ToBoundedStatic>(T); We still get: impl<T: ToBoundedStatic + ToBoundedStatic> ToBoundedStatic for Foo<T>
where
<T as ToBoundedStatic>::Static: ToBoundedStatic,
{
type Static = Foo<<T as ToBoundedStatic>::Static>;
fn to_static(&self) -> Self::Static {
Foo(self.0.to_static())
}
}
impl<T: ToBoundedStatic + IntoBoundedStatic> IntoBoundedStatic for Foo<T>
where
<T as IntoBoundedStatic>::Static: ToBoundedStatic,
{
type Static = Foo<<T as IntoBoundedStatic>::Static>;
fn into_static(self) -> Self::Static {
Foo(self.0.into_static())
}
} The macro should probably have special handling to filter out the duplicate trait bounds. |
I tried adding fn make_static_generic_predicates(generics: &Generics, target: TargetTrait) -> Vec<WherePredicate> {
let target_bound = target.bound();
generics
.params
.iter()
.filter_map(|param| match param {
GenericParam::Type(param_ty) => {
let var = ¶m_ty.ident;
let param_ty_bounds = ¶m_ty.bounds;
match find_predicate(generics.where_clause.as_ref(), var) {
None if param_ty_bounds.is_empty() => None,
None => Some(parse_quote!(<#var as #target_bound>::Static: #param_ty_bounds)),
Some(predicate_ty) => {
let predicate_bounds = &predicate_ty.bounds;
if param_ty_bounds.is_empty() {
Some(parse_quote!(<#var as #target_bound>::Static: #predicate_bounds))
} else {
Some(parse_quote!(<#var as #target_bound>::Static: #param_ty_bounds + #predicate_bounds))
}
}
}
}
_ => None,
})
.collect()
} Then this test case works: #[test]
fn test_struct_named_fields_bounded_generics() {
#[derive(ToStatic)]
struct Foo<T: IntoBoundedStatic + ToBoundedStatic>(T);
let inner = "foo";
let owned = Foo(inner).into_static();
ensure_static(owned);
} Which expands as: impl<T: IntoBoundedStatic + ToBoundedStatic + ::bounded_static::ToBoundedStatic>
::bounded_static::ToBoundedStatic for Foo<T>
where
<T as ToBoundedStatic>::Static: IntoBoundedStatic + ToBoundedStatic,
{
type Static = Foo<<T as ToBoundedStatic>::Static>;
fn to_static(&self) -> Self::Static {
Foo(self.0.to_static())
}
}
impl<T: IntoBoundedStatic + ToBoundedStatic + ::bounded_static::IntoBoundedStatic>
::bounded_static::IntoBoundedStatic for Foo<T>
where
<T as IntoBoundedStatic>::Static: IntoBoundedStatic + ToBoundedStatic,
{
type Static = Foo<<T as IntoBoundedStatic>::Static>;
fn into_static(self) -> Self::Static {
Foo(self.0.into_static())
}
} |
466a0a0
to
62f8d48
Compare
Pushed an update with my change. Note that the documentation and examples will need to be updated as well. |
Thanks for taking & fixing the issue! |
When the compiler cannot deduce the actual type on expanding derive(ToStatic) macro, it can have an error because T::Static can be ambiguous. This could be solved with qualifying like <T as IntoBoundedStatic>::Static.
62f8d48
to
34294f8
Compare
34294f8
to
d3ee256
Compare
@xkikeg I think this is ready to merge; I trust it works for your use case? |
Static
associated type in ToStatic
derive macro
I briefly checked and mostly looked good to me, but maybe ToStatic derive may not be working for the case ToBoundedStatic/IntoBoundedStatic traits are not used. Let me check tomorrow when I have a time |
LGTM with 2 above comments
If you have this test (without using Into/ToBoundedStatic) it can be covered. |
When the compiler cannot deduce the actual type on expanding
derive(ToStatic)
macro, it can have an error becauseT::Static
can be ambiguous. This could be solved with qualifying like<T as IntoBoundedStatic>::Static
.Context:
Currently I'm working on applying Generic Associated Type to my struct, and then the compiler complies that
::Static
is ambiguous. I suppose this could be solved by fully qualifying the Static type association.See xkikeg/okane#183 for context.