Nested struct inside another struct, not the same as standalone struct?

I'm getting a compile error with this:

struct Foo<content: Hashable> {
    struct Holder {
        static var x = 0   // Compile error: Static stored properties not supported in generic types
    }
}

I thought the above is the same as this:

struct Holder {
    static var x = 0 
}

struct Foo<content: Hashable> {
}

So nested struct is not the same as stand alone one? I thought they are the same, just scope is different.

Asking this for my own understanding nest struct. I can just make Holder private

I looks more like this

struct Holder<Content: Hashable> {
    static var x = 0 
}

Sorry, the example is simplified minimum to ask my question. The Holder is actually a SwiftUI.PreferenceKey

struct Holder: PreferenceKey {
    ....
    static var defaultValue: ....
    ....
}

Foo is a container View...I wanted to hide the Holder inside Foo but was getting this compile error. So I ask this question...why I'm not allow to put nest Holder?

You cannot declare static properties inside generic types. The language doesn't support it today. This is because the semantics aren't very clear, should Structure<Int> share the same static variables as Structure<String> or should they be distinct? You probably should be able to do the former, but that hasn't been decided yet and behaviour and syntax are simply not designed. Hence, the compiler bans it outright.

This applies to nested or top level types, static properties inside generic types simply are not allowed anywhere. In your case, as Foo is generic on content, then any nested type inside Foo is also generic on content (this might be easier to grasp if you think about the fully-qualified type of Holder β€” it is Foo<content>.Holder).

1 Like

If Foo is generic, it’s still the same that Holder is generic.

1 Like

Everything (every type, function, etc) that is nested inside a generic type inherits the generic context of its parent.

2 Likes

If you just want this for namespacing, and the inner struct should be non-generic, then you can use a typealias:

struct FooBar {
  static var x = 0
}

struct Foo<T> {
  typealias Bar = FooBar
}

Foo.Bar.x += 1
3 Likes

So I just learned I can have static properties inside a generic type by using computed property.

So my first example can be:

struct Foo<content: Hashable> {
    struct Holder {
        static var x: Int { 0 }
    }
}

with this, my generic SwiftUI.View can directly implement PreferenceKey. So I can avoid defining free standing PreferenceKey and refer to its Type as Self.self

1 Like