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-7429] Cannot conform a non-final class to a protocol with a defaulted requirement with a generic placeholder constrained to an associated type #49972

Closed
hamishknight opened this issue Apr 13, 2018 · 6 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself regression swift 4.1

Comments

@hamishknight
Copy link
Collaborator

Previous ID SR-7429
Radar None
Original Reporter @hamishknight
Type Bug
Status Resolved
Resolution Duplicate
Environment

Swift version 4.2-dev (LLVM 064f71a292, Clang 238f385323, Swift 18b28b9)
Target: x86_64-apple-darwin17.5.0

Additional Detail from JIRA
Votes 1
Component/s Compiler
Labels Bug, 4.1Regression
Assignee None
Priority Medium

md5: 358353b1fcad620d1abf6070b802116e

duplicates:

  • SR-7428 Class conforming to protocol with default method implementation no longer compiles with Xcode 9.3

relates to:

  • SR-7428 Class conforming to protocol with default method implementation no longer compiles with Xcode 9.3

Issue Description:

The following compiles in Swift 4.0.3, but not in 4.1:

protocol P {
  associatedtype Q = String
  func foo<T>(_ t: T) where T == Q
}

extension P {
  func foo<T>(_ t: T) where T == Q {}
}

class C : P {}

// error: type 'C' does not conform to protocol 'P'
// class C : P {}
//       ^
// note: candidate has non-matching type '<Self, T> (T) -> ()' [with Q = String]
// func foo<T>(_ t: T) where T == Q { }
//      ^
// note: protocol requires function 'foo' with type '<T> (T) -> ()'; do you want to add a stub?
// func foo<T>(_ t: T) where T == Q
//      ^

Marking C as final or making it a struct, as well as removing the associated type constraint on foo makes the code compile again in 4.1.

Note that this regression impacts conformance of a non-final class to RangeReplacableCollection:

class Foo<Element> {
  required init() {}
  // required init<S : Sequence>(_ elements: S) where Element == S.Element {}
  private var base: [Element] = []
}

extension Foo : Collection {
  typealias Index = Int

  var startIndex: Index {
    return base.startIndex
  }

  var endIndex: Index {
    return base.endIndex
  }

  func index(after i: Index) -> Index {
    return base.index(after: i)
  }

  subscript(index: Index) -> Element {
    return base[index]
  }
}

extension Foo : RangeReplaceableCollection {

  // func append<S : Sequence>(contentsOf newElements: S) where Element == S.Element {}
  func replaceSubrange<C : Collection>(
    _ subrange: Range<Index>, with newElements: C
  ) where Element == C.Element {}
}


// error: type 'Foo<Element>' does not conform to protocol 'RangeReplaceableCollection'
// extension Foo : RangeReplaceableCollection {
// ^
//   Swift.RangeReplaceableCollection:5:26: note: candidate has non-matching type '<Self, S> (contentsOf: S) -> ()' [with SubSequence = Foo<Element>.SubSequence]
//   public mutating func append<S>(contentsOf newElements: S) where S : Sequence, Self.Element == S.Element
//                        ^
//   Swift.RangeReplaceableCollection:9:26: note: protocol requires function 'append(contentsOf:)' with type '<S> (contentsOf: S) -> ()'; do you want to add a stub?
//   public mutating func append<S>(contentsOf newElements: S) where S : Sequence, Self.Element == S.Element
//                        ^

The two commented lines (the required init and append(contentsOf:)) need to be uncommented for the code to compile in 4.1.

@hamishknight
Copy link
Collaborator Author

Oh wow this seems to be a dupe of https://bugs.swift.org/browse/SR-7428 filed 4 minutes earlier.

@hamishknight
Copy link
Collaborator Author

cc @slavapestov – looking at the error message, could this be related to your work on adding the constrained Self placeholder to witness thunks for classes?

@belkadan
Copy link
Contributor

cc @huonw, @DougGregor

@DougGregor
Copy link
Member

This appears to be a consequence of the type soundness hole we closed (despite known source-compatibility issues) and discussed in https://bugs.swift.org/browse/SR-5265,

@slavapestov
Copy link
Member

The original soundness hole was https://bugs.swift.org/browse/SR-617. The example in this bug report is itself due to a hack that was meant to preserve source compatibility with another corner case. See the big comment here:

if (!classDecl->isFinal()) {

@slavapestov
Copy link
Member

I didn't realize the hack itself had source compatibility implications. Perhaps this is a sign we should rip out the hack and fix the real soundness problem it was working around in the stdlib/Foundation.

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

No branches or pull requests

5 participants