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-11516] Simplest MutableDataProtocol generates initializer that spins forever #53917
Comments
yeah, MutableDataProtocol is a RRC:
|
That’s not really the relevant part. It’s fine that MutableDataProtocol must be an RRC. What’s not fine is that ByteBucket doesn’t implement any of the required API for RRC: it has no replaceSubrange method. That means MutableDataProtocol is providing the implementation, and whatever implementation it is providing is clearly leading to an infinite recursion. |
I don't think we have a good answer for this. How is the compiler supposed to know which requirement you want to implement to break the cycle? |
Yeah, I tagged the compiler but I don’t know if the compiler can resolve this. I do think that something (probably MutableDataProtocol) has not correctly documented its implementation requirements, because I don’t think anything is obviously implemented incorrectly here. |
Comment by Sergo Beruashvili (JIRA) The problem seems that RangeReplaceableCollection requires custom implementation of replaceSubrange, https://github.com/apple/swift/blob/master/stdlib/public/core/RangeReplaceableCollection.swift#L57 But... It also provides its own replaceSubrange, which just forwards it to custom implementation, but since there is no custom one, it calls itself - https://github.com/apple/swift/blob/master/stdlib/public/core/RangeReplaceableCollection.swift#L746 MutableDataProtocol just declares conformance of RRC - https://github.com/apple/swift/blob/master/stdlib/public/Darwin/Foundation/DataProtocol.swift#L73 Adding following code to the ByteBucket fixes it: mutating func replaceSubrange<C>(_ subrange: Range<Data.Index>, with newElements: __owned C) where C: Collection, C.Element == Element {
underlyingData.replaceSubrange(subrange, with: newElements)
} |
Jordan, is it correct that the default implementation of |
Ah, it's not desirable but it is correct. :-/ @lorentey, any ideas? |
Nice analysis, ogres (JIRA User). |
Ah, thanks Sergo – this is a new incarnation of the same issue that we have seen with `RandomNumberGenerator.next()` vs `.next<F>()`. It doesn't bode well that we got this wrong twice now. What if we added a @_not_implements(RangeReplaceableCollection) attribute that would remove these from consideration during conformance checks? |
Environment
Apple Swift version 5.1.1 (swiftlang-1100.0.273 clang-1100.0.33.9)
Target: x86_64-apple-darwin19.0.0
Additional Detail from JIRA
md5: e90e078aa56172fe96027339f8b054ce
duplicates:
Issue Description:
The following sample program, which is basically the simplest possible
MutableDataProtocol
, generates an initializer that spins forever:This program will never exit (release mode) or will segfault (debug mode), though it definitely should run cleanly.
This appears to be the result of the default implementations for `RangeReplaceableProtocol`. Taking a look at the debug mode call stack gives us a call stack 65k frames deep. The base is:
The above stack shows the infinite recursion:
There is no code in my sample that actually implements any of the requirements of
RangeReplaceableCollection
, which suggests thatMutableDataProtocol
is bringing them in somehow. This is backed up by the fact that if the above program is changed to change the wordsMutableDataProtocol
toDataProtocol
, the program fails to compile.I don't know if this is a compiler bug or a Foundation bug, so it goes to both teams.
The text was updated successfully, but these errors were encountered: