Clarify the infinitely recursive types through interop test (#8046)

This test generates an infinite recursion between Carbon and C++ making
a new type at each step through the recursion, producing an infinite
number of types. We improve the test in a few ways:
- Remove direct dependencies on min_prelude parts, we should just depend
on a single min_prelude, and not `import Core` explicitly.
- Remove a dependency on `i32` so we rely on less prelude.
- Remove the use of pointers, which currently introduce a dependency on
`Optional`, so we rely on less prelude. Instead use a generic `Wrap(T)`
type that we nest repeatedly to generate types.
- Add some comments and expand function names to help explain the
behaviour being tested

Now the test just depends on the convert.carbon prelude, which makes it
much simpler when running under a debugger.
This commit is contained in:
Dana Jansens authored and GitHub committed 2026-10-27 20:58:00 +00:00
1 parent 33863ed07c
commit a450026679
1 file changed
+24 -13
@@ -3,8 +3,6 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/parts/int.carbon
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/parts/optional.carbon
//
// AUTOUPDATE
// TIP: To test this file alone, run:
@@ -12,26 +10,39 @@
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/template/fail_todo_bidirectional_intorp_too_deep.carbon
import Core library "prelude/parts/optional";
import Core library "prelude/parts/int";
import Cpp;
fn ManualMultiply[template T: type](p: T*) -> T*;
class Wrap(T: Core.Copy) {
var unwrap: T;
impl as Core.Copy { fn Op(self) -> Self { return {.unwrap = self.unwrap}; } }
}
// TODO: C++ should be able to construct Wrap directly without this function.
fn MakeWrap[T: Core.Copy](t: T) -> Wrap(T) { return {.unwrap = t} as Wrap(T); }
fn CarbonSide[template T: type](p: T) -> T;
inline Cpp '''c++
template<typename T>
auto ManualMultiply(T x) -> T {
return *Carbon::ManualMultiply(&x);
// CHECK:STDERR: fail_todo_bidirectional_intorp_too_deep.carbon:[[@LINE+2]]:6: error: semantics TODO: `maximum depth for bidirectional Carbon/C++ interop is 10` [SemanticsTodo]
// CHECK:STDERR:
auto AddTypeWrapper(T x) -> T {
// Calls into to Carbon, adding a layer of Wrap(...) to the type T that
// came from Carbon. This recursively generates an infinite number of
// CarbonSide() specifics.
return Carbon::CarbonSide(Carbon::MakeWrap(x)).unwrap;
}
''';
fn ManualMultiply[template T: type](p: T*) -> T* {
// CHECK:STDERR: fail_todo_bidirectional_intorp_too_deep.carbon:[[@LINE+2]]:32: error: semantics TODO: `maximum depth for bidirectional Carbon/C++ interop is 10` [SemanticsTodo]
// CHECK:STDERR:
return Cpp.ManualMultiply(p);
fn CarbonSide[template T: type](p: T) -> T {
return Cpp.AddTypeWrapper(p);
}
class C {
adapt {};
impl as Core.Copy { fn Op(unused self) -> Self { return {} as C; } }
}
fn Test() {
var v: i32 = 5;
ManualMultiply(&v);
var v: C = {} as C;
CarbonSide(v);
}