Skip to content

Commit

Permalink
Look for must_use on typdefs in function return
Browse files Browse the repository at this point in the history
  • Loading branch information
ian-h-chamberlain authored and Aatif Syed committed Sep 22, 2022
1 parent 8a6eae9 commit 9191306
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 5 deletions.
32 changes: 28 additions & 4 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3965,11 +3965,35 @@ impl CodeGenerator for Function {

let mut attributes = vec![];

if signature.must_use() &&
ctx.options().rust_features().must_use_function
{
attributes.push(attributes::must_use());
if ctx.options().rust_features().must_use_function {
let must_use = signature.must_use() || {
let ret_ty = signature.return_type();

let resolved_ret = ret_ty
.into_resolver()
.through_type_refs()
.through_type_aliases()
.resolve(ctx);

let must_use_resolved_ty =
resolved_ret.annotations().must_use_type() ||
ctx.must_use_type_by_name(resolved_ret);

let ret = ctx.resolve_item(ret_ty);
let must_use_ty = ret.annotations().must_use_type() ||
ctx.must_use_type_by_name(ret);

// If the return type already has #[must_use], the function does not
// need the annotation. This preserves the codegen behavior before
// type aliases with #[must_use] were supported.
!must_use_resolved_ty && must_use_ty
};

if must_use {
attributes.push(attributes::must_use());
}
}

if let Some(comment) = item.comment(ctx) {
attributes.push(attributes::doc(comment));
}
Expand Down
3 changes: 2 additions & 1 deletion src/ir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1921,7 +1921,8 @@ If you encounter an error missing from this list, please file an issue or a PR!"
let item = Item::new(
with_id,
None,
None,
self.resolve_item_fallible(wrapped_id)
.map(|item| item.annotations().clone()),
parent_id.unwrap_or_else(|| self.current_module.into()),
ItemKind::Type(ty),
Some(location),
Expand Down
76 changes: 76 additions & 0 deletions tests/expectations/tests/func_return_must_use.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#![allow(
dead_code,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]

pub type MustUseInt = ::std::os::raw::c_int;
extern "C" {
#[must_use]
pub fn return_int() -> MustUseInt;
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
#[must_use]
pub struct MustUseStruct {
_unused: [u8; 0],
}
extern "C" {
pub fn return_struct() -> MustUseStruct;
}
/// <div rustbindgen mustusetype></div>
pub type AnnotatedInt = ::std::os::raw::c_int;
extern "C" {
#[must_use]
pub fn return_annotated_int() -> AnnotatedInt;
}
extern "C" {
pub fn return_plain_int() -> ::std::os::raw::c_int;
}
/// <div rustbindgen mustusetype></div>
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
#[must_use]
pub struct AnnotatedStruct {}
#[test]
fn bindgen_test_layout_AnnotatedStruct() {
assert_eq!(
::std::mem::size_of::<AnnotatedStruct>(),
0usize,
concat!("Size of: ", stringify!(AnnotatedStruct))
);
assert_eq!(
::std::mem::align_of::<AnnotatedStruct>(),
1usize,
concat!("Alignment of ", stringify!(AnnotatedStruct))
);
}
extern "C" {
pub fn return_annotated_struct() -> AnnotatedStruct;
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct PlainStruct {}
#[test]
fn bindgen_test_layout_PlainStruct() {
assert_eq!(
::std::mem::size_of::<PlainStruct>(),
0usize,
concat!("Size of: ", stringify!(PlainStruct))
);
assert_eq!(
::std::mem::align_of::<PlainStruct>(),
1usize,
concat!("Alignment of ", stringify!(PlainStruct))
);
}
/// <div rustbindgen mustusetype></div>
pub type TypedefPlainStruct = PlainStruct;
extern "C" {
pub fn return_plain_struct() -> PlainStruct;
}
extern "C" {
#[must_use]
pub fn return_typedef_struct() -> TypedefPlainStruct;
}
36 changes: 36 additions & 0 deletions tests/headers/func_return_must_use.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// bindgen-flags: --must-use-type 'MustUse.*'

typedef int MustUseInt;

MustUseInt return_int();

struct MustUseStruct;

struct MustUseStruct return_struct();

/**
* <div rustbindgen mustusetype></div>
*/
typedef int AnnotatedInt;

AnnotatedInt return_annotated_int();

int return_plain_int();

/**
* <div rustbindgen mustusetype></div>
*/
struct AnnotatedStruct {};

struct AnnotatedStruct return_annotated_struct();

struct PlainStruct {};

/**
* <div rustbindgen mustusetype></div>
*/
typedef struct PlainStruct TypedefPlainStruct;

struct PlainStruct return_plain_struct();

TypedefPlainStruct return_typedef_struct();

0 comments on commit 9191306

Please sign in to comment.