Hi Ian,

You're right, if there's a function that's specialized everything works well 
(actually, I deleted exactly the same function from my example, in an attempt 
to be brief and succinct :) ). But that kind of ruins the whole point of 
interface specialization and violates the principle of least surprise, don't 
you think?

I don't have enough knowledge about how Swift compiler implements generics to 
speculate is the "right" solution possible or not. If the compiler emits 
different implementations for functions testPrint<Int> and testPrint<String>, 
then it definitely have enought info to pick the right specialized 
implementation, and this is a bug; If not... well, then it's probably best to 
remove the whole feature from the language.

Alex

On June 9, 2016 at 16:05:47, Ian Terrell (ian.terr...@gmail.com) wrote:

Hi Alex,

This is definitely a little confusing. I think it may be intentional behavior 
though.

I don't believe it's tied to scope, but tied to the fact (I think!) that all 
generic specialization methods are statically dispatched.

Although it looks like the printMe method chosen would be based on the T of the 
specialized class at runtime, it's actually based on the T of the printPrinter 
method at compile time. At that time printPrinter has no information about T, 
and so it is tied to the general version of printMe. You can see that if you 
add a specialized printPrinter method:

func printPrinter<T: SignedIntegerType>(printer: PrintClass<T>) {
    printer.printMe()
    testPrint(printer.value)
}

Now the further constrained version of printPrinter is called, which calls the 
further contrained version of printMe.

I hope this helps! And I hope if I got anything wrong someone chimes in to 
correct me. :)

Ian





On Wed, Jun 8, 2016 at 4:44 PM, Aleksandar Petrovic via swift-users 
<swift-users@swift.org> wrote:
Hi swift-users,

I'm trying achieve something similar to C++ template specialization with 
protocol extensions, and I found a strange behavior: 

// ----------

protocol Printer {
    associatedtype TestType
    var value: TestType { get }
    func printMe()
}

extension Printer {
    func printMe() {
        print("Base printer: \(value)")
    }
}

extension Printer where TestType: SignedIntegerType {
    func printMe() {
        print("Int printer: \(value)")
    }
}

func testPrint<T>(value: T) {
    print("testPrint")
}

func testPrint<T where T:SignedIntegerType>(value: T) {
    print("testPrint for int")
}


class PrintClass<T>: Printer {
    var value: T
    init(value: T) { self.value = value }
}

func printPrinter<T>(printer: PrintClass<T>) {
    printer.printMe()
    testPrint(printer.value)
}


let intPrinter = PrintClass(value: 42)
let stringPrinter = PrintClass(value: "test value")

intPrinter.printMe()                    // Int printer: 42
stringPrinter.printMe()               // Base printer: test value

testPrint(intPrinter.value)          // testPrint for int
testPrint(stringPrinter.value)     // testPrint

printPrinter(intPrinter)               // Base printer: 42    (!!!)
                                                 // testPrint                
(!!!)

// ----------

The compiler correctly chooses specialized protocol extension as long as the 
function call is in the same scope with the object declaration. But all 
knowledge about types seems to be lost in the last line, when the scope is 
changed, in function printPrinter(). 

Is this a bug or desired behaviour?

Alex


_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to