Types from Swift Standard Library as a generic type

Shouldn't types from the Swift Standard Library, example Bool , Int , String , Float
Be flagged by the compiler when used as a generic type.
This would prevent the code below from compiling.

 func foo<Int>(a: Int, b: String) {
    print(a)
    print(b)
}

var a = "Yello"
var b = "World"

foo(a: a,b: b)
1 Like

Standard Library Types are just normal types, they don't, and aren't supposed to, have any privilege.

It's much like you write this.

struct Foo { }

func foo<Foo>(a: Foo, b: String) {
  print(a, b)
}

foo(a: "Hello", b: "World")

Foo inside foo will just shadow struct Foo.

Whether it should emit warning and/or have mechanism to refer to shadowed Foo, that's debatable.

4 Likes

Yeah, this is the same basic shadowing problem as this nonsense (combined with an old, somewhat evil feature called tuple shuffling):

let a: (Int: Int, Double: Int) = (1, 2)
let (Double: Double, Int: Int) = a

print(Double) // 2
print(Int) // 1
print(type(of: Int)) // Int
print(type(of: Double)) // Int
1 Like

I'd say the answer is obviously "no" and the counter example is Result. Result is a too generic word that it fits in a lot different contexts, which does not imply that it should ever only mean Swift.Result<Success, Failure>. It would be odd if the compiler would not allow us to call our generic type parameters whatever we wanted.

2 Likes

But isn’t that the normal argument in favour of shadowing everywhere, and doesn’t the normal counter-argument apply: that it makes things more confusing for humans (if not also the compiler)?

My first reaction is that this is just another example of Swift’s namespacing problem, and would be better solved through language enhancements for namespacing than simply allowing confusing shadowing.

I personally consider shadowing a bad practice, at least if there is no obvious reasoning for it like readability of an API. Since I'm no compiler developer I can only guess that not every shadowing scenario can be captured/handled by the compiler or even should. There are likely to be some examples out there where you want to shadow the generic type of the enclosing generic context but also at the same time want to be able to reference it.

Here is one non-valid example where shadowing is a consequence of nesting:

struct FirstDimension<Element> {
	struct SecondDimension<Element> where Element == FirstDimension.Element {
		...
	}
}

However that requires a feature that we still don't have in Swift, qualified lookup for generic type parameters. I discussed this topic in more detail in this thread.

Long story short, I personally wouldn't support the proposed restrictions as they already would prevent code to compile in some of my codebases (e.g. Result as a generic type parameter name). Even though I don't care much about breaking changes, the benefit of this special case does not outweigh the consequences from my perspective.

If someone can present some strong arguments why we really should apply that special case, I'd be happy to re-consider my view point. :+1:

1 Like