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

[SR-12120] Compiler forgets some constraints of P within extension to P, known bug? #54555

Closed
jepers opened this issue Feb 3, 2020 · 2 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior.

Comments

@jepers
Copy link

jepers commented Feb 3, 2020

Previous ID SR-12120
Radar rdar://problem/59132837
Original Reporter @jepers
Type Bug
Status Resolved
Resolution Done
Environment

default toolchain of Xcode 11.3.1 (11C504)
and
dev snapshot 2020-01-31.

Additional Detail from JIRA
Votes 0
Component/s
Labels Bug
Assignee None
Priority Medium

md5: 6b948778adbd99c276cd9fd5b1463369

Issue Description:

Forum thread:
https://forums.swift.org/t/compiler-forgets-some-constraints-of-p-within-extension-to-p-known-bug/33386


//----------------------------------------------------------------------------
// This program demonstrates (what I assume must be) a compiler bug.
// The compiler forgets some of the same type constraints of the protocol in
// protocol extensions. The issue can be worked around by restating those
// constraints at the extension.
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
// Compiling without the workaround (ie this program, as is):
//----------------------------------------------------------------------------
// $ swiftc --version
// Apple Swift version 5.1.3 (swiftlang-1100.0.282.1 clang-1100.0.33.15)
// Target: x86_64-apple-darwin19.2.0
// $ swiftc test.swift
// test.swift:43:33: error: cannot convert value of type 'Self.Swapped.B' to specified type 'Self.A'
//         let _: Self.A = swapped.b // <- ERROR: Cannot convert value of type
//                         ~~~~~~~~^
//                                   as! Self.A
// test.swift:46:33: error: cannot convert value of type 'Self.Swapped.A' to specified type 'Self.B'
//         let _: Self.B = swapped.a // <- ERROR: Cannot convert value of type
//                         ~~~~~~~~^
//                                   as! Self.B
//
// Same thing when using dev snapshot 2020-01-31, ie:
// Apple Swift version 5.2-dev (Swift a0fbeb9179)
// Target: x86_64-apple-darwin19.2.0
//
//----------------------------------------------------------------------------
// Compiling and running with the workaround (ie after uncommenting line 62):
//----------------------------------------------------------------------------
// $ swiftc test.swift && ./test
// 123 abc
// abc 123
//----------------------------------------------------------------------------


/// A type with a "swapped dual".
/// ```
/// x.swapped.swapped == x
/// && x.a == x.swapped.b
/// && x.b == x.swapped.a
/// ```
/// Note that `x` and `x.swapped` can be of different types,
/// and so can `x.a` and `x.b`.
protocol Swappable where
    Swapped: Swappable,
    Swapped.Swapped == Self,
    Swapped.A == B, Swapped.B == A
{
    associatedtype A
    associatedtype B
    associatedtype Swapped
    var a: A { get }
    var b: B { get }
    var swapped: Swapped { get }
}


// This should compile according to constraints of Swappable, but does not:
extension Swappable
    // WORKAROUND: Uncomment these (restated) constraints:
    // where Swapped.A == B, Swapped.B == A
{
    func bar() {
        let _: Self = swapped.swapped // <- Compiles as expected.
        let _: Self.A = swapped.b // <- ERROR: Cannot convert value of type
        //           'Self.Swapped.B' to specified
        //           type 'Self.A'.
        let _: Self.B = swapped.a // <- ERROR: Cannot convert value of type
        //           'Self.Swapped.A' to specified
        //           type 'Self.B'.
    }
}


struct Pair<L, R> {
    var left: L
    var right: R
}
extension Pair : Swappable{
    var a: L { return left }
    var b: R { return right }
    var swapped: Pair<R, L> { return Pair<R, L>(left: right, right: left) }
}

func foo() {
    // This works as expected (with or without the extension):
    let op = Pair(left: 123, right: "abc") // (op = Original Pair)
    let sp = op.swapped                    // (sp = Swapped Pair)
    print(op.left, op.right) // 123 abc
    print(sp.left, sp.right) // abc 123
}
foo()
@beccadax
Copy link
Contributor

beccadax commented Feb 4, 2020

@swift-ci create

@slavapestov
Copy link
Member

#42113

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
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.
Projects
None yet
Development

No branches or pull requests

3 participants