Could some types be allowed to be nested in generic functions?

What are the reasons for not allowing this:

func f<T>(_ v: T) {
    struct S { // ERROR: Type 'S' cannot be nested in generic function 'f'
        let a: Int
        let b: Bool
    }
}

?

Given that the following compiles:

func g<T>(_ v: T) {
    typealias S = (
        a: Int,
        b: Bool
    )
}
6 Likes

Nobody decided if S defined inside f<String> and inside f<Data> should be the same type or not yet

4 Likes

In the first example, the struct is defining a completely new type with new type metadata, its own initializers and property getters/setters, and so forth. In the second, the typealias is merely a new name for an existing type; nothing new is being generated (and AFAICT, typealiases that aren't accessible outside the module aren't emitted at all in the serialized module file).

3 Likes

What difference would it make? Ie, let's say S is the same type no matter the type parameter (because it doesn't use any type parameter), what problem can it cause? The type is only available/existing within the scope of the function afaics.

func foo<T: Numeric>(_ n: T) -> Int {
  struct Bar {
    static var x: Int = 0
  }
  
  if n == 0 {
    Bar.x += 1
  }
  return Bar.x
}

print(foo(0))
print(foo(0.0))

What should get printed?

2 Likes

Right, I didn't think about static stored properties. So it seems like S (or Bar) should not be the same type for different type parameters then, which would sort of make them generic, but static stored properties are not allowed in generic types ...

There's only one possible answer—yes, the type is different for each set of outer type arguments. This just hasn't been implemented yet.

9 Likes