Support deprecated attribute for type aliases
This CL adds functionality that, given a Rust type alias defined as:
```
#[deprecated = "Use `OtherTypeAlias` instead"]
pub type TypeAlias = i32;
```
...generates the following C++ type alias:
```
using TypeAlias [[deprecated("Use `OtherTypeAlias` instead")]] = std::int32_t;
```
PiperOrigin-RevId: 660553142
Change-Id: I0af595a1bcb1acb06f6314eb6592bd4de3951844
diff --git a/bazel/llvm.bzl b/bazel/llvm.bzl
index 543a5c9..fd4ba9c 100644
--- a/bazel/llvm.bzl
+++ b/bazel/llvm.bzl
@@ -53,7 +53,7 @@
executable = False,
)
-LLVM_COMMIT_SHA = "2f28378317827afed81db1c2ce33c187ee6582a0"
+LLVM_COMMIT_SHA = "41491c77231e9d389ef18593be1fab4f4e810e88"
def llvm_loader_repository_dependencies():
# This *declares* the dependency, but it won't actually be *downloaded* unless it's used.
diff --git a/cc_bindings_from_rs/bindings.rs b/cc_bindings_from_rs/bindings.rs
index 658e9d4..3b24687 100644
--- a/cc_bindings_from_rs/bindings.rs
+++ b/cc_bindings_from_rs/bindings.rs
@@ -1219,12 +1219,8 @@
}
}
-/// Checks if the item associated with the given def_id has a deprecated
-/// attribute. If so, returns the corresponding C++ deprecated tag.
-///
-/// TODO(codyheiner): consider adding a more general version of this function
-/// that builds a Vec<TokenStream> containing all the attributes of a given
-/// item.
+/// Returns the C++ deprecated tag for the item identified by `def_id`, if it is
+/// deprecated. Otherwise, returns None.
fn format_deprecated_tag(tcx: TyCtxt, def_id: DefId) -> Option<TokenStream> {
if let Some(deprecated_attr) = tcx.get_attr(def_id, rustc_span::symbol::sym::deprecated) {
if let Some((deprecation, _span)) =
@@ -1321,7 +1317,7 @@
// This points directly to a type definition, not an alias or compound data
// type, so we can drop the hir type.
let use_type = SugaredTy::new(tcx.type_of(def_id).instantiate_identity(), None);
- create_type_alias(db, using_name, use_type)
+ create_type_alias(db, def_id, using_name, use_type)
}
_ => bail!(
"Unsupported use statement that refers to this type of the entity: {:#?}",
@@ -1341,11 +1337,12 @@
panic!("called format_type_alias on a non-type-alias");
};
let alias_type = SugaredTy::new(tcx.type_of(def_id).instantiate_identity(), Some(*hir_ty));
- create_type_alias(db, tcx.item_name(def_id).as_str(), alias_type)
+ create_type_alias(db, def_id, tcx.item_name(def_id).as_str(), alias_type)
}
fn create_type_alias<'tcx>(
db: &dyn BindingsGenerator<'tcx>,
+ def_id: DefId,
alias_name: &str,
alias_type: SugaredTy<'tcx>,
) -> Result<ApiSnippets> {
@@ -1354,7 +1351,13 @@
let actual_type_name = cc_bindings.into_tokens(&mut main_api_prereqs);
let alias_name = format_cc_ident(alias_name).context("Error formatting type alias name")?;
- let tokens = quote! {using #alias_name = #actual_type_name;};
+
+ let mut attributes = vec![];
+ if let Some(cc_deprecated_tag) = format_deprecated_tag(db.tcx(), def_id) {
+ attributes.push(cc_deprecated_tag);
+ }
+
+ let tokens = quote! {using #alias_name #(#attributes)* = #actual_type_name;};
Ok(ApiSnippets {
main_api: CcSnippet { prereqs: main_api_prereqs, tokens },
@@ -7302,6 +7305,25 @@
}
#[test]
+ fn test_format_item_type_alias_deprecated() {
+ let test_src = r#"
+ #[deprecated = "Use `OtherTypeAlias` instead"]
+ pub type TypeAlias = i32;
+ "#;
+ test_format_item(test_src, "TypeAlias", |result| {
+ let result = result.unwrap().unwrap();
+ let main_api = &result.main_api;
+ assert!(!main_api.prereqs.is_empty());
+ assert_cc_matches!(
+ main_api.tokens,
+ quote! {
+ using TypeAlias [[deprecated("Use `OtherTypeAlias` instead")]] = std::int32_t;
+ }
+ );
+ });
+ }
+
+ #[test]
fn test_format_item_unsupported_impl_item_const_value() {
let test_src = r#"
#![allow(dead_code)]
diff --git a/cc_bindings_from_rs/test/type_aliases/type_aliases.rs b/cc_bindings_from_rs/test/type_aliases/type_aliases.rs
index 50db93e..6e27c77 100644
--- a/cc_bindings_from_rs/test/type_aliases/type_aliases.rs
+++ b/cc_bindings_from_rs/test/type_aliases/type_aliases.rs
@@ -10,3 +10,8 @@
0
}
}
+
+pub mod test_deprecated_type_alias {
+ #[deprecated = "Use `OtherTypeAlias` instead"]
+ pub type TypeAlias = i32;
+}
diff --git a/cc_bindings_from_rs/test/type_aliases/type_aliases_test.cc b/cc_bindings_from_rs/test/type_aliases/type_aliases_test.cc
index 9051ce4..24357b4 100644
--- a/cc_bindings_from_rs/test/type_aliases/type_aliases_test.cc
+++ b/cc_bindings_from_rs/test/type_aliases/type_aliases_test.cc
@@ -2,8 +2,8 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include <cstdint>
#include <type_traits>
-#include <utility>
#include "gtest/gtest.h"
#include "cc_bindings_from_rs/test/type_aliases/type_aliases_cc_api.h"
@@ -27,5 +27,13 @@
decltype(type_aliases::test_type_aliases::func_using_alias())>));
}
+// Note: this test verifies that the generated code compiles and gives the
+// correct type, but doesn't check that the C++ type is actually deprecated.
+TEST(TypeAliasesTest, DeprecatedTypeAlias) {
+ EXPECT_TRUE(
+ (std::is_same_v<std::int32_t,
+ type_aliases::test_deprecated_type_alias::TypeAlias>));
+}
+
} // namespace
-} // namespace crubit
\ No newline at end of file
+} // namespace crubit