Unnecessary phantom warnings

move reports “The parameter ‘T’ is only used as an argument to phantom parameters. Consider adding a phantom declaration here”

struct Foo<T: drop + store + key> {
    bars: VecSet<T>,

@shiqicao, can you share the full code example, and the version of the sui CLI you are using?

I tried to reproduce this locally with this code:

module test::test {
    use sui::vec_set::VecSet;
    struct Foo<T: copy + drop + store> {
        bars: VecSet<T>,

Built with CLI version 1.7.0-5764a24d3a (a fairly recent build on main), and it didn’t produce this warning. But it’s possible that you are using a different implementation of VecSet? The version that’s part of Sui Framework requires copy and doesn’t allow key which makes me think that’s a possibility.

sorry for the incorrect repro, it only repro with table, try this one.

    struct Foo<T: drop + store> {
        bar: Table<u8, T>,

Ah, this is actually a legitimate error because the type parameters for Table are also phantom.

Rust doesn’t require recursively marking phantom, what’s the purpose of marking it phantom in Move? If the reason is the same as Rust, then it doesn’t need to be marked recursively.

The reason is different and is detailed here:

The abilities for the instantiation of a generic type are calculated as the abilities declared on the type intersected with the abilities of the actual type parameter(s). E.g.

struct Foo<T, phantom U> has copy {
  x: T

struct Bar has copy {}
struct Baz {}

Foo<Bar, Baz> // has copy
Foo<Baz, Bar> // does not have copy