why is unresolved generic type legal in a generic?

Viewed 105

Perhaps I'm being extremely dense, and I realize I'm supposed to know about this sort of thing, but I was taken by surprise by this:

class Wrapper<T> {
    let value: T
    var wrapper: Wrapper? // ok
    init(value: T) {
        self.value = value
    }
}
class Thing {
    var wrapper: Wrapper? // error
}

The error is that inside class Thing I have to resolve the Wrapper generic when I declare the type; I need to say, for instance,

var wrapper: Wrapper<String>?

Why is legal to declare that a property has type Wrapper plain and simple inside a Wrapper but not elsewhere? What makes the declaration inside Wrapper okay? Is it because the compiler just assumes that inside Wrapper, Wrapper means Wrapper<T>?

1 Answers

In the case of Wrapper, T is known, as it's part of Wrapper's definition, so use of Wrapper without specialization is implicitly assumed to be Wrapper<T>

In the case of Thing, there is no T defined, and even if there were, it would not be the same T as in Wrapper. Think of it being analogous to these functions:

func foo(_ x: Int) {
   // x is known here
}

func bar() {
   // x is unheard of here.
}

func foobar(_ x: Int) {
   // x is known here, but it's not the same x as in foo
}

Of course the difference is that even foo has to refer to x explicitly, whereas Wrapper can infer T within its own definition. In fact, if Wrapper wants to refer to another Wrapper that's specialized on a different type, it has to be explicit about it:

class Wrapper<T> {
   ...
   func someConversion<U>(otherWrapper: Wrapper<U>) {
   }
}

Thing on the other hand is declared outside of Wrapper, so it doesn't know about T. So from its perspective

var wrapper: Wrapper?

is just as meaningless as

var values: Array?

The compiler can't create an array if it doesn't know the Element type. Neither can it create your Wrapper without knowing what T is.

Related