Skip to content

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

@jepers

Description

@jepers
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()

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions