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-9686] Swift 5 regression: extension applied to type alias not "seen" #52128

Closed
ktoso opened this issue Jan 17, 2019 · 9 comments
Closed

[SR-9686] Swift 5 regression: extension applied to type alias not "seen" #52128

ktoso opened this issue Jan 17, 2019 · 9 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself regression source compatibility swift 5.0

Comments

@ktoso
Copy link
Member

ktoso commented Jan 17, 2019

Previous ID SR-9686
Radar rdar://problem/47352138
Original Reporter @ktoso
Type Bug
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, 5.0Regression, SourceCompatibility
Assignee @slavapestov
Priority Medium

md5: e92e8c40edeaa38d9111378b8f591e2e

is duplicated by:

  • SR-9671 compiler crash: expression has no type / (declref_expr type='' decl=Logging.(file). extension.init(stringLiteral:)

Issue Description:

I believe I found a regression in Swift 5 ( 5.0-DEVELOPMENT-SNAPSHOT-2019-01-16-a ) with regards to 4.2 while working on the logging proposal for the server side swift working group (so context is: https://github.com/weissi/swift-server-logging-api-proposal ).

I'm using these types in a library which is cross compiled for 4.2 and development builds of Swift 5 so noticed it there. The following self contained snippet isolates the issue:

public enum Logging {
}

public extension Logging {
    typealias Metadata = [String: MetadataValue]

    enum MetadataValue {
        case string(String)
        case array([Metadata.Value])
    }
}


extension Logging.Metadata.Value: Equatable {
    // we have to implement it, in reality there's many more cases in the enum
    public static func ==(lhs: Logging.Metadata.Value, rhs: Logging.Metadata.Value) -> Bool {
        switch (lhs, rhs) {
        case (.string(let lhs), .string(let rhs)):
            return lhs == rhs
        case (.array(let lhs), .array(let rhs)):
            return lhs == rhs
        default:
            return false
        }
    }
}

The important bit being that we extend `Logging.Metadata.Value` via the alias through `Metadata`. This works on swift 4.2 but not on 5:

$ swiftenv local 4.2.1
$ swiftc repro.swift


$ swiftenv local 5.0-DEVELOPMENT-SNAPSHOT-2019-01-16-a
$ swiftc repro.swift
repro.swift:29:24: error: type 'Logging.Metadata.Value' (aka 'Logging.MetadataValue') does not conform to protocol 'Equatable'
            return lhs == rhs
                       ^
repro.swift:29:24: error: '<Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool' requires that 'Logging.Metadata.Value' (aka 'Logging.MetadataValue') conform to 'Equatable'
            return lhs == rhs
                       ^
repro.swift:29:24: note: requirement specified as 'Logging.Metadata.Value' (aka 'Logging.MetadataValue') : 'Equatable'
            return lhs == rhs
                       ^
repro.swift:29:24: note: requirement from conditional conformance of '[Logging.Metadata.Value]' (aka 'Array<Logging.MetadataValue>') to 'Equatable'
            return lhs == rhs
                       ^

If we avoid touching the alias it works on all Swift versions:

// NOPE: extension Logging.Metadata.Value: Equatable {
// yes:
extension Logging.MetadataValue: Equatable {

I would hope to be able to use the alias version since this way we have an uniform way to address Key/Value, by always saying Logging.Metadata.Key / Logging.Metadata.Value etc.

@belkadan
Copy link
Contributor

Hm. @slavapestov, how does this relate to your fix for SR-631?

@DougGregor
Copy link
Member

I think I introduced this failure with #18539 . Dictionary only has a nested type named `Value`through indirect means that involve the full type checker (associated type inference, IIUC), which is a layering violation in the compiler that we're trying to eliminate. The language could accommodate this example directly with the (IMO reasonable) extension described at https://forums.swift.org/t/allow-member-lookup-to-find-generic-parameters/7768

@DougGregor
Copy link
Member

It is annoying that we don't get a more-specific diagnostic about our inability to bind this extension, though. That makes it much harder to see what the problem is.

@DougGregor
Copy link
Member

Oh, it's because of the substitution in the typealias. I don't know that future language changes would alter this at all—at best I hope we get a better diagnostic for it.

@belkadan
Copy link
Contributor

Arguably we should get it from Dictionary's generic parameter, no?

@DougGregor
Copy link
Member

Getting it from Dictionary's generic parameter effectively means implementing some of the "substitution" logic needed to resolve a member of a generic type that involves other type parameters. One could handle simple cases of this, but the general case is "all of type checking," and it feels like it might be easier to explain in terms like "cannot name a generic parameter".

@slavapestov
Copy link
Member

Yeah, I think it makes sense to prohibit extensions from naming a type alias whose underlying type is a dependent type.

@rjmccall
Copy link
Member

I've duped SR-9671 to this, but note that SR-9671 demonstrates a crash, not just a rejects-arguably-valid.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@slavapestov
Copy link
Member

Behaves correctly in 5.7:

/private/tmp/SR-9671/swift-server-logger-api/Sources/Logging/Logging.swift:295:1: error: extension of type 'Logging.Metadata.Value' (aka 'Logging.MetadataValue') must be declared as an extension of 'Logging.MetadataValue'
extension Logging.Metadata.Value: ExpressibleByStringInterpolation {
^         ~~~~~~~~~~~~~~~~~~~~~~
/private/tmp/SR-9671/swift-server-logger-api/Sources/Logging/Logging.swift:295:1: note: did you mean to extend 'Logging.MetadataValue' instead?
extension Logging.Metadata.Value: ExpressibleByStringInterpolation {
^         ~~~~~~~~~~~~~~~~~~~~~~
          Logging.MetadataValue

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. compiler The Swift compiler in itself regression source compatibility swift 5.0
Projects
None yet
Development

No branches or pull requests

6 participants