[swift-evolution] Binding generic types using a metatype parameter

Joanna Carter joanna at carterconsulting.org.uk
Fri Mar 25 05:21:29 CDT 2016


>> extension PropertyType
>> {
>>  private static func create() -> Property<Self>
>>  {
>>    typealias SelfType = Self
>> 
>>    return Property<SelfType>.init()
>>  }
>> }
> 
> Oops, that's definitely a bug.

Excellent! I would also say that I have had a different error with…

  private static func create() -> PropertyProtocol
  {
    return Property<Self>() // without the explicit .init
                   ^ Non-associative operator is adjacent to operator of the same precedence
                   ^ No'>' candidates produce the expected contextual result type 'PropertyProtocol'
  }

So, it would seem that omitting the .init and using Self is interpreted differently to using the .init and using Self. I'd hate you to solve one bug just to find another for a very similar use case :-)

> Oops, my fault, this one is by design. Since we're calling through a dynamic type, our type system isn't able to express the result type `Property<valueType>`, so we need to abstract it behind the PropertyProtocol.

Understood and somewhat expected. It's just that the error message is somewhat distant from the error site and seemingly not connected.

>> Of course, after all this effort, I still have the problem of how to get the Any.Type from the SubjectType property of a Mirror into a PropertyType.Type.
> 
> That one's easy, at least—you can take `Any.Type` and use `as?` to cast it to `PropertyType.Type`.

You'd have thought so wouldn't you. But although this works fine…

      let childMirror = Mirror(reflecting: child.value)
      
      print(child.label, child.value, childMirror.subjectType)
      
      let subjectType = childMirror.subjectType
      
      print(subjectType)
      
      if let propertyType = subjectType as? PropertyType.Type
      {
        let property = PropertyFactory.createProperty(propertyType)
        
        print(property)
      }

… this doesn't…

    let intType: Any.Type = Int.self
    
    print(intType)
    
    if let propertyType = intType as? PropertyType.Type // this cast fails
    {
      if var property = PropertyFactory.createProperty(propertyType) as? Property<Int?>
      {
        property.value = 123
        
        print(property)
      }
    }

>> What would really make life easier here would be the ability to extend Any.
>> 
>> Any chance?
> 
> I think that'd be cool. Some people fear the power (and ensuing responsibility) that unleashes, though…

Of course there will always be abusers of power but, by not permitting it, low level framework code becomes more difficult, onerous and obfuscated to write. Framework writers have always had to bear far more responsibility - think Cocoa ;-)

Joanna

--
Joanna Carter
Carter Consulting



More information about the swift-evolution mailing list