None = 0b0000_0000__0000_0000__0000,
// Things that are interior to the value (first nibble):
- InteriorUnsized = 0b0000_0000__0000_0000__0001,
InteriorUnsafe = 0b0000_0000__0000_0000__0010,
InteriorParam = 0b0000_0000__0000_0000__0100,
// InteriorAll = 0b00000000__00000000__1111,
OwnsDtor = 0b0000_0000__0000_0010__0000,
OwnsAll = 0b0000_0000__1111_1111__0000,
- // Things that are reachable by the value in any way (fourth nibble):
- ReachesBorrowed = 0b0000_0010__0000_0000__0000,
- ReachesMutable = 0b0000_1000__0000_0000__0000,
- ReachesFfiUnsafe = 0b0010_0000__0000_0000__0000,
- ReachesAll = 0b0011_1111__0000_0000__0000,
-
// Things that mean drop glue is necessary
NeedsDrop = 0b0000_0000__0000_0111__0000,
- // Things that prevent values from being considered sized
- Nonsized = 0b0000_0000__0000_0000__0001,
-
// All bits
All = 0b1111_1111__1111_1111__1111
}
self.intersects(TC::OwnsOwned)
}
- pub fn is_sized(&self, _: &ctxt) -> bool {
- !self.intersects(TC::Nonsized)
- }
-
pub fn interior_param(&self) -> bool {
self.intersects(TC::InteriorParam)
}
self.intersects(TC::InteriorUnsafe)
}
- pub fn interior_unsized(&self) -> bool {
- self.intersects(TC::InteriorUnsized)
- }
-
pub fn needs_drop(&self, _: &ctxt) -> bool {
self.intersects(TC::NeedsDrop)
}
/// Includes only those bits that still apply when indirected through a `Box` pointer
pub fn owned_pointer(&self) -> TypeContents {
- TC::OwnsOwned | (
- *self & (TC::OwnsAll | TC::ReachesAll))
- }
-
- /// Includes only those bits that still apply when indirected through a reference (`&`)
- pub fn reference(&self, bits: TypeContents) -> TypeContents {
- bits | (
- *self & TC::ReachesAll)
- }
-
- /// Includes only those bits that still apply when indirected through a raw pointer (`*`)
- pub fn unsafe_pointer(&self) -> TypeContents {
- *self & TC::ReachesAll
+ TC::OwnsOwned | (*self & TC::OwnsAll)
}
pub fn union<T, F>(v: &[T], mut f: F) -> TypeContents where
let result = match ty.sty {
// usize and isize are ffi-unsafe
TyUint(ast::TyUs) | TyInt(ast::TyIs) => {
- TC::ReachesFfiUnsafe
+ TC::None
}
// Scalar and unique types are sendable, and durable
}
TyBox(typ) => {
- TC::ReachesFfiUnsafe | tc_ty(cx, typ, cache).owned_pointer()
+ tc_ty(cx, typ, cache).owned_pointer()
}
- TyTrait(box TraitTy { ref bounds, .. }) => {
- object_contents(bounds) | TC::ReachesFfiUnsafe | TC::Nonsized
+ TyTrait(_) => {
+ TC::All - TC::InteriorParam
}
- TyRawPtr(ref mt) => {
- tc_ty(cx, mt.ty, cache).unsafe_pointer()
+ TyRawPtr(_) => {
+ TC::None
}
- TyRef(r, ref mt) => {
- tc_ty(cx, mt.ty, cache).reference(borrowed_contents(*r, mt.mutbl)) |
- TC::ReachesFfiUnsafe
+ TyRef(_, _) => {
+ TC::None
}
TyArray(ty, _) => {
}
TySlice(ty) => {
- tc_ty(cx, ty, cache) | TC::Nonsized
+ tc_ty(cx, ty, cache)
}
- TyStr => TC::Nonsized,
+ TyStr => TC::None,
TyStruct(did, substs) => {
let flds = cx.struct_fields(did, substs);
let mut res =
TypeContents::union(&flds[..],
- |f| tc_mt(cx, f.mt, cache));
-
- if !cx.lookup_repr_hints(did).contains(&attr::ReprExtern) {
- res = res | TC::ReachesFfiUnsafe;
- }
+ |f| tc_ty(cx, f.mt.ty, cache));
if cx.has_dtor(did) {
res = res | TC::OwnsDtor;
}
TyClosure(did, substs) => {
- // FIXME(#14449): `borrowed_contents` below assumes `&mut` closure.
let param_env = cx.empty_parameter_environment();
let infcx = infer::new_infer_ctxt(cx, &cx.tables, Some(param_env), false);
let upvars = infcx.closure_upvars(did, substs).unwrap();
res = res | TC::OwnsDtor;
}
- if !variants.is_empty() {
- let repr_hints = cx.lookup_repr_hints(did);
- if repr_hints.len() > 1 {
- // this is an error later on, but this type isn't safe
- res = res | TC::ReachesFfiUnsafe;
- }
-
- match repr_hints.get(0) {
- Some(h) => if !h.is_ffi_safe() {
- res = res | TC::ReachesFfiUnsafe;
- },
- // ReprAny
- None => {
- res = res | TC::ReachesFfiUnsafe;
-
- // We allow ReprAny enums if they are eligible for
- // the nullable pointer optimization and the
- // contained type is an `extern fn`
-
- if variants.len() == 2 {
- let mut data_idx = 0;
-
- if variants[0].args.is_empty() {
- data_idx = 1;
- }
-
- if variants[data_idx].args.len() == 1 {
- match variants[data_idx].args[0].sty {
- TyBareFn(..) => { res = res - TC::ReachesFfiUnsafe; }
- _ => { }
- }
- }
- }
- }
- }
- }
-
-
apply_lang_items(cx, did, res)
}
result
}
- fn tc_mt<'tcx>(cx: &ctxt<'tcx>,
- mt: TypeAndMut<'tcx>,
- cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents
- {
- let mc = TC::ReachesMutable.when(mt.mutbl == MutMutable);
- mc | tc_ty(cx, mt.ty, cache)
- }
-
fn apply_lang_items(cx: &ctxt, did: ast::DefId, tc: TypeContents)
-> TypeContents {
if Some(did) == cx.lang_items.unsafe_cell_type() {
tc
}
}
-
- /// Type contents due to containing a reference with
- /// the region `region` and borrow kind `bk`.
- fn borrowed_contents(region: ty::Region,
- mutbl: ast::Mutability)
- -> TypeContents {
- let b = match mutbl {
- ast::MutMutable => TC::ReachesMutable,
- ast::MutImmutable => TC::None,
- };
- b | (TC::ReachesBorrowed).when(region != ty::ReStatic)
- }
-
- fn object_contents(bounds: &ExistentialBounds) -> TypeContents {
- // These are the type contents of the (opaque) interior. We
- // make no assumptions (other than that it cannot have an
- // in-scope type parameter within, which makes no sense).
- let mut tc = TC::All - TC::InteriorParam;
- for bound in &bounds.builtin_bounds {
- tc = tc - match bound {
- BoundSync | BoundSend | BoundCopy => TC::None,
- BoundSized => TC::Nonsized,
- };
- }
- return tc;
- }
}
fn impls_bound<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
result
}
- pub fn is_ffi_safe(&'tcx self, cx: &ctxt<'tcx>) -> bool {
- !self.type_contents(cx).intersects(TC::ReachesFfiUnsafe)
- }
-
// True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
pub fn is_instantiable(&'tcx self, cx: &ctxt<'tcx>) -> bool {
fn type_requires<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>,
#![allow(deprecated)]
use metadata::{csearch, decoder};
+use middle::{cfg, def, infer, pat_util, stability, traits};
use middle::def::*;
-use middle::infer;
use middle::subst::Substs;
use middle::ty::{self, Ty};
-use middle::traits;
-use middle::{def, pat_util, stability};
use middle::const_eval::{eval_const_expr_partial, ConstVal};
use middle::const_eval::EvalHint::ExprTypeChecked;
-use middle::cfg;
use rustc::ast_map;
-use util::nodemap::{FnvHashMap, NodeSet};
+use util::nodemap::{FnvHashMap, FnvHashSet, NodeSet};
use lint::{Level, Context, LintPass, LintArray, Lint};
use std::collections::{HashSet, BitSet};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::{cmp, slice};
use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
+use std::rc::Rc;
use syntax::{abi, ast};
use syntax::ast_util::{self, is_shift_binop, local_def};
cx: &'a Context<'a, 'tcx>
}
+enum FfiResult {
+ FfiSafe,
+ FfiUnsafe(&'static str),
+ FfiBadStruct(ast::DefId, &'static str),
+ FfiBadEnum(ast::DefId, &'static str)
+}
+
+/// Check if this enum can be safely exported based on the
+/// "nullable pointer optimization". Currently restricted
+/// to function pointers and references, but could be
+/// expanded to cover NonZero raw pointers and newtypes.
+/// FIXME: This duplicates code in trans.
+fn is_repr_nullable_ptr<'tcx>(variants: &Vec<Rc<ty::VariantInfo<'tcx>>>) -> bool {
+ if variants.len() == 2 {
+ let mut data_idx = 0;
+
+ if variants[0].args.is_empty() {
+ data_idx = 1;
+ } else if !variants[1].args.is_empty() {
+ return false;
+ }
+
+ if variants[data_idx].args.len() == 1 {
+ match variants[data_idx].args[0].sty {
+ ty::TyBareFn(None, _) => { return true; }
+ ty::TyRef(..) => { return true; }
+ _ => { }
+ }
+ }
+ }
+ false
+}
+
impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
- fn check_def(&mut self, sp: Span, id: ast::NodeId) {
- match self.cx.tcx.def_map.borrow().get(&id).unwrap().full_def() {
- def::DefPrimTy(ast::TyInt(ast::TyIs)) => {
- self.cx.span_lint(IMPROPER_CTYPES, sp,
- "found rust type `isize` in foreign module, while \
- libc::c_int or libc::c_long should be used");
+ /// Check if the given type is "ffi-safe" (has a stable, well-defined
+ /// representation which can be exported to C code).
+ fn check_type_for_ffi(&self,
+ cache: &mut FnvHashSet<Ty<'tcx>>,
+ ty: Ty<'tcx>)
+ -> FfiResult {
+ use self::FfiResult::*;
+ let cx = &self.cx.tcx;
+
+ // Protect against infinite recursion, for example
+ // `struct S(*mut S);`.
+ // FIXME: A recursion limit is necessary as well, for irregular
+ // recusive types.
+ if !cache.insert(ty) {
+ return FfiSafe;
+ }
+
+ match ty.sty {
+ ty::TyStruct(did, substs) => {
+ if !cx.lookup_repr_hints(did).contains(&attr::ReprExtern) {
+ return FfiUnsafe(
+ "found struct without foreign-function-safe \
+ representation annotation in foreign module, \
+ consider adding a #[repr(C)] attribute to \
+ the type");
+ }
+
+ // We can't completely trust repr(C) markings; make sure the
+ // fields are actually safe.
+ let fields = cx.struct_fields(did, substs);
+
+ if fields.is_empty() {
+ return FfiUnsafe(
+ "found zero-size struct in foreign module, consider \
+ adding a member to this struct");
+ }
+
+ for field in fields {
+ let field_ty = infer::normalize_associated_type(cx, &field.mt.ty);
+ let r = self.check_type_for_ffi(cache, field_ty);
+ match r {
+ FfiSafe => {}
+ FfiBadStruct(..) | FfiBadEnum(..) => { return r; }
+ FfiUnsafe(s) => { return FfiBadStruct(did, s); }
+ }
+ }
+ FfiSafe
}
- def::DefPrimTy(ast::TyUint(ast::TyUs)) => {
- self.cx.span_lint(IMPROPER_CTYPES, sp,
- "found rust type `usize` in foreign module, while \
- libc::c_uint or libc::c_ulong should be used");
+ ty::TyEnum(did, substs) => {
+ let variants = cx.substd_enum_variants(did, substs);
+ if variants.is_empty() {
+ // Empty enums are okay... although sort of useless.
+ return FfiSafe
+ }
+
+ // Check for a repr() attribute to specify the size of the
+ // discriminant.
+ let repr_hints = cx.lookup_repr_hints(did);
+ match &**repr_hints {
+ [] => {
+ // Special-case types like `Option<extern fn()>`.
+ if !is_repr_nullable_ptr(&variants) {
+ return FfiUnsafe(
+ "found enum without foreign-function-safe \
+ representation annotation in foreign module, \
+ consider adding a #[repr(...)] attribute to \
+ the type")
+ }
+ }
+ [ref hint] => {
+ if !hint.is_ffi_safe() {
+ // FIXME: This shouldn't be reachable: we should check
+ // this earlier.
+ return FfiUnsafe(
+ "enum has unexpected #[repr(...)] attribute")
+ }
+
+ // Enum with an explicitly sized discriminant; either
+ // a C-style enum or a discriminated union.
+
+ // The layout of enum variants is implicitly repr(C).
+ // FIXME: Is that correct?
+ }
+ _ => {
+ // FIXME: This shouldn't be reachable: we should check
+ // this earlier.
+ return FfiUnsafe(
+ "enum has too many #[repr(...)] attributes");
+ }
+ }
+
+ // Check the contained variants.
+ for variant in variants {
+ for arg in &variant.args {
+ let arg = infer::normalize_associated_type(cx, arg);
+ let r = self.check_type_for_ffi(cache, arg);
+ match r {
+ FfiSafe => {}
+ FfiBadStruct(..) | FfiBadEnum(..) => { return r; }
+ FfiUnsafe(s) => { return FfiBadEnum(did, s); }
+ }
+ }
+ }
+ FfiSafe
+ }
+
+ ty::TyInt(ast::TyIs) => {
+ FfiUnsafe("found Rust type `isize` in foreign module, while \
+ `libc::c_int` or `libc::c_long` should be used")
+ }
+ ty::TyUint(ast::TyUs) => {
+ FfiUnsafe("found Rust type `usize` in foreign module, while \
+ `libc::c_uint` or `libc::c_ulong` should be used")
+ }
+ ty::TyChar => {
+ FfiUnsafe("found Rust type `char` in foreign module, while \
+ `u32` or `libc::wchar_t` should be used")
+ }
+
+ // Primitive types with a stable representation.
+ ty::TyBool | ty::TyInt(..) | ty::TyUint(..) |
+ ty::TyFloat(..) => FfiSafe,
+
+ ty::TyBox(..) => {
+ FfiUnsafe("found Rust type Box<_> in foreign module, \
+ consider using a raw pointer instead")
+ }
+
+ ty::TySlice(_) => {
+ FfiUnsafe("found Rust slice type in foreign module, \
+ consider using a raw pointer instead")
+ }
+
+ ty::TyTrait(..) => {
+ FfiUnsafe("found Rust trait type in foreign module, \
+ consider using a raw pointer instead")
+ }
+
+ ty::TyStr => {
+ FfiUnsafe("found Rust type `str` in foreign module; \
+ consider using a `*const libc::c_char`")
}
- def::DefTy(..) => {
- let tty = match self.cx.tcx.ast_ty_to_ty_cache.borrow().get(&id) {
- Some(&t) => t,
- None => panic!("ast_ty_to_ty_cache was incomplete after typeck!")
- };
- if !tty.is_ffi_safe(self.cx.tcx) {
- self.cx.span_lint(IMPROPER_CTYPES, sp,
- "found type without foreign-function-safe \
- representation annotation in foreign module, consider \
- adding a #[repr(...)] attribute to the type");
+ ty::TyTuple(_) => {
+ FfiUnsafe("found Rust tuple type in foreign module; \
+ consider using a struct instead`")
+ }
+
+ ty::TyRawPtr(ref m) | ty::TyRef(_, ref m) => {
+ self.check_type_for_ffi(cache, m.ty)
+ }
+
+ ty::TyArray(ty, _) => {
+ self.check_type_for_ffi(cache, ty)
+ }
+
+ ty::TyBareFn(None, bare_fn) => {
+ match bare_fn.abi {
+ abi::Rust |
+ abi::RustIntrinsic |
+ abi::RustCall => {
+ return FfiUnsafe(
+ "found function pointer with Rust calling \
+ convention in foreign module; consider using an \
+ `extern` function pointer")
+ }
+ _ => {}
}
+
+ let sig = cx.erase_late_bound_regions(&bare_fn.sig);
+ match sig.output {
+ ty::FnDiverging => {}
+ ty::FnConverging(output) => {
+ if !output.is_nil() {
+ let r = self.check_type_for_ffi(cache, output);
+ match r {
+ FfiSafe => {}
+ _ => { return r; }
+ }
+ }
+ }
+ }
+ for arg in sig.inputs {
+ let r = self.check_type_for_ffi(cache, arg);
+ match r {
+ FfiSafe => {}
+ _ => { return r; }
+ }
+ }
+ FfiSafe
+ }
+
+ ty::TyParam(..) | ty::TyInfer(..) | ty::TyError |
+ ty::TyClosure(..) | ty::TyProjection(..) |
+ ty::TyBareFn(Some(_), _) => {
+ panic!("Unexpected type in foreign function")
+ }
+ }
+ }
+
+ fn check_def(&mut self, sp: Span, id: ast::NodeId) {
+ let tty = match self.cx.tcx.ast_ty_to_ty_cache.borrow().get(&id) {
+ Some(&t) => t,
+ None => panic!("ast_ty_to_ty_cache was incomplete after typeck!")
+ };
+ let tty = infer::normalize_associated_type(self.cx.tcx, &tty);
+
+ match ImproperCTypesVisitor::check_type_for_ffi(self, &mut FnvHashSet(), tty) {
+ FfiResult::FfiSafe => {}
+ FfiResult::FfiUnsafe(s) => {
+ self.cx.span_lint(IMPROPER_CTYPES, sp, s);
+ }
+ FfiResult::FfiBadStruct(_, s) => {
+ // FIXME: This diagnostic is difficult to read, and doesn't
+ // point at the relevant field.
+ self.cx.span_lint(IMPROPER_CTYPES, sp,
+ &format!("found non-foreign-function-safe member in \
+ struct marked #[repr(C)]: {}", s));
+ }
+ FfiResult::FfiBadEnum(_, s) => {
+ // FIXME: This diagnostic is difficult to read, and doesn't
+ // point at the relevant variant.
+ self.cx.span_lint(IMPROPER_CTYPES, sp,
+ &format!("found non-foreign-function-safe member in \
+ enum: {}", s));
}
- _ => ()
}
}
}
impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> {
fn visit_ty(&mut self, ty: &ast::Ty) {
- if let ast::TyPath(..) = ty.node {
- self.check_def(ty.span, ty.id);
+ match ty.node {
+ ast::TyPath(..) |
+ ast::TyBareFn(..) => self.check_def(ty.span, ty.id),
+ ast::TyVec(..) => {
+ self.cx.span_lint(IMPROPER_CTYPES, ty.span,
+ "found Rust slice type in foreign module, consider \
+ using a raw pointer instead");
+ }
+ ast::TyFixedLengthVec(ref ty, _) => self.visit_ty(ty),
+ ast::TyTup(..) => {
+ self.cx.span_lint(IMPROPER_CTYPES, ty.span,
+ "found Rust tuple type in foreign module; \
+ consider using a struct instead`")
+ }
+ _ => visit::walk_ty(self, ty)
}
- visit::walk_ty(self, ty);
}
}
#![feature(ref_slice)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
+#![feature(slice_patterns)]
#![feature(staged_api)]
#![feature(str_char)]
pub fn LLVMGetArrayLength(ArrayTy: TypeRef) -> c_uint;
pub fn LLVMGetPointerAddressSpace(PointerTy: TypeRef) -> c_uint;
pub fn LLVMGetPointerToGlobal(EE: ExecutionEngineRef, V: ValueRef)
- -> *const ();
+ -> *const c_void;
pub fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint;
/* Operations on other types */
use std::os::windows::prelude::*;
use std::ops::RangeFrom;
use libc::{DWORD, LPCWSTR, LONG, LPDWORD, LPBYTE, ERROR_SUCCESS};
+use libc::c_void;
const HKEY_LOCAL_MACHINE: HKEY = 0x80000002 as HKEY;
const KEY_WOW64_32KEY: REGSAM = 0x0200;
pub type PHKEY = *mut HKEY;
pub type REGSAM = DWORD;
pub type LPWSTR = *mut u16;
-pub type PFILETIME = *mut ();
+pub type PFILETIME = *mut c_void;
#[link(name = "advapi32")]
extern "system" {
use rt::libunwind as uw;
use libc::{c_void, c_int};
- #[repr(C)]
- pub struct EXCEPTION_RECORD;
- #[repr(C)]
- pub struct CONTEXT;
- #[repr(C)]
- pub struct DISPATCHER_CONTEXT;
+ // Fake definitions; these are actually complicated structs,
+ // but we don't use the contents here.
+ pub type EXCEPTION_RECORD = c_void;
+ pub type CONTEXT = c_void;
+ pub type DISPATCHER_CONTEXT = c_void;
#[repr(C)]
#[derive(Copy, Clone)]
Handler { _data: 0 as *mut libc::c_void }
}
+#[repr(C)]
pub struct EXCEPTION_RECORD {
pub ExceptionCode: DWORD,
pub ExceptionFlags: DWORD,
pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS]
}
+#[repr(C)]
pub struct EXCEPTION_POINTERS {
pub ExceptionRecord: *mut EXCEPTION_RECORD,
pub ContextRecord: LPVOID
#[linkage = "extern_weak"]
static __dso_handle: *mut u8;
#[linkage = "extern_weak"]
- static __cxa_thread_atexit_impl: *const ();
+ static __cxa_thread_atexit_impl: *const libc::c_void;
}
if !__cxa_thread_atexit_impl.is_null() {
type F = unsafe extern fn(dtor: unsafe extern fn(*mut u8),
arg: *mut u8,
dso_handle: *mut u8) -> libc::c_int;
- mem::transmute::<*const (), F>(__cxa_thread_atexit_impl)
+ mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl)
(dtor, t, &__dso_handle as *const _ as *mut _);
return
}
}
extern "C" {
- fn foo(x: A); //~ ERROR found type without foreign-function-safe
+ fn foo(x: A); //~ ERROR found struct without foreign-function-safe
fn bar(x: B); //~ ERROR foreign-function-safe
fn baz(x: C);
fn qux(x: A2); //~ ERROR foreign-function-safe
#![deny(warnings)]
extern {
- pub fn foo(x: (isize)); //~ ERROR found rust type `isize` in foreign module
+ pub fn foo(x: (isize)); //~ ERROR found Rust type `isize` in foreign module
}
fn main() {
extern {
fn zf(x: Z);
- fn uf(x: U); //~ ERROR found type without foreign-function-safe
- fn bf(x: B); //~ ERROR found type without foreign-function-safe
- fn tf(x: T); //~ ERROR found type without foreign-function-safe
+ fn uf(x: U); //~ ERROR found enum without foreign-function-safe
+ fn bf(x: B); //~ ERROR found enum without foreign-function-safe
+ fn tf(x: T); //~ ERROR found enum without foreign-function-safe
}
pub fn main() { }
extern crate libc;
+trait Mirror { type It; }
+impl<T> Mirror for T { type It = Self; }
+#[repr(C)]
+pub struct StructWithProjection(*mut <StructWithProjection as Mirror>::It);
+#[repr(C)]
+pub struct StructWithProjectionAndLifetime<'a>(
+ &'a mut <StructWithProjectionAndLifetime<'a> as Mirror>::It
+);
+pub type I32Pair = (i32, i32);
+#[repr(C)]
+pub struct ZeroSize;
+pub type RustFn = fn();
+pub type RustBadRet = extern fn() -> Box<u32>;
+
extern {
- pub fn bare_type1(size: isize); //~ ERROR: found rust type
- pub fn bare_type2(size: usize); //~ ERROR: found rust type
- pub fn ptr_type1(size: *const isize); //~ ERROR: found rust type
- pub fn ptr_type2(size: *const usize); //~ ERROR: found rust type
+ pub fn bare_type1(size: isize); //~ ERROR: found Rust type
+ pub fn bare_type2(size: usize); //~ ERROR: found Rust type
+ pub fn ptr_type1(size: *const isize); //~ ERROR: found Rust type
+ pub fn ptr_type2(size: *const usize); //~ ERROR: found Rust type
+ pub fn slice_type(p: &[u32]); //~ ERROR: found Rust slice type
+ pub fn str_type(p: &str); //~ ERROR: found Rust type
+ pub fn box_type(p: Box<u32>); //~ ERROR found Rust type
+ pub fn char_type(p: char); //~ ERROR found Rust type
+ pub fn trait_type(p: &Clone); //~ ERROR found Rust trait type
+ pub fn tuple_type(p: (i32, i32)); //~ ERROR found Rust tuple type
+ pub fn tuple_type2(p: I32Pair); //~ ERROR found Rust tuple type
+ pub fn zero_size(p: ZeroSize); //~ ERROR found zero-size struct
+ pub fn fn_type(p: RustFn); //~ ERROR found function pointer with Rust
+ pub fn fn_type2(p: fn()); //~ ERROR found function pointer with Rust
+ pub fn fn_contained(p: RustBadRet); //~ ERROR: found Rust type
pub fn good1(size: *const libc::c_int);
pub fn good2(size: *const libc::c_uint);
+ pub fn good3(fptr: Option<extern fn()>);
+ pub fn good4(aptr: &[u8; 4 as usize]);
+ pub fn good5(s: StructWithProjection);
+ pub fn good6(s: StructWithProjectionAndLifetime);
+ pub fn good7(fptr: extern fn() -> ());
+ pub fn good8(fptr: extern fn() -> !);
}
fn main() {
mod xx {
extern {
- pub fn strlen(str: *const u8) -> usize; //~ ERROR found rust type `usize`
- pub fn foo(x: isize, y: usize); //~ ERROR found rust type `isize`
- //~^ ERROR found rust type `usize`
+ pub fn strlen(str: *const u8) -> usize; //~ ERROR found Rust type `usize`
+ pub fn foo(x: isize, y: usize); //~ ERROR found Rust type `isize`
+ //~^ ERROR found Rust type `usize`
}
}
// except according to those terms.
#![feature(rustc_private)]
+#![feature(libc)]
+extern crate libc;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_lint;
use rustc::session::build_session;
use rustc_driver::driver;
use rustc_resolve::MakeGlobMap;
+use libc::c_void;
use syntax::diagnostics::registry::Registry;
}
/// Returns a raw pointer to the named function.
- pub fn get_function(&mut self, name: &str) -> Option<*const ()> {
+ pub fn get_function(&mut self, name: &str) -> Option<*const c_void> {
let s = CString::new(name.as_bytes()).unwrap();
for &m in &self.modules {
}
/// Returns a raw pointer to the named global item.
- pub fn get_global(&mut self, name: &str) -> Option<*const ()> {
+ pub fn get_global(&mut self, name: &str) -> Option<*const c_void> {
let s = CString::new(name.as_bytes()).unwrap();
for &m in &self.modules {