use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
-use rustc_middle::ty::layout::{IntegerExt, SizeSkeleton};
+use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeFoldable};
use rustc_span::source_map;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol, DUMMY_SP};
use rustc_target::abi::Abi;
-use rustc_target::abi::{Integer, LayoutOf, TagEncoding, Variants};
+use rustc_target::abi::{Integer, TagEncoding, Variants};
use rustc_target::spec::abi::Abi as SpecAbi;
use if_chain::if_chain;
use FfiResult::*;
if def.repr.transparent() {
- // Can assume that only one field is not a ZST, so only check
+ // Can assume that at most one field is not a ZST, so only check
// that field's type for FFI-safety.
if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) {
self.check_field_type_for_ffi(cache, field, substs)
} else {
- bug!("malformed transparent type");
+ // All fields are ZSTs; this means that the type should behave
+ // like (), which is FFI-unsafe
+ FfiUnsafe {
+ ty,
+ reason: "this struct contains only zero-sized fields".into(),
+ help: None,
+ }
}
} else {
// We can't completely trust repr(C) markings; make sure the fields are
FfiSafe
}
+ ty::RawPtr(ty::TypeAndMut { ty, .. })
+ if match ty.kind() {
+ ty::Tuple(tuple) => tuple.is_empty(),
+ _ => false,
+ } =>
+ {
+ FfiSafe
+ }
+
ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => {
self.check_type_for_ffi(cache, ty)
}
};
let (variants, tag) = match layout.variants {
Variants::Multiple {
- tag_encoding: TagEncoding::Direct,
- ref tag,
- ref variants,
- ..
+ tag_encoding: TagEncoding::Direct, tag, ref variants, ..
} => (variants, tag),
_ => return,
};
if let ExprKind::Call(ref func, ref args) = expr.kind;
if let ExprKind::Path(ref func_qpath) = func.kind;
if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
- if cx.tcx.is_diagnostic_item(sym::fence, def_id) ||
- cx.tcx.is_diagnostic_item(sym::compiler_fence, def_id);
+ if matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence));
if let ExprKind::Path(ref ordering_qpath) = &args[0].kind;
if let Some(ordering_def_id) = cx.qpath_res(ordering_qpath, args[0].hir_id).opt_def_id();
if Self::matches_ordering(cx, ordering_def_id, &[sym::Relaxed]);