Mark implicit class template specialization record decl `Item`s as top level

Intro:
* For implicit template specialization decls, we generate top level `Item`s (even when the decl is in a namespace)
* We use the `enclosing_namespace_id` field to fully qualify types in our bindings, eg in the generated binding `pub fn processT(test_namespace_bindings::T t)`, we obtained the `test_namespace_bindings` qualifier through the `enclosing_namespace_id` field.

Problem:

Currently crubit will take an implicit template specialization decl that belongs to a namespace and will generate a (top level) `Item` that has the field `enclosing_namespace_id` set to the parent namespace's `id`. Later on when the type is spelled out (eg, when generating code for a type alias) crubit uses the provided `enclosing_namespace_id` to construct the fully qualified identifier. This is wrong, because, as mentioned above, the generated `Item` is top level.

Eg:
```
namespace ns {
  template<typename T> struct MyStruct{T t;};
  using Alias1 = MyStruct<int>;
}
```
gets converted to
```
pub mod ns {
  // DOESN'T WORK: extra ns identifier; __CcTemplateInstN2ns8MyStructIiEE is top level
  pub type Alias1 = crate::ns::__CcTemplateInstN2ns8MyStructIiEE;
}
struct __CcTemplateInstN2ns8MyStructIiEE {
  pub t: i32,
}
```

The fix in this cl is simple: we know that implicit class template specialization `Item`s are top level, and as such we set their `enclosing_namespace_id` to `None`.

after this cl the generated bindings are:
```
pub mod ns {
  // WORKS!!!
  pub type Alias1 = crate::__CcTemplateInstN2ns8MyStructIiEE;
}
struct __CcTemplateInstN2ns8MyStructIiEE {
  pub t: i32,
}
```

PiperOrigin-RevId: 456577112
6 files changed
tree: ff05f8ffb8ddc27c7c93e72f4bce1b810d568cff
  1. .bazelci/
  2. bazel/
  3. cc_template/
  4. common/
  5. docs/
  6. lifetime_analysis/
  7. lifetime_annotations/
  8. migrator/
  9. nullability_verification/
  10. rs_bindings_from_cc/
  11. .bazelrc
  12. .gitignore
  13. BUILD
  14. Cargo.Bazel.lock
  15. CODE_OF_CONDUCT
  16. CONTRIBUTING
  17. LICENSE
  18. README.md
  19. WORKSPACE
README.md

Crubit: C++/Rust Bidirectional Interop Tool

Build status

Extremely experimental interop tooling for C++ and Rust.

Please don‘t use, this is an experiment and we don’t yet know where will it take us. There will be breaking changes without warning. Unfortunately, we can't take contributions at this point.

Building Crubit

$ apt install clang lld bazel
$ git clone git@github.com:google/crubit.git
$ cd crubit
$ bazel build --linkopt=-fuse-ld=/usr/bin/ld.lld //rs_bindings_from_cc:rs_bindings_from_cc_impl

Using a prebuilt LLVM tree

$ git clone https://github.com/llvm/llvm-project
$ cd llvm-project
$ CC=clang CXX=clang++ cmake -S llvm -B build -DLLVM_ENABLE_PROJECTS='clang' -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=install
$ cmake --build build -j
$ # wait...
$ cmake --install build
$ cd ../crubit
$ LLVM_INSTALL_PATH=../llvm-project/install bazel build //rs_bindings_from_cc:rs_bindings_from_cc_impl