So without any initial constraints how would one use this generic function??

extension UIButton: ProtocolA {}

let button = UIButton()
let shadowedButton: ProtocolA = UIButton()

// creates a set of a least one element if the generic type could be inferred
func unionIfPossible<T, U>(_ a: T, _ b: U) -> Set<Any<T, U>>? { /* merge 
somehow if possible */ }

You would not be able to form Any<T, U> here because T and U are generic 
arguments unknown.  We don’t accept those, only `class`, specific classes, and 
specific protocols (and recursively, other Any).

Why would Any<…> does not work with the generic system here? To me it makes no 
sense, I as a developer would assume I can use a generic Type anywhere a type 
can be used (protocols and their associated types are a special case).

I would assume that:

func foo<T: UIView>(value: Any<T, SomeProtocol>)

should be equal to (without the need of generics):

func foo(value: Any<UIView, SomeProtocol>)


// this should be valid because the compiler will assume Any<UIView, ProtocolA> 
where T == UIView and U == ProtocolA
let merged_1: Set<Any<UIView, ProtocolA>> = unionIfPossible( /* UIView subtype 
*/ button, /* ProtocolA */ shadowedButton) 

// this won’t be possible because of the restriction
let merged_2: Set<Any<UIView, ProtocolA>> = unionIfPossible(shadowedButton, 
button) 

Any<UIView, ProtocolA> != Any<ProtocolA, UIView> isn’t right. Sure it may feel 
right for readability but the types should be equal.

"Can be any class type that is a UIView or a subclass of UIView, that also 
conforms to ProtocolA.“ == "Type that conforms to ProtocolA and that is a 
UIView or a subclass of UIView.“

This is also a nesting problem where you will be forced to choose the right 
place inside the angle brackets where to add a nested `Any<…>`.

class A: ClassB, ProtocolA {}

Any<A, Any<ClassB, ProtocolA>> == A != Any<Any<ClassB, ProtocolA>, A> == 
Any<ClassB, ProtocolA, A> which should be reorder by the compiler and inferred 
as A

`Any<Any<ClassB, ProtocolA>, A>` is not allowed because if a class is provided 
it must come first.

`Any<ClassB, ProtocolA, A>` is not allowed because it contains more than one 
class.
Not true, take a look at the nested section of the proposal again.

We discussed that this is valid:

// Allowed, but pointless.
// Identical to Any<ProtocolA, ProtocolB>
let b : Any<Any<ProtocolA, ProtocolB>>

This implies that also this would be valid:

Any<Any<ClassA, ProtocolA>> inferred as Any<ClassA, ProtocolA>

There is another example:

// Can be any type that is a UITableView conforming to ProtocolA.
// UITableView is the most specific class, and it is a subclass of the other
// two classes.
let a : Any<UIScrollView, Any<UITableView, Any<UIView, ProtocolA>>>

Which followed by the mentioned rule can als be:

Any<UIScrollView, UITableView, Any<UIView, ProtocolA>> or
Any<UIScrollView, UITableView, UIView, ProtocolA>

This would force us to allow multiple classes inside Any<…> if there is a 
inheritance relationship between them.

And because this is a inheritance relationship it can be simplified to:

Any<UITableView, ProtocolA> which is valid. 

And by the way since the order in your proposal would matter, this example 
won’t work at all, because its not:

Any<UITableView, Any<UIScrollView, Any<UIView, ProtocolA>>> 

In my proposal I explicitly banned multiple reference types and inheritance 
branches like this. I would need to simplify that type to Any<UITableView, 
ProtocolA> by myself.
Ingeneral this is a good idea, but it makes nesting (with typealiases) almost 
impossible, when there are some relationship like in the above example.


-- 
Adrian Zubarev
Sent with Airmail
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to