Skip to content

error: ambiguous use of 'remquo' with C++ interop and explicit module build on Windows #85606

@hjyamauchi

Description

@hjyamauchi

Description

This overload ambiguity error happens because

  • The C/C++ types double and long double are typealias to each other in Swift on Windows
  • The system C++ header cmath.h defines a remquo function overload for long double which conflicts with the one in the C header corecrt_math.h in Swift,.

Note the C++ compiler can disambiguate this but in Swift the distinction between the two types are lost.

error: compile-module-from-interface command failed with exit code 1 (use -v to see invocation)
S:\Program Files\Swift\Platforms\Windows.platform\Developer\SDKs\Windows.sdk\usr\lib\swift\windows\CRT.swiftmodule\x86_64-unknown-windows-msvc.private.swiftinterface:335:13: error: ambiguous use of 'remquo'
333 | @_transparent public func remquo(_ x: Swift.Double, _ y: Swift.Double) -> (Swift.Double, Swift.Int) {
334 |   var quo = Int32(0)
335 |   let rem = remquo(CDouble(x), CDouble(y), &quo)
    |             `- error: ambiguous use of 'remquo'
336 |   return (Double(rem), Int(quo))
337 | }

C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt\corecrt_math.h:565:44: note: found this candidate in module 'corecrt'
 563 |     _Check_return_ _ACRTIMP double __cdecl nexttoward(_In_ double _X, _In_ long double _Y);
 564 |     _Check_return_ _ACRTIMP double __cdecl remainder(_In_ double _X, _In_ double _Y);
 565 |     _Check_return_ _ACRTIMP double __cdecl remquo(_In_ double _X, _In_ double _Y, _Out_ int* _Z);
     |                                            `- note: found this candidate in module 'corecrt'
 566 |     _Check_return_ _ACRTIMP double __cdecl rint(_In_ double _X);
 567 |     _Check_return_ _ACRTIMP double __cdecl round(_In_ double _X);

C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\cmath:496:20: note: found this candidate in module 'CxxStdlib'
 494 | }
 495 |
 496 | inline long double remquo(_In_ long double _Xx, _In_ long double _Yx, _Out_ int* _Zx) noexcept /* strengthened */ {
     |                    `- note: found this candidate in module 'CxxStdlib'
 497 |     return _CSTD remquol(_Xx, _Yx, _Zx);
 498 | }

This is specific to Windows because of the way the C and the C++ headers declare it. This doesn't occur and the following reproducer test doesn't err on macos because the macos C++ header imports the C remquo into the std namespace for C++ rather than declaring another remquo for long double that would cause an overload with C remquo for long in Swift.

The C header on macos
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/math.h

...
extern double remquo(double, double, int *);
...

The C++ header on macos
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/cmath

...
_LIBCPP_BEGIN_NAMESPACE_STD
...
using ::remquo _LIBCPP_USING_IF_EXISTS;
...

Reproduction

remquo.swift

import CRT
var quo: Int32 = 0
let rem = remquo(5.0, 2.0, &quo)
print(rem, quo)
> swiftc remquo.swift -cxx-interoperability-mode=default -explicit-module-build
error: compile-module-from-interface command failed with exit code 1 (use -v to see invocation)
S:\Program Files\Swift\Platforms\Windows.platform\Developer\SDKs\Windows.sdk\usr\lib\swift\windows\CRT.swiftmodule\x86_64-unknown-windows-msvc.private.swiftinterface:335:13: error: ambiguous use of 'remquo'
333 | @_transparent public func remquo(_ x: Swift.Double, _ y: Swift.Double) -> (Swift.Double, Swift.Int) {
334 |   var quo = Int32(0)
335 |   let rem = remquo(CDouble(x), CDouble(y), &quo)
    |             `- error: ambiguous use of 'remquo'
336 |   return (Double(rem), Int(quo))
337 | }

C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt\corecrt_math.h:565:44: note: found this candidate in module 'corecrt'
 563 |     _Check_return_ _ACRTIMP double __cdecl nexttoward(_In_ double _X, _In_ long double _Y);
 564 |     _Check_return_ _ACRTIMP double __cdecl remainder(_In_ double _X, _In_ double _Y);
 565 |     _Check_return_ _ACRTIMP double __cdecl remquo(_In_ double _X, _In_ double _Y, _Out_ int* _Z);
     |                                            `- note: found this candidate in module 'corecrt'
 566 |     _Check_return_ _ACRTIMP double __cdecl rint(_In_ double _X);
 567 |     _Check_return_ _ACRTIMP double __cdecl round(_In_ double _X);

C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\cmath:496:20: note: found this candidate in module 'CxxStdlib'
 494 | }
 495 |
 496 | inline long double remquo(_In_ long double _Xx, _In_ long double _Yx, _Out_ int* _Zx) noexcept /* strengthened */ {
     |                    `- note: found this candidate in module 'CxxStdlib'
 497 |     return _CSTD remquol(_Xx, _Yx, _Zx);
 498 | }

Expected behavior

No error

Environment

The main branch on Windows

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.triage neededThis issue needs more specific labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions