Error: type of expression is ambiguous without more context

Hi.

I am trying address TODO in internal function _applyMapping of Unicode.Scalar.Properties swift/UnicodeScalarProperties.swift at 172c0472f6acbc37a6a0b70b57fadf181d2e30b0 · apple/swift · GitHub

Here is my implementation using _FixedArray16:

internal func _applyMapping(_ u_strTo: _U_StrToX) -> String {
  let count = 64
  var array = _FixedArray16<UInt64>(allZeros: ()) // 16 * UInt64 take 128 bytes, same as 64 * UInt16
  let len: Int = array.withUnsafeMutableBufferPointer { bufPtr in
    return _scalar.withUTF16CodeUnits { utf16 in
      var err = __swift_stdlib_U_ZERO_ERROR
      let correctSize = u_strTo(
        UnsafeMutableRawPointer(bufPtr.baseAddress!).bindMemory(to: UInt16.self, capacity: count),
        Int32(count),
        utf16.baseAddress._unsafelyUnwrappedUnchecked,
        Int32(utf16.count),
        "",
        &err)
      guard err.isSuccess else {
        fatalError("Unexpected error case-converting Unicode scalar.")
      }
      // TODO: _internalInvariant(count == correctSize, "inconsistent ICU behavior")
      return Int(correctSize)
    }
  }
  // TODO: replace `len` with `count`
  let result: String = array.withUnsafeBufferPointer{
// error: type of expression is ambiguous without more context
//    let result: String = array.withUnsafeBufferPointer{
//                             ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
    return String._uncheckedFromUTF16(UnsafeRawPointer($0).bindMemory(to: UInt16.self, capacity: len))
  }
  return result
}

I am having compile error "type of expression is ambiguous without more context" as shown in snippet above.

Whatever I do I can't fix this compile error.

Any help is appreciated.

Regards,
Valeriy Van

Let's try to go backwards.

_uncheckedFromUTF16 expects an UnsafeBufferPointer<UInt16>. However, the return type on UnsafeRawPointer.bindMemory(to:capacity:) is UnsafePointer. That seems to be tripping up the compiler. The correct thing (from a types perspective, I'm hardly an expert on memory binding) to do would be to create an UnsafeRawBufferPointer and then call bindMemory on it, which would give you an UnsafeBufferPointer.

Here's a verbose version:

let result = array.withUnsafeBufferPointer { (bp : UnsafeBufferPointer<UInt64>) -> String in
    let ubp = UnsafeRawBufferPointer(bp).bindMemory(to: UInt16.self)
    return String._uncheckedFromUTF16(ubp)
}

To follow up on that, I think from a memory binding perspective withMemoryRebound should be what you're looking for here:

let result = array.withUnsafeBufferPointer { (bp : UnsafeBufferPointer<UInt64>) -> String in
    return bp.withMemoryRebound(to: UInt16.self) {
        String._uncheckedFromUTF16($0)
    }
}
1 Like

It did work. Refactors internal func _applyMapping using _FixedArray16 by valeriyvan · Pull Request #31333 · apple/swift · GitHub
Thank you!

Just for reference, I just minimize this sample created [SR-12689] Undiagnosed argument mismatch involving pointer types · Issue #55133 · apple/swift · GitHub

2 Likes