Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent Type Inference with Generics and Protocols in Closure #68306

Open
alessionossa opened this issue Sep 4, 2023 · 0 comments
Open
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels

Comments

@alessionossa
Copy link

Description
When combining protocols with type constraints and generics for function’s parameter type, the type returned by the function in the closure is different from the type of the other parameter, even though in the body of the function it is required that they are the same.

Example:

protocol SpecialViewControllerProtocol: GenericViewController {
    func doSomeMagic()
}

class DisplayManager {
    func displaySpecialVC() {
        let vc: SpecialViewControllerProtocol = MyViewController()
        goTo(viewController: vc) { actualVC in            
            actualVC.doSomeMagic() // removing this line, the error is gone
        }
    }
    
    private func goTo<T: GenericViewController>(viewController: T, completion: ((T) -> Void)? = nil) {
        completion?(viewController)
        // completion?(MyViewController()) // ERROR: Cannot convert value of type 'MyViewController' to expected argument type 'T'
    }
}

class GenericViewController { }

class MyViewController: GenericViewController, SpecialViewControllerProtocol {
    func doSomeMagic() {
        print("Magic1!")
    }
}

let vc: SpecialViewControllerProtocol = MyViewController()
let displayManager = DisplayManager()
displayManager.displaySpecialVC()

viewController parameter in goTo(viewController:completion:) is correctly bound to T that in displaySpecialVC() will be SpecialViewControllerProtocol, however the type of actualVC is just GenericViewController instead of T and it requires a casting like guard let actualVCCasted: SpecialViewControllerProtocol = actualVC as? SpecialViewControllerProtocol else { return } in order to call protocols’s functions.

I took a look at #61296 and #58624, but it seems that this is a different case.

Steps to reproduce
See example above.

Expected behavior
The type returned in the closure completion should be the same as the one passed in the parameter viewController.

Environment

  • Swift compiler version info swift-driver version: 1.75.2 Apple Swift version 5.8.1 (swiftlang-5.8.0.124.5 clang-1403.0.22.11.100) - Target: x86_64-apple-macosx13.0
  • Xcode version info Xcode 14.3.1 - Build version 14E300c
  • Deployment target: macOS 13.5.1 (22G90)
@alessionossa alessionossa added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels labels Sep 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels
Projects
None yet
Development

No branches or pull requests

1 participant