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-7019] Not all required, yet missing, methods for a protocol are noticed. #49567

Open
swift-ci opened this issue Feb 17, 2018 · 3 comments
Open
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself standard library Area: Standard library umbrella

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-7019
Radar None
Original Reporter CTMacUser (JIRA User)
Type Bug

Attachment: Download

Additional Detail from JIRA
Votes 0
Component/s Compiler, Standard Library
Labels Bug
Assignee @moiseev
Priority Medium

md5: ddc029a67510ed37a7c56ef6172e582c

Issue Description:

This is based from a thread I created on the Swift discussion forums.

I made a sample extended unsigned integer type. I had to create (stub) implementations for the arithmetic operations, but the compiler didn't insist the same for the bit-wise operations. I originally thought that those operations were defined in a source file I hadn't discovered yet. But another poster said that those operations should have been flagged. (This implies that there is no other source for those methods in the Swift Standard Library.)

To make sure, I added a call to the bitwise-AND operator, and sure enough it compiled yet crashed. (I first tried bitwise-shift-left, but that caused a "inlining 'transparent' functions forms circular loop" error.)

@belkadan
Copy link
Contributor

cc @moiseev

@moiseev
Copy link
Mannequin

moiseev mannequin commented Feb 19, 2018

This is an amazing discovery! Prior to Swift 4 and the new integers, there was a protocol called `BitwiseOperations`. It was deemed not needed with the introduction of the integer protocols. But, for backward compatibility, it was left in the standard library as `_BitwiseOperations` with a conditionally available typealias `BitwiseOperations`. That protocol declares only the "non-muating" operators, the mutating ones (i.e. `|=` and friends) are defined as free functions here:

/// Calculates the union of bits sets in the two arguments and stores the result
/// in the first argument.
///
/// - Parameters:
/// - lhs: A value to update with the union of bits set in the two arguments.
/// - rhs: Another value.
@_inlineable // FIXME(sil-serialize-all)
public func |= <T : _BitwiseOperations>(lhs: inout T, rhs: T) {
lhs = lhs | rhs
}
/// Calculates the intersections of bits sets in the two arguments and stores
/// the result in the first argument.
///
/// - Parameters:
/// - lhs: A value to update with the intersections of bits set in the two
/// arguments.
/// - rhs: Another value.
@_inlineable // FIXME(sil-serialize-all)
public func &= <T : _BitwiseOperations>(lhs: inout T, rhs: T) {
lhs = lhs & rhs
}
/// Calculates the bits that are set in exactly one of the two arguments and
/// stores the result in the first argument.
///
/// - Parameters:
/// - lhs: A value to update with the bits that are set in exactly one of the
/// two arguments.
/// - rhs: Another value.
@_inlineable // FIXME(sil-serialize-all)
public func ^= <T : _BitwiseOperations>(lhs: inout T, rhs: T) {
lhs = lhs ^ rhs
}

As you can see, they are implemented in terms of `_BitwiseOperations` protocol requirements, which is reasonable.

Now the interesting part. In the new integer protocols we established a convention to provide default implementations for non-mutating functions in terms of mutating ones (exactly the opposite of a much earlier decision made for BitwiseOperations). So now, when you define a type that conforms to the `FixedWidthInteger`, even though both mutating and non-mutating bitwise operations are required, the default implementation of `|` comes from extension FixedWidthInteger, and the default implementation of `|=` comes from the _BitwiseOperations free functions. And they are mutually recursive. Hence the crash.

Unfortunately this is not a unique case where a protocol requirement can be accidentally fulfilled unexpectedly and self-recursively. But in this case, it should be very much possible to mark the default implementations coming from the `_BitwiseOperations` as obsolete from Swift 4 onward.

Transparent and infinite inlining might have similar causes, but is a separate issue from this.

@moiseev
Copy link
Mannequin

moiseev mannequin commented Feb 21, 2018

Tentative fix: #14761

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
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 standard library Area: Standard library umbrella
Projects
None yet
Development

No branches or pull requests

2 participants