mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-11-15 15:38:10 +00:00
There were a number of iterations on the design that weren't reflected in the initial port to the terminal rendering library. This PR tries to complete the rendering side of things to match the design we landed on: code-focused, with messages attached by lines to the code, and condensed as much as possible to avoid the vertical space. It also improves the styling to make things more visually distinguishable such as adding a `->` to the main error line, and making the underlines and connectors for it have a heavy weight (when the font supports that). Another major change is having multiple messages on a single line be drawn in source lexical order. This requires the connectors to cross without joining, but makes it easier to read the messages. This PR also has some refactorings to enable these improvements, and a _number_ of improvements to comment prose and terminology to try and avoid jargon and make things read more naturally. Sorry for the fact that Claude left a bunch of this mannerly language in comments despite my efforts, but I'm continuing to try and drive the prose towards something direct and simple to read. Some of the terminology improvements also needed to be made in the design doc and those have been made here. Note that I don't think this rendering is perfect or should be viewed as final. I'm happy to iterate on it further, and have a few adjustments in mind already, but would like to focus this on getting the _implementation_ of the current rendering design in place, and then we can make targeted changes or tweaks as needed. For example, I'm not yet fully happy with the rendering when messages are too long and we move them all the way to the left, but am leaving that for a follow-up. Assisted-by: Claude Code
613 lines
24 KiB
Plaintext
613 lines
24 KiB
Plaintext
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon
|
|
//
|
|
// AUTOUPDATE
|
|
// TIP: To test this file alone, run:
|
|
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/function/import/overloads.carbon
|
|
// TIP: To dump output, run:
|
|
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/function/import/overloads.carbon
|
|
|
|
// ============================================================================
|
|
// Overloaded sets tests
|
|
// ============================================================================
|
|
|
|
// --- multiple_functions_no_overloads.h
|
|
|
|
auto no_overloads_foo(short a) -> void;
|
|
auto no_overloads_bar(short a) -> void;
|
|
|
|
// --- import_multiple_functions_no_overloads.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "multiple_functions_no_overloads.h";
|
|
|
|
fn F() {
|
|
Cpp.no_overloads_bar(1 as i16);
|
|
}
|
|
|
|
// --- overloaded_functions.h
|
|
|
|
auto overloaded_foo(short a) -> void;
|
|
auto overloaded_foo(int a) -> void;
|
|
|
|
// --- import_overloaded_functions.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "overloaded_functions.h";
|
|
|
|
fn F() {
|
|
Cpp.overloaded_foo(1 as i32);
|
|
}
|
|
|
|
// --- both_overloaded_functions_called.h
|
|
|
|
auto both_called_foo(short a) -> void;
|
|
auto both_called_foo(int a) -> void;
|
|
|
|
// --- import_both_overloaded_functions_called.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "both_overloaded_functions_called.h";
|
|
|
|
fn F() {
|
|
Cpp.both_called_foo(1 as i32);
|
|
Cpp.both_called_foo(1 as i16);
|
|
}
|
|
|
|
// --- multiple_overloaded_sets.h
|
|
|
|
auto multi_set_foo(short a) -> void;
|
|
auto multi_set_foo(int a) -> void;
|
|
|
|
auto multi_set_bar(long a) -> void;
|
|
auto multi_set_bar(int a) -> void;
|
|
|
|
// --- import_multiple_overloaded_sets.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "multiple_overloaded_sets.h";
|
|
|
|
fn F() {
|
|
Cpp.multi_set_foo(1 as i32);
|
|
Cpp.multi_set_bar(1 as i32);
|
|
}
|
|
|
|
// ============================================================================
|
|
// Call args tests
|
|
// ============================================================================
|
|
|
|
// --- int_literal.h
|
|
|
|
auto int_literal_foo(int a) -> int;
|
|
auto int_literal_foo(unsigned int a) -> unsigned int;
|
|
|
|
auto int_literal_foo(long a) -> long;
|
|
auto int_literal_foo(unsigned long a) -> unsigned long;
|
|
|
|
auto int_literal_foo(long long a) -> long long;
|
|
auto int_literal_foo(unsigned long long a) -> unsigned long long;
|
|
|
|
auto int_literal_foo(__int128 a) -> __int128;
|
|
auto int_literal_foo(unsigned __int128 a) -> unsigned __int128;
|
|
|
|
// --- import_int_literal.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "int_literal.h";
|
|
|
|
fn F() {
|
|
// i32_max
|
|
let unused a: i32 = Cpp.int_literal_foo(2147483647);
|
|
|
|
// i32_max + 1
|
|
// It could fit to unsigned int, but only signed integers are considered, so assigned to long.
|
|
// Decimal, hexadecimal and binary integer literals are treated the same when assigning a C++ type.
|
|
let unused b: i64 = Cpp.int_literal_foo(2147483648);
|
|
let unused b_hexa: i64 = Cpp.int_literal_foo(0x8000_0000);
|
|
let unused b_binary: i64 = Cpp.int_literal_foo(0b1000_0000_0000_0000_0000_0000_0000_0000);
|
|
|
|
// i64_max
|
|
let unused c: i64 = Cpp.int_literal_foo(9223372036854775807);
|
|
|
|
// i64_max + 1
|
|
// Could fit to unsigned long, but only signed integers are considered, so fitted to _int128.
|
|
let unused d: i128 = Cpp.int_literal_foo(9223372036854775808);
|
|
|
|
// u64_max
|
|
let unused e: i128 = Cpp.int_literal_foo(18446744073709551615);
|
|
|
|
// u64_max + 1
|
|
let unused f: i128 = Cpp.int_literal_foo(18446744073709551616);
|
|
|
|
// i128_max
|
|
let unused g: i128 = Cpp.int_literal_foo(170141183460469231731687303715884105727);
|
|
}
|
|
|
|
// --- fail_import_large_int_literal.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "int_literal.h";
|
|
|
|
fn F() {
|
|
// TODO: get rid of the second error message here.
|
|
// i128_max + 1
|
|
// CHECK:STDERR: fail_import_large_int_literal.carbon:[[@LINE+4]]:44-82: error: integer value 170141183460469231731687303715884105728 too large to fit in a signed C++ integer type; requires 129 bits, but max is 128 [IntTooLargeForCppType]
|
|
// CHECK:STDERR:
|
|
// CHECK:STDERR: fail_import_large_int_literal.carbon:[[@LINE+2]]:44-82: error: call argument of type `Core.IntLiteral` is not supported [CppCallArgTypeNotSupported]
|
|
// CHECK:STDERR:
|
|
let unused h: i128 = Cpp.int_literal_foo(170141183460469231731687303715884105728);
|
|
}
|
|
|
|
// --- negative_int_literal.h
|
|
|
|
auto neg_literal_foo(long a) -> void;
|
|
auto neg_literal_foo(int a) -> void;
|
|
|
|
// --- import_negative_int_literal.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "negative_int_literal.h";
|
|
|
|
fn F() {
|
|
// selects `auto neg_literal_foo(int a) -> void;`
|
|
Cpp.neg_literal_foo(-1);
|
|
}
|
|
|
|
// --- negative_literal_passed_to_unsigned.h
|
|
|
|
auto neg_to_unsigned_foo(unsigned int a) -> void;
|
|
|
|
// --- fail_import_negative_literal_passed_to_unsigned.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "negative_literal_passed_to_unsigned.h";
|
|
|
|
fn F() {
|
|
// CHECK:STDERR: fail_import_negative_literal_passed_to_unsigned.carbon:[[@LINE+3]]:27-28: error: negative integer value -1 converted to unsigned type `u32` [NegativeIntInUnsignedType]
|
|
// CHECK:STDERR: ./negative_literal_passed_to_unsigned.h:2:39: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.neg_to_unsigned_foo(-1);
|
|
}
|
|
|
|
// --- floating_point_literal.h
|
|
|
|
auto float_literal_foo(float a) -> float;
|
|
auto float_literal_foo(double a) -> double;
|
|
|
|
// --- import_floating_point_literal.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "floating_point_literal.h";
|
|
|
|
fn F() {
|
|
let unused d: f64 = Cpp.float_literal_foo(1.0);
|
|
}
|
|
|
|
// --- fail_import_large_floating_point_literal.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "floating_point_literal.h";
|
|
|
|
fn F() {
|
|
// CHECK:STDERR: fail_import_large_floating_point_literal.carbon:[[@LINE+3]]:25-32: error: value 18*10^307 too large for floating-point type `f64` [FloatLiteralTooLargeForType]
|
|
// CHECK:STDERR: ./floating_point_literal.h:3:31: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.float_literal_foo(1.8e+308);
|
|
}
|
|
|
|
// --- struct_init.h
|
|
|
|
struct NoFields {};
|
|
|
|
auto PassNoFields(NoFields s) -> void;
|
|
|
|
struct ThreeFields {
|
|
int a, b, c;
|
|
};
|
|
|
|
auto PassThreeFields(ThreeFields t) -> void;
|
|
|
|
// --- struct_init.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "struct_init.h";
|
|
|
|
fn MakeEmpty() -> {};
|
|
|
|
fn Empty(value: {}, ref reference: {}) {
|
|
Cpp.PassNoFields({});
|
|
|
|
Cpp.PassNoFields(value);
|
|
|
|
Cpp.PassNoFields(reference);
|
|
|
|
Cpp.PassNoFields(MakeEmpty());
|
|
}
|
|
|
|
// --- fail_todo_struct_init_nonempty.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "struct_init.h";
|
|
|
|
fn MakeThreeFields() -> {.a: i32, .b: i32, .c: i32};
|
|
|
|
fn ThreeFields(value: {.a: i32, .b: i32, .c: i32}, ref reference: {.a: i32, .b: i32, .c: i32}) {
|
|
// CHECK:STDERR: fail_todo_struct_init_nonempty.carbon:[[@LINE+4]]:23-46: error: cannot implicitly convert expression of type `{.a: Core.IntLiteral, .b: Core.IntLiteral, .c: Core.IntLiteral}` to `Cpp.ThreeFields` [ConversionFailure]
|
|
// CHECK:STDERR: fail_todo_struct_init_nonempty.carbon:[[@LINE+3]]:23-46: note: type `{.a: Core.IntLiteral, .b: Core.IntLiteral, .c: Core.IntLiteral}` does not implement interface `Core.ImplicitAs(Cpp.ThreeFields)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./struct_init.h:10:34: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassThreeFields({.a = 1, .b = 2, .c = 3});
|
|
|
|
// CHECK:STDERR: fail_todo_struct_init_nonempty.carbon:[[@LINE+4]]:23-27: error: cannot implicitly convert expression of type `{.a: i32, .b: i32, .c: i32}` to `Cpp.ThreeFields` [ConversionFailure]
|
|
// CHECK:STDERR: fail_todo_struct_init_nonempty.carbon:[[@LINE+3]]:23-27: note: type `{.a: i32, .b: i32, .c: i32}` does not implement interface `Core.ImplicitAs(Cpp.ThreeFields)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./struct_init.h:10:34: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassThreeFields(value);
|
|
|
|
// CHECK:STDERR: fail_todo_struct_init_nonempty.carbon:[[@LINE+4]]:23-31: error: cannot implicitly convert expression of type `{.a: i32, .b: i32, .c: i32}` to `Cpp.ThreeFields` [ConversionFailure]
|
|
// CHECK:STDERR: fail_todo_struct_init_nonempty.carbon:[[@LINE+3]]:23-31: note: type `{.a: i32, .b: i32, .c: i32}` does not implement interface `Core.ImplicitAs(Cpp.ThreeFields)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./struct_init.h:10:34: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassThreeFields(reference);
|
|
|
|
// CHECK:STDERR: fail_todo_struct_init_nonempty.carbon:[[@LINE+4]]:23-39: error: cannot implicitly convert expression of type `{.a: i32, .b: i32, .c: i32}` to `Cpp.ThreeFields` [ConversionFailure]
|
|
// CHECK:STDERR: fail_todo_struct_init_nonempty.carbon:[[@LINE+3]]:23-39: note: type `{.a: i32, .b: i32, .c: i32}` does not implement interface `Core.ImplicitAs(Cpp.ThreeFields)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./struct_init.h:10:34: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassThreeFields(MakeThreeFields());
|
|
|
|
// CHECK:STDERR: fail_todo_struct_init_nonempty.carbon:[[@LINE+4]]:23-46: error: cannot implicitly convert expression of type `{.b: Core.IntLiteral, .c: Core.IntLiteral, .a: Core.IntLiteral}` to `Cpp.ThreeFields` [ConversionFailure]
|
|
// CHECK:STDERR: fail_todo_struct_init_nonempty.carbon:[[@LINE+3]]:23-46: note: type `{.b: Core.IntLiteral, .c: Core.IntLiteral, .a: Core.IntLiteral}` does not implement interface `Core.ImplicitAs(Cpp.ThreeFields)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./struct_init.h:10:34: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassThreeFields({.b = 1, .c = 2, .a = 3});
|
|
}
|
|
|
|
// --- fail_struct_init_field_mismatch.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "struct_init.h";
|
|
|
|
fn F() {
|
|
// CHECK:STDERR: fail_struct_init_field_mismatch.carbon:[[@LINE+4]]:3-21: error: no matching function for call to 'PassThreeFields' [CppInteropParseError]
|
|
// CHECK:STDERR: ./struct_init.h:10:6: note: candidate function not viable [CppInteropParseNote]
|
|
// CHECK:STDERR: ./struct_init.h:10:22-34: note: cannot convert initializer list argument to 'ThreeFields' [CppInteropParseNoteReason]
|
|
// CHECK:STDERR:
|
|
Cpp.PassThreeFields({.a = 1, .b = 2, .c = 3, .d = 4});
|
|
|
|
// CHECK:STDERR: fail_struct_init_field_mismatch.carbon:[[@LINE+4]]:3-21: error: no matching function for call to 'PassThreeFields' [CppInteropParseError]
|
|
// CHECK:STDERR: ./struct_init.h:10:6: note: candidate function not viable [CppInteropParseNote]
|
|
// CHECK:STDERR: ./struct_init.h:10:22-34: note: cannot convert initializer list argument to 'ThreeFields' [CppInteropParseNoteReason]
|
|
// CHECK:STDERR:
|
|
Cpp.PassThreeFields({.a = 1, .x = 2, .c = 3});
|
|
}
|
|
|
|
// --- fail_struct_init_unsupported_field_name.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "struct_init.h";
|
|
|
|
fn F() {
|
|
// CHECK:STDERR: fail_struct_init_unsupported_field_name.carbon:[[@LINE+2]]:23-33: error: field name `base` cannot be mapped into C++ [CppCallFieldNameNotSupported]
|
|
// CHECK:STDERR:
|
|
Cpp.PassThreeFields({.base = 1});
|
|
}
|
|
|
|
// --- fail_struct_init_from_tuple.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "struct_init.h";
|
|
|
|
// TODO: Struct init from an undesignated list is allowed in C++, but not in
|
|
// Carbon. Should we allow it when initializing a C++ class type?
|
|
|
|
fn MakeEmpty() -> ();
|
|
|
|
fn Empty(value: (), ref reference: ()) {
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+4]]:20-21: error: cannot implicitly convert expression of type `()` to `Cpp.NoFields` [ConversionFailure]
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+3]]:20-21: note: type `()` does not implement interface `Core.ImplicitAs(Cpp.NoFields)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./struct_init.h:4:28: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassNoFields(());
|
|
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+4]]:20-24: error: cannot implicitly convert expression of type `()` to `Cpp.NoFields` [ConversionFailure]
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+3]]:20-24: note: type `()` does not implement interface `Core.ImplicitAs(Cpp.NoFields)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./struct_init.h:4:28: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassNoFields(value);
|
|
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+4]]:20-28: error: cannot implicitly convert expression of type `()` to `Cpp.NoFields` [ConversionFailure]
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+3]]:20-28: note: type `()` does not implement interface `Core.ImplicitAs(Cpp.NoFields)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./struct_init.h:4:28: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassNoFields(reference);
|
|
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+4]]:20-30: error: cannot implicitly convert expression of type `()` to `Cpp.NoFields` [ConversionFailure]
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+3]]:20-30: note: type `()` does not implement interface `Core.ImplicitAs(Cpp.NoFields)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./struct_init.h:4:28: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassNoFields(MakeEmpty());
|
|
}
|
|
|
|
fn MakeThreeFields() -> (i32, i32, i32);
|
|
|
|
fn ThreeFields(value: (i32, i32, i32), ref reference: (i32, i32, i32)) {
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+4]]:23-31: error: cannot implicitly convert expression of type `(Core.IntLiteral, Core.IntLiteral, Core.IntLiteral)` to `Cpp.ThreeFields` [ConversionFailure]
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+3]]:23-31: note: type `(Core.IntLiteral, Core.IntLiteral, Core.IntLiteral)` does not implement interface `Core.ImplicitAs(Cpp.ThreeFields)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./struct_init.h:10:34: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassThreeFields((1, 2, 3));
|
|
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+4]]:23-27: error: cannot implicitly convert expression of type `(i32, i32, i32)` to `Cpp.ThreeFields` [ConversionFailure]
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+3]]:23-27: note: type `(i32, i32, i32)` does not implement interface `Core.ImplicitAs(Cpp.ThreeFields)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./struct_init.h:10:34: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassThreeFields(value);
|
|
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+4]]:23-31: error: cannot implicitly convert expression of type `(i32, i32, i32)` to `Cpp.ThreeFields` [ConversionFailure]
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+3]]:23-31: note: type `(i32, i32, i32)` does not implement interface `Core.ImplicitAs(Cpp.ThreeFields)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./struct_init.h:10:34: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassThreeFields(reference);
|
|
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+4]]:23-39: error: cannot implicitly convert expression of type `(i32, i32, i32)` to `Cpp.ThreeFields` [ConversionFailure]
|
|
// CHECK:STDERR: fail_struct_init_from_tuple.carbon:[[@LINE+3]]:23-39: note: type `(i32, i32, i32)` does not implement interface `Core.ImplicitAs(Cpp.ThreeFields)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./struct_init.h:10:34: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassThreeFields(MakeThreeFields());
|
|
}
|
|
|
|
// --- int_from_struct.h
|
|
|
|
auto PassInt(int n) -> void;
|
|
|
|
struct S {};
|
|
|
|
auto PassOverloaded(int n) -> void;
|
|
auto PassOverloaded(S n) -> void;
|
|
|
|
// --- fail_int_from_struct.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "int_from_struct.h";
|
|
|
|
fn F() {
|
|
// C++ permits `{}` to be used to initialize an int, but Carbon does not.
|
|
|
|
// CHECK:STDERR: fail_int_from_struct.carbon:[[@LINE+4]]:15-16: error: cannot implicitly convert expression of type `{}` to `i32` [ConversionFailure]
|
|
// CHECK:STDERR: fail_int_from_struct.carbon:[[@LINE+3]]:15-16: note: type `{}` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./int_from_struct.h:2:18: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassInt({});
|
|
|
|
// CHECK:STDERR: fail_int_from_struct.carbon:[[@LINE+4]]:15-16: error: cannot implicitly convert expression of type `()` to `i32` [ConversionFailure]
|
|
// CHECK:STDERR: fail_int_from_struct.carbon:[[@LINE+3]]:15-16: note: type `()` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./int_from_struct.h:2:18: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassInt(());
|
|
}
|
|
|
|
// --- fail_int_from_struct_overloaded.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "int_from_struct.h";
|
|
|
|
fn F() {
|
|
// C++ overload resolution prefers to convert `{}` to `int` rather than to an
|
|
// empty struct. So that's the overload we pick, even though we can't call it.
|
|
|
|
// CHECK:STDERR: fail_int_from_struct_overloaded.carbon:[[@LINE+4]]:22-23: error: cannot implicitly convert expression of type `{}` to `i32` [ConversionFailure]
|
|
// CHECK:STDERR: fail_int_from_struct_overloaded.carbon:[[@LINE+3]]:22-23: note: type `{}` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./int_from_struct.h:6:25: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassOverloaded({});
|
|
|
|
// CHECK:STDERR: fail_int_from_struct_overloaded.carbon:[[@LINE+4]]:22-23: error: cannot implicitly convert expression of type `()` to `i32` [ConversionFailure]
|
|
// CHECK:STDERR: fail_int_from_struct_overloaded.carbon:[[@LINE+3]]:22-23: note: type `()` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./int_from_struct.h:6:25: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.PassOverloaded(());
|
|
}
|
|
|
|
// --- nested_structs.h
|
|
|
|
struct A {
|
|
int x, y;
|
|
};
|
|
|
|
struct B {
|
|
A a;
|
|
int n;
|
|
};
|
|
|
|
void TakeB(B);
|
|
|
|
// --- fail_pass_nested_structs_inner_field_mismatch.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "nested_structs.h";
|
|
|
|
fn F() {
|
|
// CHECK:STDERR: fail_pass_nested_structs_inner_field_mismatch.carbon:[[@LINE+4]]:3-11: error: no matching function for call to 'TakeB' [CppInteropParseError]
|
|
// CHECK:STDERR: ./nested_structs.h:11:6: note: candidate function not viable [CppInteropParseNote]
|
|
// CHECK:STDERR: ./nested_structs.h:11:12: note: cannot convert initializer list argument to 'B' [CppInteropParseNoteReason]
|
|
// CHECK:STDERR:
|
|
Cpp.TakeB({.a = {.x = 1, .z = 2}, .n = 3});
|
|
}
|
|
|
|
// --- fail_todo_pass_nested_structs.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "nested_structs.h";
|
|
|
|
fn F() {
|
|
// CHECK:STDERR: fail_todo_pass_nested_structs.carbon:[[@LINE+4]]:13-43: error: cannot implicitly convert expression of type `{.a: {.x: Core.IntLiteral, .y: Core.IntLiteral}, .n: Core.IntLiteral}` to `Cpp.B` [ConversionFailure]
|
|
// CHECK:STDERR: fail_todo_pass_nested_structs.carbon:[[@LINE+3]]:13-43: note: type `{.a: {.x: Core.IntLiteral, .y: Core.IntLiteral}, .n: Core.IntLiteral}` does not implement interface `Core.ImplicitAs(Cpp.B)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./nested_structs.h:11:13: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.TakeB({.a = {.x = 1, .y = 2}, .n = 3});
|
|
}
|
|
|
|
// ============================================================================
|
|
// Overload rejected on Carbon side
|
|
// ============================================================================
|
|
|
|
// --- upsizing.h
|
|
|
|
auto upsizing_foo(int a) -> void;
|
|
|
|
// --- upsizing.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "upsizing.h";
|
|
|
|
fn F() {
|
|
Cpp.upsizing_foo(1 as i16);
|
|
}
|
|
|
|
// --- signedness_change.h
|
|
|
|
auto signedness_foo(unsigned int a) -> void;
|
|
|
|
// --- fail_signedness_change_rejected.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "signedness_change.h";
|
|
|
|
fn F() {
|
|
// CHECK:STDERR: fail_signedness_change_rejected.carbon:[[@LINE+4]]:22-29: error: cannot implicitly convert expression of type `i32` to `u32` [ConversionFailure]
|
|
// CHECK:STDERR: fail_signedness_change_rejected.carbon:[[@LINE+3]]:22-29: note: type `i32` does not implement interface `Core.ImplicitAs(u32)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./signedness_change.h:2:34: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.signedness_foo(1 as i32);
|
|
}
|
|
|
|
// --- downsizing_rejected.h
|
|
|
|
auto downsizing_foo(short a) -> void;
|
|
|
|
// --- fail_import_downsizing_rejected.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "downsizing_rejected.h";
|
|
|
|
fn F() {
|
|
// CHECK:STDERR: fail_import_downsizing_rejected.carbon:[[@LINE+4]]:22-29: error: cannot implicitly convert expression of type `i32` to `i16` [ConversionFailure]
|
|
// CHECK:STDERR: fail_import_downsizing_rejected.carbon:[[@LINE+3]]:22-29: note: type `i32` does not implement interface `Core.ImplicitAs(i16)` [MissingImplInMemberAccessInContext]
|
|
// CHECK:STDERR: ./downsizing_rejected.h:2:27: note: initializing function parameter [InCallToFunctionParam]
|
|
// CHECK:STDERR:
|
|
Cpp.downsizing_foo(1 as i32);
|
|
}
|
|
|
|
// ============================================================================
|
|
// No viable function found
|
|
// ============================================================================
|
|
|
|
// --- no_viable_function.h
|
|
|
|
auto no_viable_foo(short a, int b) -> void;
|
|
|
|
// --- fail_import_no_viable_function.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "no_viable_function.h";
|
|
|
|
fn F() {
|
|
// CHECK:STDERR: fail_import_no_viable_function.carbon:[[@LINE+4]]:3-19: error: no matching function for call to 'no_viable_foo' [CppInteropParseError]
|
|
// CHECK:STDERR: ./no_viable_function.h:2:6: note: candidate function not viable [CppInteropParseNote]
|
|
// CHECK:STDERR: ./no_viable_function.h:2:20-33: note: requires 2 arguments, but 1 was provided [CppInteropParseNoteReason]
|
|
// CHECK:STDERR:
|
|
Cpp.no_viable_foo(1 as i64);
|
|
}
|
|
|
|
// ============================================================================
|
|
// Ambiguous overload found
|
|
// ============================================================================
|
|
|
|
// --- ambiguous_overload.h
|
|
|
|
auto ambiguous_foo(short a) -> void;
|
|
auto ambiguous_foo(int a) -> void;
|
|
|
|
// --- fail_import_ambiguous_overload.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "ambiguous_overload.h";
|
|
|
|
fn F() {
|
|
// CHECK:STDERR: fail_import_ambiguous_overload.carbon:[[@LINE+4]]:3-19: error: call to 'ambiguous_foo' is ambiguous [CppInteropParseError]
|
|
// CHECK:STDERR: ./ambiguous_overload.h:2:6: note: candidate function [CppInteropParseNote]
|
|
// CHECK:STDERR: ./ambiguous_overload.h:3:6: note: candidate function [CppInteropParseNote]
|
|
// CHECK:STDERR:
|
|
Cpp.ambiguous_foo(1 as i64);
|
|
}
|
|
|
|
// ============================================================================
|
|
// Deleted function found
|
|
// ============================================================================
|
|
|
|
// --- deleted_function.h
|
|
|
|
auto deleted_foo(short a) -> void;
|
|
auto deleted_foo(int a) -> void = delete;
|
|
|
|
// --- fail_import_deleted_function.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp library "deleted_function.h";
|
|
|
|
fn F() {
|
|
// CHECK:STDERR: fail_import_deleted_function.carbon:[[@LINE+4]]:3-17: error: call to deleted function 'deleted_foo' [CppInteropParseError]
|
|
// CHECK:STDERR: ./deleted_function.h:3:6: note: candidate function has been explicitly deleted [CppInteropParseNote]
|
|
// CHECK:STDERR: ./deleted_function.h:2:6: note: candidate function [CppInteropParseNote]
|
|
// CHECK:STDERR:
|
|
Cpp.deleted_foo(1 as i32);
|
|
}
|
|
|
|
// --- fail_missing_impl.carbon
|
|
library "[[@TEST_NAME]]";
|
|
|
|
import Cpp inline '''
|
|
void missing_impl_foo();
|
|
void missing_impl_foo(int);
|
|
''';
|
|
|
|
interface I {}
|
|
|
|
fn EchoValue[ValueT: I](unused generic value: ValueT) {}
|
|
|
|
fn F() {
|
|
// CHECK:STDERR: fail_missing_impl.carbon:[[@LINE+3]]:3-33: error: cannot convert type `<type of Cpp.missing_impl_foo>` into type implementing `I` [ConversionFailureTypeToFacet]
|
|
// CHECK:STDERR: fail_missing_impl.carbon:[[@LINE-4]]:1-55: note: while deducing parameters of generic declared here [DeductionGenericHere]
|
|
// CHECK:STDERR:
|
|
EchoValue(Cpp.missing_impl_foo);
|
|
}
|