More type checker unexpected weirdness

Another bit of an oddity.

I've added Span, RawSpan, MutableSpan, MutableRawSpan to my stdlib and when I try to compile I'm seeing these types of errors...

MutableRawSpan.swift:21:12: warning: unrecognized platform name 'SwiftCompatibilitySpan' [#AvailabilityUnrecognizedName]
 19 | @safe
 20 | @frozen
 21 | @available(SwiftCompatibilitySpan 5.0, *)
    |            `- warning: unrecognized platform name 'SwiftCompatibilitySpan' [#AvailabilityUnrecognizedName]
 22 | @_originallyDefinedIn(module: "Swift;CompatibilitySpan", SwiftCompatibilitySpan 6.2)
 23 | public struct MutableRawSpan: ~Copyable & ~Escapable {

MutableRawSpan.swift:38:20: error: invalid use of borrow dependence with consuming ownership
 36 |   @_unsafeNonescapableResult
 37 |   @_alwaysEmitIntoClient
 38 |   @lifetime(borrow pointer)
    |                    `- error: invalid use of borrow dependence with consuming ownership
 39 |   internal init(
 40 |     _unchecked pointer: UnsafeMutableRawPointer?,

The code in question so you don't have to go hunting is...

@safe
@frozen
@available(SwiftCompatibilitySpan 5.0, *)
@_originallyDefinedIn(module: "Swift;CompatibilitySpan", SwiftCompatibilitySpan 6.2)
public struct MutableRawSpan: ~Copyable & ~Escapable {
  @usableFromInline
  internal let _pointer: UnsafeMutableRawPointer?

  @usableFromInline
  internal let _count: Int

  @_alwaysEmitIntoClient
  internal func _start() -> UnsafeMutableRawPointer {
    unsafe _pointer._unsafelyUnwrappedUnchecked
  }

  @unsafe
  @_unsafeNonescapableResult
  @_alwaysEmitIntoClient
  @lifetime(borrow pointer)
  internal init(
    _unchecked pointer: UnsafeMutableRawPointer?,
    byteCount: Int
  ) {
    unsafe _pointer = pointer
    _count = byteCount
  }
}

FYI My compile command is...

"/Users/carl/Documents/Code/swift-project/build/Ninja-RelWithDebInfoAssert/swift-macosx-arm64/bin/swiftc" -parse-as-library -parse-stdlib -target avr-none-none-elf  -nostdimport -I uSwiftShims  -I "/Applications/S4A IDE Pro.app/Contents/XPCServices/BuildEngine.xpc/Contents/Resources/lib/avr-libgcc/include" -I "/Applications/S4A IDE Pro.app/Contents/XPCServices/BuildEngine.xpc/Contents/Resources/lib/avr-libc/include" -Xcc -DAVR_LIBC_DEFINED -Xcc -DLIBC_DEFINED -DAVR_LIBC_DEFINED_SWIFT  -DFORCE_MAIN_SWIFT_ARRAYS -enable-experimental-feature Embedded -enable-experimental-feature LifetimeDependence -enable-experimental-feature MoveOnly -enable-experimental-feature ExistentialAny -enable-experimental-feature BitwiseCopyable -Xfrontend -disable-reflection-metadata -Xfrontend -disable-stack-protector -Osize -whole-module-optimization -emit-module -emit-module-path bin/AVR-Embedded/Swift.swiftmodule -module-name Swift CoreOperators.swift CoreAliases.swift RawRepresentable.swift LiteralProtocols.swift TopLevelFunctions.swift CoreProtocols.swift CoreFloatingPoint.swift CoreBinaryFloatingPoint.swift Float.swift Float16.swift CoreFloatingPointFunctions.swift Optional.swift Bridging.swift CoreNumericProtocols.swift BinaryInteger.swift CoreIntegers.swift ErrorType.swift Bool.swift Integers.swift Ranges.swift Sequence.swift Stride.swift Slice.swift Collection.swift BidirectionalCollection.swift RandomAccessCollection.swift ClosedRange.swift MutableCollection.swift Hash.swift Pointer.swift UnsafeBufferPointer.swift UnsafeRawBufferPointer.swift UnsafeRawPointer.swift Indices.swift Existential.swift Algorithm.swift FixedWidth.swift IntegerMath.swift CTypes.swift UnsafePointer.swift ObjectIdentifier.swift CollectionAlgorithms.swift WriteBackMutableSlice.swift Random.swift RangeReplaceableCollection.swift MemoryLayout.swift Tuple.swift SequenceAlgorithms.swift LifetimeManager.swift Repeat.swift EmptyCollection.swift CollectionOfOne.swift StringLiterals.swift StaticString.swift StringInterpolation.swift Unicode.swift UnicodeScalar.swift UnicodeEncoding.swift UTF8.swift UTF16.swift ValidUTF8Buffer.swift UnicodeParser.swift UIntBuffer.swift UTFEncoding.swift UTF32.swift ArrayType.swift ArrayBufferProtocol.swift ArrayLiterals.swift ArrayShared.swift ContiguousArray.swift SliceBuffer.swift ArraySlice.swift Array.swift ArrayBody.swift ArrayCast.swift AnyHashable.swift ManagedBuffer.swift Reverse.swift Map.swift Zip.swift LazySequence.swift LazyCollection.swift Filter.swift FlatMap.swift Flatten.swift DropWhile.swift Volatile.swift uSwift.swift Identifiable.swift OptionSet.swift Sendable.swift SetAlgebra.swift Unmanaged.swift ContiguousArrayBuffer.swift Volatile-stdlib.swift MutableRawSpan.swift MutableSpan.swift RawSpan.swift Span.swift Integer-16.swift IntegerMath-16.swift CTypes-16.swift Progmem.swift EmbeddedRuntime.swift version.swift

I don't understand why the compiler thinks this constructor has a "consuming ownership"?

What am I doing wrong here? Any advice gratefully received!

Carl

These are defined in swift/utils/availability-macros.def at main · swiftlang/swift · GitHub.

Your compiler is too old or new for your stdlib, I forget which.

OK, I'll update both.

(Both are around ten days old I think.)

Thanks!

Hmm... updated swift to fa3db90ae378dc088d30c167f21f0d058117f118 including the standard library, rebuilt the compiler, copied over the contents of MutableSpan, Span, RawSpan, MutableRawSpan exactly and tried again. Same compiler diagnostic.

Weird.

I think I'm going to have to build a debug version of the compiler put a breakpoint in swift/lib/AST/LifetimeDependence.cpp at main · swiftlang/swift · GitHub and try to work out what's going on when I compile these files separately.

It looks like the issue is here...

  bool isCompatibleWithOwnership(ParsedLifetimeDependenceKind kind, Type type,
                                 ValueOwnership loweredOwnership,
                                 bool isInterfaceFile = false) const {
    if (kind == ParsedLifetimeDependenceKind::Inherit) {
      return true;
    }
    if (kind == ParsedLifetimeDependenceKind::Borrow) {
      // An owned/consumed BitwiseCopyable value can be effectively borrowed
      // because its lifetime can be indefinitely extended.
      if (loweredOwnership == ValueOwnership::Owned
          && isBitwiseCopyable(type, ctx)) {    <<<<< ISSUE IS HERE
        return true;
      }
      if (isInterfaceFile) {
        return loweredOwnership == ValueOwnership::Shared ||
               loweredOwnership == ValueOwnership::InOut;
      }
      return loweredOwnership == ValueOwnership::Shared;
    }
    assert(kind == ParsedLifetimeDependenceKind::Inout);
    return loweredOwnership == ValueOwnership::InOut;
  }

It seems like isBitwiseCopyable is returning false for UnsafeMutableRawPointer even though I think it should conform to BItwiseCopyable in my setup, here are the relevant excerpts from my stdlib...

@frozen
@unsafe
public struct UnsafeMutableRawPointer: @unsafe _Pointer {
...

public protocol _Pointer
: Hashable, Strideable, BitwiseCopyable {
...

...I'm not sure why this isn't working. I'll debug a bit further and I'll let you guys know on here when I get to the bottom of it.

The clue was in the debugger... when I got the nominal type, nominal->dump() yielded a load of information but the important point was it was actually checking the conformance of Optional to BitwiseCopyable. What I was missing from my stdlib was...

extension Optional: BitwiseCopyable
where Wrapped: BitwiseCopyable & ~Escapable {}

...obvious when you think about it! :slight_smile:

Pretty nearly up and running now (hopefully my last compiler errors are trivial AVR platform specific issues).

Thank you everyone!