[Ranted]Allow to compare generic types without providing a signature specialization

This thread is dead. Help me write a better pitch, if you are interested.


Currently, in swift to compare two generic types, the generic signature has to be explicitly declared.

Array<Int>.self == Array<String>.self // compiles

Array<Int>.self == Array.self // doesnt

There might be a time when it is not necessary to specify the full signature; for example, when the semantic of a type does not depend on the signature or members of the type are not parameterized with types from the generic signature.

//for type erasure
struct Box<T> { var value: T; func dealocate() {...} }
let dealocTarget: Box<?> = Box<Int>
dealocTarget.dealocate()

//for reflection
struct A<T> { var val: Optional<T> }
Mirror.init(reflecting: A(val:0))
  .children[0 as AnyIndex].value == Optional<?>.self
//nice, now i know val's semantic

Can you relax this strictness, @core-team

1 Like

What you're suggesting is much, much more complicated than you're suggesting. It's not just relaxing strictness. It's generating completely new kind of an object that doesn't exist in Swift today.

For example, have you considered what would be the type of x here? Would this code even compile?

struct Test<T: Collection> {
    static var index: T.Index? { nil }
}
let x = Test<?>.index

It would be erased as well, but have the same bounds as Index. This is essentially Any? but more strict.
Since its a type member rather than instance member, the type would have been Optional<?>

It seems like it is just Any with a bit different flavour, or erasing with protocol type parametrization.

I think we have different definitions of "just"


Your suggestion looks like the thing kotlin does

interface A { fun a() }
interface B { fun b() }
data class Box<T>(var value: T) where T: A, T: B {
    fun dealocate() {}
}
class Foo: A, B {
    override fun a() { }
    override fun b() { }
}
fun main() {
    val dealocTarget: Box<*> = Box<Foo>(Foo())
    dealocTarget.dealocate()
    // dealocTarget.value = 456 // Setter for 'value' is removed by type projection
	dealocTarget.value.a()
}

It would be cool to have a feature like that if you manage to find someone willing to design and implement it.

Improving the UI of generics among other things suggests to introduce existential containers for generic types, with syntax being any Optional, any Array, etc.

You would not be able to compare meta types as equal, but you could check values by casting:

var x: Array<Int> = [1, 2, 37]
var y: any Array = x
print(type(of: y)) // prints 'Array<Int>'
y = ["abc", "xyz"] // ok
print(type(of: y)) // prints 'Array<String>'

print(Array<Int>.self == (any Array).self) // prints 'false'
print(Array<String>.self == (any Array).self) // prints 'false'

var z: Any = y
print(z is Array<Bool>) // prints 'false'
print(z is Array<String>) // prints 'true'
print(z is any Array) // prints 'true'

@total_swiftification, does this solve your use case?

2 Likes

Not really. I want to have actors and to do that I intended to use reflection to enforce certain properties about members of such construct. Something like this:

struct ImageLoader: ActorProtocol {
  @Unique
  var currentImage: Image
  @Shared
  var filters: Set<CIFilter>
  @Behaviour
  var load = { (url: URL) -> () in ... }
}
@Actor var loader = ImageLoader()

Then with mirror I would check types of the fields and set the appropriate dispatch strategy.
Can do it still with dummy protocol, something like struct Behaviour: _isBehaviour and then check it with is, but that seems like a hack, and swift already has planty of them. It would be reasonable to tackled them down.

I believe, that should say yes to be useful

Hi @total_swiftification – would you mind not routinely pinging the core team group on your pitches?

4 Likes

I was expecting this line to solve your problem:

For your case you would do something like

if value is (any Behaviour) {
    ...
}

But any Behaviour and Behaviour<(URL) -> Void> are still different types. The former is the super type of the later, but they are not equal.

1 Like

Another formulation of this you might want to consider is an 'as?' cast that can introduce new generic parameters. For example,

let a: Dictionary = ["hi":1, "bye":2, "ok":3]

if let aa = a? as <K : Hashable, V> Dictionary<K, V> {
  if K.self == Int.self {
    ...
  }
}

If the cast succeeds, then the concrete type stored inside the Any is bound to Dictionary<K, V>, and you can refer to the abstract key and value types as K and V, with K known to conform to Hashable.

We've discussed adding something like this, at least internally, for SIL's generic specialization passes.

9 Likes

It sounds intriguing, but I can't wrap my head around this example; why a is accessed as it was optional? (with ? operator).


Anyway, the rest of the example looks interesting.

I assume that the type of aa becomes Dictionary<?,?> (? is analogous to java's existentials).
And existential parameterization could be very useful and a lot of people here need and want it already.


Do you know what is the current decision about this feature inside the core team? Shall we see it in swift 6? (7, 8 ...)?

It's not very useful to probe the core team at every junction. One of the better questions would be whether someone is implementing the feature. While the core team does make the call (and someone needs to make the call), Swift Evolution is more of a place to exchange the pros, cons and feasibility of the design rather than an authoritarian announcement. Also, believe it or not, the core team consists of multiple people (or that's what they want us to believe β–³πŸ‘), so there may not even be a consensus on a particular subject matter. While it is crucial that some broad strokes come from them, including the Principles for Trailing Closure Evolution Proposals, acquiring an opinion that represents the entire group takes a lot of effort.

1 Like

To clarify, I am not doing this routinely, nor I do it at every junction. These statements would be appropriate if I was doing it on a per-week basis for no constructive reason. If you had read the one (1) thread where I mentioned ct, @Ben_Cohen, you'd find (hopefully) that the matters discussed there worth your time; and also I don't know with whom to speak about issues that was raised there; they seemed like a design flaw. (Although I had some positive exchange with Jordan Rose).
The problem remains: I came across many threads in this cite and found that there are discussions about expanding the type system in many useful ways, yet there is no consistent answer to what is going to be implemented and when. Recently I encountered a case that resembled me about all that stuff with types and that made me curious about what is the current state of this topic; I doubt that there is a better candidate to be asked then the core team. Is that clear?


They are called core team. And it is about the time to do these things (or at least say if these ever going to be implemented), since their initial appearance, that happened somewhat ~2 years ago.


Lets summ up a bit: where are existential with associated types? If they going to appear?If yes, then when? And if yes, then would generic types, have the same feature of type erasure (see java' wildcard)?
There is also a question about mutability that is involved with all these things, but (since I spent more time on this forums than I should) I'll just wait until the official information that I heard coming.
So yes, if anyone on this site knows, where all this going to happen, then go ahead and tell me, would you? (answers will definitely impact many of my near-term decisions)

You're misunderstanding the role of the core team. It is more about approving/adjusting the proposal to maintain the coherence and overall swift-iness of the proposals. Of course, they could also work with the implementation but that's the same as essentially anyone in the community.


You can just ask the community at large. If anyone is working on it, asking on this forum (without mentioning anyone) will be just as good. On the same note, if there's no answer, it's likely that no one is working on it. Many features got in by someone in the communiy implementing them themselves, afterall.

6 Likes

Pretty. So the language which is not completely finished with its internals and foundational semantic is already given away to all the people out there who should "just" spend their time digging around the huge c++ codebase for no reward other than avowal, doing what essentially is the duty of the project initiator(apple/core team)? Is there at least a single vision of what it should become? Right now all I know is a bag of words such as 'disclosure of complexity' and 'something as a library feature', and a pile of design docs on git.

Yes, please! This would also be incredibly useful for unboxing existentials in to local generic parameters, allowing conditional downcasting to protocols with associated types. That’s a real limitation with the language we have today.

If you can write this:

if let aa = a? as <K : Hashable, V> Dictionary<K, V> {

It follows that this should also be possible:

if let aa = a? as <T: RandomAccessCollection> T {

2 Likes

Take a look at this forum. There are at least weekly new proposals for features and improvements of the language. Most of those proposals are worked on by volunteers, who neither work at Apple nor are in the core team.
Sure this process needs a bit more time, but you can't just overlook the massive improvements Swift has made in the last years.

And yes...there is quite a clear vision for the future of Swift, shared by a member of the core team over here.

3 Likes

It's a typo. I meant to write if let aa = a as? <...>.

I have no idea and I don't speak for the core team. I'm just suggesting your pitch is more likely to gain traction if you pursue this approach of binding new generic parameters, rather than allowing them to be simply omitted.

4 Likes

Ok, I see. I have another question, though: would a and aa from your example be equal when compared with is expression?

Software is never finished.

How many years between C++'s public introduction and the last new version?

I think the emphasis here is a little off.

Swift is a work in progress. Those who wish to work on it can. If it feels like a burden to do so, then don't do it (well unless someone is paying you to do it, and the pay beats out the burden).

The ability to work on an open source project is an extra option in people's lives, but not a requirement.

1 Like

That comparison is irrelevant, since cpp wasn't backed by a trillion-dollar company and a pack of people with math phds.

It is already used in production, so that statement is to be doubted.
There is no evidence of progress on important things like type system and fixing bugs with protocols. At least the mutability is coming. Hooray for that.

Terms of Service

Privacy Policy

Cookie Policy