最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

rust - My struct has a field implementing a generic trait G<T>, but it has no fields using T directly. Is this a l

programmeradmin1浏览0评论

I have a struct Foo which a field of some type implementing a generic trait G, but I can't refer to this trait unless I also bind a type T, but then this leads to a compiler error:

type parameter T is never used. consider removing T, referring to it in a field, or using a marker such as std::marker::PhantomData

trait Trait {}
trait GenericTrait<T: Trait> {}

struct Foo<T, G>
where
    T: Trait,
    G: GenericTrait<T>,
{
    t: G,
}

This can be solved by adding a PhantomData for T:

trait Trait {}
trait GenericTrait<T: Trait> {}

struct Foo<T, G>
where
    T: Trait,
    G: GenericTrait<T>,
{
    t: G,
    phantom: PhantomData<T>,
}

But this feels like tricking the compiler, and I'm wondering if there isn't a simpler solution that I'm missing here.

I've also considered to remove the bounds from the struct, but then I run into an error when trying to write an impl block:

trait Trait {}
trait GenericTrait<T: Trait> {}

struct Foo<G> {
    t: G,
}
impl<T: Trait, G: GenericTrait<T>> Foo<G> {}

This doesn't compile because the parameter T is not used in the declaration.

I have a struct Foo which a field of some type implementing a generic trait G, but I can't refer to this trait unless I also bind a type T, but then this leads to a compiler error:

type parameter T is never used. consider removing T, referring to it in a field, or using a marker such as std::marker::PhantomData

trait Trait {}
trait GenericTrait<T: Trait> {}

struct Foo<T, G>
where
    T: Trait,
    G: GenericTrait<T>,
{
    t: G,
}

This can be solved by adding a PhantomData for T:

trait Trait {}
trait GenericTrait<T: Trait> {}

struct Foo<T, G>
where
    T: Trait,
    G: GenericTrait<T>,
{
    t: G,
    phantom: PhantomData<T>,
}

But this feels like tricking the compiler, and I'm wondering if there isn't a simpler solution that I'm missing here.

I've also considered to remove the bounds from the struct, but then I run into an error when trying to write an impl block:

trait Trait {}
trait GenericTrait<T: Trait> {}

struct Foo<G> {
    t: G,
}
impl<T: Trait, G: GenericTrait<T>> Foo<G> {}

This doesn't compile because the parameter T is not used in the declaration.

Share Improve this question edited Mar 15 at 13:31 cafce25 28k5 gold badges45 silver badges58 bronze badges asked Mar 15 at 13:05 TudorTudor 1571 silver badge4 bronze badges 7
  • 3 If those bounds on Foo are proper for solving your problem, then yes. Using PhantomData is absolutely correct. – Aleksander Krauze Commented Mar 15 at 13:09
  • 2 Probably better to just not put the trait bound on the struct to begin with, there's nothing requiring you to. – cafce25 Commented Mar 15 at 13:13
  • I considered this, but then my code will look like this impl<T: Trait, G: GenericTrait<T>> Foo<G> {} And this also doesn't compile because the T type is not constrained in the impl block – Tudor Commented Mar 15 at 13:15
  • 3 There's nothing requiring you to add the bounds to that impl either, move them to the item that needs the bounds. – cafce25 Commented Mar 15 at 13:33
  • 2 Unrelated to your question, you might want to change PhantomData<T> to PhantomData<fn() -> T>, which has the same variance, but it decouples Foo from T regarding autotraits like Send/Sync/Unpin. – user4815162342 Commented Mar 15 at 13:45
 |  Show 2 more comments

1 Answer 1

Reset to default 4

Have you considered changing GenericTrait to instead have an associated type instead of a type parameter, this would look like

trait GenericTrait {
    type AssociatedType: Trait;
}

It would have the effect that now, for any implementing type T, it can only implement GenericTrait once, with one specific AssociatedType, which may not be acceptable for your application, but if it is, then this would solve your issue because it's no longer necessary to provide the generic argument to GenericTrait at all.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论