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-8817] Type nested in function unable to conform to protocols with operator requirements #51325

Closed
ffried opened this issue Sep 21, 2018 · 3 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@ffried
Copy link
Contributor

ffried commented Sep 21, 2018

Previous ID SR-8817
Radar None
Original Reporter @ffried
Type Bug
Status Resolved
Resolution Duplicate

Attachment: Download

Environment
Apple Swift version 4.2 (swiftlang-1000.11.37.1 clang-1000.11.45.1)
Target: x86_64-apple-darwin18.0.0

Also happens with Swift 4.1 in Xcode 9.4.1

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

md5: 7df70af54efa8d7dc9ecb55e48ac9d5a

duplicates:

  • SR-8696 Types nested in functions and their operator functions.

Issue Description:

The following code emits an error that SomeComparable does not conform to Comparable:

func someComparableFunc() {
   struct SomeComparable: Comparable {
      static func == (lhs: SomeComparable, rhs: SomeComparable) -> Bool { return false }
      static func < (lhs: SomeComparable, rhs: SomeComparable) -> Bool { return true }
   }
}

The only requirement (<) is implemented, though.

Output:

$ swift s42_nestedStructConformances.swift 
s42_nestedStructConformances.swift:2:11: error: type 'SomeComparable' does not conform to protocol 'Comparable'
   struct SomeComparable: Comparable {
          ^
Swift.<:1:13: note: candidate has non-matching type '((), ()) -> Bool'
public func < (lhs: (), rhs: ()) -> Bool
            ^
Swift.<:1:13: note: candidate has non-matching type '<A, B where A : Comparable, B : Comparable> ((A, B), (A, B)) -> Bool'
public func < <A, B>(lhs: (A, B), rhs: (A, B)) -> Bool where A : Comparable, B : Comparable
            ^
Swift.<:1:13: note: candidate has non-matching type '<A, B, C where A : Comparable, B : Comparable, C : Comparable> ((A, B, C), (A, B, C)) -> Bool'
public func < <A, B, C>(lhs: (A, B, C), rhs: (A, B, C)) -> Bool where A : Comparable, B : Comparable, C : Comparable
            ^
Swift.<:1:13: note: candidate has non-matching type '<A, B, C, D where A : Comparable, B : Comparable, C : Comparable, D : Comparable> ((A, B, C, D), (A, B, C, D)) -> Bool'
public func < <A, B, C, D>(lhs: (A, B, C, D), rhs: (A, B, C, D)) -> Bool where A : Comparable, B : Comparable, C : Comparable, D : Comparable
            ^
Swift.<:1:13: note: candidate has non-matching type '<A, B, C, D, E where A : Comparable, B : Comparable, C : Comparable, D : Comparable, E : Comparable> ((A, B, C, D, E), (A, B, C, D, E)) -> Bool'
public func < <A, B, C, D, E>(lhs: (A, B, C, D, E), rhs: (A, B, C, D, E)) -> Bool where A : Comparable, B : Comparable, C : Comparable, D : Comparable, E : Comparable
            ^
Swift.<:1:13: note: candidate has non-matching type '<A, B, C, D, E, F where A : Comparable, B : Comparable, C : Comparable, D : Comparable, E : Comparable, F : Comparable> ((A, B, C, D, E, F), (A, B, C, D, E, F)) -> Bool'
public func < <A, B, C, D, E, F>(lhs: (A, B, C, D, E, F), rhs: (A, B, C, D, E, F)) -> Bool where A : Comparable, B : Comparable, C : Comparable, D : Comparable, E : Comparable, F : Comparable
            ^
Swift.Character:2:24: note: candidate has non-matching type '(Character, Character) -> Bool'
    public static func < (lhs: Character, rhs: Character) -> Bool
                       ^
Swift.Character.UnicodeScalarView.Index:2:24: note: candidate has non-matching type '(Character.UnicodeScalarView.Index, Character.UnicodeScalarView.Index) -> Bool'
    public static func < (lhs: Character.UnicodeScalarView.Index, rhs: Character.UnicodeScalarView.Index) -> Bool
                       ^
Swift.ClosedRange<Bound>.Index:3:24: note: candidate has non-matching type '<Bound> (ClosedRange<Bound>.Index, ClosedRange<Bound>.Index) -> Bool'
    public static func < (lhs: ClosedRange<Bound>.Index, rhs: ClosedRange<Bound>.Index) -> Bool
                       ^
Swift.Dictionary<Key, Value>.Index:3:24: note: candidate has non-matching type '<Key, Value> (Dictionary<Key, Value>.Index, Dictionary<Key, Value>.Index) -> Bool'
    public static func < (lhs: Dictionary<Key, Value>.Index, rhs: Dictionary<Key, Value>.Index) -> Bool
                       ^
Swift.LazyDropWhileCollection<Base>.Index:3:24: note: candidate has non-matching type '<Base> (LazyDropWhileCollection<Base>.Index, LazyDropWhileCollection<Base>.Index) -> Bool'
    public static func < (lhs: LazyDropWhileCollection<Base>.Index, rhs: LazyDropWhileCollection<Base>.Index) -> Bool
                       ^
Swift.FlattenCollection<Base>.Index:2:24: note: candidate has non-matching type '<Base> (FlattenCollection<Base>.Index, FlattenCollection<Base>.Index) -> Bool'
    public static func < (lhs: FlattenCollection<Base>.Index, rhs: FlattenCollection<Base>.Index) -> Bool
                       ^
Swift.FloatingPoint:3:24: note: candidate has non-matching type '<Self> (Self, Self) -> Bool'
    public static func < (lhs: Self, rhs: Self) -> Bool
                       ^
Swift.BinaryInteger:4:24: note: candidate has non-matching type '<Self, Other> (Self, Other) -> Bool'
    public static func < <Other>(lhs: Self, rhs: Other) -> Bool where Other : BinaryInteger
                       ^
Swift.UInt8:12:24: note: candidate has non-matching type '(UInt8, UInt8) -> Bool'
    public static func < (lhs: UInt8, rhs: UInt8) -> Bool
                       ^
Swift.Int8:12:24: note: candidate has non-matching type '(Int8, Int8) -> Bool'
    public static func < (lhs: Int8, rhs: Int8) -> Bool
                       ^
Swift.UInt16:12:24: note: candidate has non-matching type '(UInt16, UInt16) -> Bool'
    public static func < (lhs: UInt16, rhs: UInt16) -> Bool
                       ^
Swift.Int16:12:24: note: candidate has non-matching type '(Int16, Int16) -> Bool'
    public static func < (lhs: Int16, rhs: Int16) -> Bool
                       ^
Swift.UInt32:12:24: note: candidate has non-matching type '(UInt32, UInt32) -> Bool'
    public static func < (lhs: UInt32, rhs: UInt32) -> Bool
                       ^
Swift.Int32:14:24: note: candidate has non-matching type '(Int32, Int32) -> Bool'
    public static func < (lhs: Int32, rhs: Int32) -> Bool
                       ^
Swift.UInt64:12:24: note: candidate has non-matching type '(UInt64, UInt64) -> Bool'
    public static func < (lhs: UInt64, rhs: UInt64) -> Bool
                       ^
Swift.Int64:14:24: note: candidate has non-matching type '(Int64, Int64) -> Bool'
    public static func < (lhs: Int64, rhs: Int64) -> Bool
                       ^
Swift.UInt:12:24: note: candidate has non-matching type '(UInt, UInt) -> Bool'
    public static func < (lhs: UInt, rhs: UInt) -> Bool
                       ^
Swift.Int:12:24: note: candidate has non-matching type '(Int, Int) -> Bool'
    public static func < (lhs: Int, rhs: Int) -> Bool
                       ^
Swift.Unicode.Scalar:2:24: note: candidate has non-matching type '(Unicode.Scalar, Unicode.Scalar) -> Bool'
    public static func < (lhs: Unicode.Scalar, rhs: Unicode.Scalar) -> Bool
                       ^
Swift.ObjectIdentifier:2:24: note: candidate has non-matching type '(ObjectIdentifier, ObjectIdentifier) -> Bool'
    public static func < (lhs: ObjectIdentifier, rhs: ObjectIdentifier) -> Bool
                       ^
Swift.LazyPrefixWhileCollection<Base>.Index:3:24: note: candidate has non-matching type '<Base> (LazyPrefixWhileCollection<Base>.Index, LazyPrefixWhileCollection<Base>.Index) -> Bool'
    public static func < (lhs: LazyPrefixWhileCollection<Base>.Index, rhs: LazyPrefixWhileCollection<Base>.Index) -> Bool
                       ^
Swift.ReversedCollection<Base>.Index:3:24: note: candidate has non-matching type '<Base> (ReversedCollection<Base>.Index, ReversedCollection<Base>.Index) -> Bool'
    public static func < (lhs: ReversedCollection<Base>.Index, rhs: ReversedCollection<Base>.Index) -> Bool
                       ^
Swift.Set<Element>.Index:3:24: note: candidate has non-matching type '<Element> (Set<Element>.Index, Set<Element>.Index) -> Bool'
    public static func < (lhs: Set<Element>.Index, rhs: Set<Element>.Index) -> Bool
                       ^
Swift.Strideable:2:24: note: candidate has non-matching type '<Self> (Self, Self) -> Bool'
    public static func < (x: Self, y: Self) -> Bool
                       ^
Swift.StringProtocol:4:24: note: candidate has non-matching type '<Self, R> (Self, R) -> Bool'
    public static func < <R>(lhs: Self, rhs: R) -> Bool where R : StringProtocol
                       ^
Swift.String:2:24: note: candidate has non-matching type '(String, String) -> Bool'
    public static func < (lhs: String, rhs: String) -> Bool
                       ^
Swift.String.Index:2:24: note: candidate has non-matching type '(String.Index, String.Index) -> Bool'
    public static func < (lhs: String.Index, rhs: String.Index) -> Bool
                       ^
Swift._UIntBuffer<Storage, Element>:4:28: note: candidate has non-matching type '<Storage, Element> (_UIntBuffer<Storage, Element>.Index, _UIntBuffer<Storage, Element>.Index) -> Bool'
        public static func < (lhs: _UIntBuffer<Storage, Element>.Index, rhs: _UIntBuffer<Storage, Element>.Index) -> Bool
                           ^
Swift.UnsafeMutablePointer<Pointee>:2:24: note: candidate has non-matching type '<Pointee> (UnsafeMutablePointer<Pointee>, UnsafeMutablePointer<Pointee>) -> Bool'
    public static func < (lhs: UnsafeMutablePointer<Pointee>, rhs: UnsafeMutablePointer<Pointee>) -> Bool
                       ^
Swift.UnsafePointer<Pointee>:2:24: note: candidate has non-matching type '<Pointee> (UnsafePointer<Pointee>, UnsafePointer<Pointee>) -> Bool'
    public static func < (lhs: UnsafePointer<Pointee>, rhs: UnsafePointer<Pointee>) -> Bool
                       ^
Swift.UnsafeMutableRawPointer:2:24: note: candidate has non-matching type '(UnsafeMutableRawPointer, UnsafeMutableRawPointer) -> Bool'
    public static func < (lhs: UnsafeMutableRawPointer, rhs: UnsafeMutableRawPointer) -> Bool
                       ^
Swift.UnsafeRawPointer:2:24: note: candidate has non-matching type '(UnsafeRawPointer, UnsafeRawPointer) -> Bool'
    public static func < (lhs: UnsafeRawPointer, rhs: UnsafeRawPointer) -> Bool
                       ^
Swift._ValidUTF8Buffer<Storage>:4:28: note: candidate has non-matching type '<Storage> (_ValidUTF8Buffer<Storage>.Index, _ValidUTF8Buffer<Storage>.Index) -> Bool'
        public static func < (lhs: _ValidUTF8Buffer<Storage>.Index, rhs: _ValidUTF8Buffer<Storage>.Index) -> Bool
                           ^
Swift._SwiftNSOperatingSystemVersion:3:24: note: candidate has non-matching type '(_SwiftNSOperatingSystemVersion, _SwiftNSOperatingSystemVersion) -> Bool'
    public static func < (lhs: _SwiftNSOperatingSystemVersion, rhs: _SwiftNSOperatingSystemVersion) -> Bool
                       ^
Swift.AnyIndex:3:24: note: candidate has non-matching type '(AnyIndex, AnyIndex) -> Bool'
    public static func < (lhs: AnyIndex, rhs: AnyIndex) -> Bool
                       ^
Swift.Comparable:2:24: note: protocol requires function '<' with type '(SomeComparable, SomeComparable) -> Bool'; do you want to add a stub?
    public static func < (lhs: Self, rhs: Self) -> Bool

When trying the same with Equatable, the conformance seems to be accepted, but the implemented == func is not called:

func someEquatableFunc() {
   struct SomeEquatable: Equatable {
      static var didCallEquatable = false
      static func == (lhs: SomeEquatable, rhs: SomeEquatable) -> Bool {
          didCallEquatable = true
          return true
      }
   }
   _ = SomeEquatable() == SomeEquatable()
   print(SomeEquatable.didCallEquatable) // -> false
}
someEquatableFunc()
@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@AnthonyLatsis AnthonyLatsis closed this as not planned Won't fix, can't repro, duplicate, stale Jun 3, 2022
@ffried
Copy link
Contributor Author

ffried commented Jun 3, 2022

@AnthonyLatsis Is there a specific reason for this not being planned? And will diagnostics be improved in this case?

@AnthonyLatsis
Copy link
Collaborator

I'm not sure why, but apparently we're supposed to close duplicates as 'not planned', which I probably shouldn't have and agree is confusing.

If you follow the chain, the oldest duplicated issue is still open, and has a PR attached that would fix it.

@ffried
Copy link
Contributor Author

ffried commented Jun 3, 2022

@AnthonyLatsis Ah, got it, thanks for clarifying! Found the open one and subscribed to it.

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
Projects
None yet
Development

No branches or pull requests

2 participants