pub const IPPROTO_TCP: c_int = 6;
pub const IPPROTO_IP: c_int = 0;
pub const IPPROTO_IPV6: c_int = 41;
- pub const IP_MULTICAST_TTL: c_int = 3;
- pub const IP_MULTICAST_LOOP: c_int = 4;
- pub const IP_ADD_MEMBERSHIP: c_int = 5;
- pub const IP_DROP_MEMBERSHIP: c_int = 6;
+ pub const IP_MULTICAST_TTL: c_int = 10;
+ pub const IP_MULTICAST_LOOP: c_int = 11;
+ pub const IP_ADD_MEMBERSHIP: c_int = 12;
+ pub const IP_DROP_MEMBERSHIP: c_int = 13;
pub const IPV6_ADD_MEMBERSHIP: c_int = 5;
pub const IPV6_DROP_MEMBERSHIP: c_int = 6;
pub const IP_TTL: c_int = 4;
ast::Return(ref ret_ty) => ast::Return(
self.rebuild_arg_ty_or_output(&**ret_ty, lifetime, anon_nums, region_names)
),
+ ast::DefaultReturn(span) => ast::DefaultReturn(span),
ast::NoReturn(span) => ast::NoReturn(span)
}
}
let mut signature = Vec::with_capacity(fn_decl.inputs.len() + 1);
// Return type -- llvm::DIBuilder wants this at index 0
- match fn_decl.output {
- ast::Return(ref ret_ty) if ret_ty.node == ast::TyTup(vec![]) =>
- signature.push(ptr::null_mut()),
- _ => {
- assert_type_for_node_id(cx, fn_ast_id, error_reporting_span);
-
- let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
- let return_type = monomorphize::apply_param_substs(cx.tcx(),
- param_substs,
- &return_type);
- signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
- }
+ assert_type_for_node_id(cx, fn_ast_id, error_reporting_span);
+ let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
+ let return_type = monomorphize::apply_param_substs(cx.tcx(),
+ param_substs,
+ &return_type);
+ if ty::type_is_nil(return_type) {
+ signature.push(ptr::null_mut())
+ } else {
+ signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
}
// Arguments types
for (input, ty) in decl.inputs.iter().zip(sig.inputs.iter()) {
check(&*input.ty, *ty)
}
- match decl.output {
- ast::NoReturn(_) => {}
- ast::Return(ref ty) => check(&**ty, sig.output.unwrap())
+ if let ast::Return(ref ty) = decl.output {
+ check(&**ty, sig.output.unwrap())
}
}
}
implied_output_region,
lifetimes_for_params,
&**output)),
- ast::NoReturn(_) => ty::FnDiverging
+ ast::DefaultReturn(..) => ty::FnConverging(ty::mk_nil(this.tcx())),
+ ast::NoReturn(..) => ty::FnDiverging
};
(ty::BareFnTy {
let expected_ret_ty = expected_sig.map(|e| e.output);
+ let is_infer = match decl.output {
+ ast::Return(ref output) if output.node == ast::TyInfer => true,
+ ast::DefaultReturn(..) => true,
+ _ => false
+ };
+
let output_ty = match decl.output {
- ast::Return(ref output) if output.node == ast::TyInfer && expected_ret_ty.is_some() =>
+ _ if is_infer && expected_ret_ty.is_some() =>
expected_ret_ty.unwrap(),
- ast::Return(ref output) if output.node == ast::TyInfer =>
- ty::FnConverging(this.ty_infer(output.span)),
+ _ if is_infer =>
+ ty::FnConverging(this.ty_infer(decl.output.span())),
ast::Return(ref output) =>
ty::FnConverging(ast_ty_to_ty(this, &rb, &**output)),
- ast::NoReturn(_) => ty::FnDiverging
+ ast::DefaultReturn(..) => unreachable!(),
+ ast::NoReturn(..) => ty::FnDiverging
};
debug!("ty_of_closure: input_tys={}", input_tys.repr(this.tcx()));
let output = match decl.output {
ast::Return(ref ty) =>
ty::FnConverging(ast_ty_to_ty(ccx, &rb, &**ty)),
- ast::NoReturn(_) =>
+ ast::DefaultReturn(..) =>
+ ty::FnConverging(ty::mk_nil(ccx.tcx)),
+ ast::NoReturn(..) =>
ty::FnDiverging
};
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
pub enum FunctionRetTy {
Return(Type),
+ DefaultReturn,
NoReturn
}
fn clean(&self, cx: &DocContext) -> FunctionRetTy {
match *self {
ast::Return(ref typ) => Return(typ.clean(cx)),
- ast::NoReturn(_) => NoReturn
+ ast::DefaultReturn(..) => DefaultReturn,
+ ast::NoReturn(..) => NoReturn
}
}
}
match *self {
clean::Return(clean::Tuple(ref tys)) if tys.is_empty() => Ok(()),
clean::Return(ref ty) => write!(f, " -> {}", ty),
+ clean::DefaultReturn => Ok(()),
clean::NoReturn => write!(f, " -> !")
}
}
/// Lazily open a dynamic library. When passed None it gives a
/// handle to the calling process
pub fn open(filename: Option<&Path>) -> Result<DynamicLibrary, String> {
- unsafe {
- let maybe_library = dl::check_for_errors_in(|| {
- match filename {
- Some(name) => dl::open_external(name.as_vec()),
- None => dl::open_internal()
- }
- });
-
- // The dynamic library must not be constructed if there is
- // an error opening the library so the destructor does not
- // run.
- match maybe_library {
- Err(err) => Err(err),
- Ok(handle) => Ok(DynamicLibrary { handle: handle })
- }
+ let maybe_library = dl::open(filename.map(|path| path.as_vec()));
+
+ // The dynamic library must not be constructed if there is
+ // an error opening the library so the destructor does not
+ // run.
+ match maybe_library {
+ Err(err) => Err(err),
+ Ok(handle) => Ok(DynamicLibrary { handle: handle })
}
}
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly"))]
-pub mod dl {
- pub use self::Rtld::*;
+mod dl {
use prelude::v1::*;
use ffi::{self, CString};
use libc;
use ptr;
- pub unsafe fn open_external(filename: &[u8]) -> *mut u8 {
+ pub fn open(filename: Option<&[u8]>) -> Result<*mut u8, String> {
+ check_for_errors_in(|| {
+ unsafe {
+ match filename {
+ Some(filename) => open_external(filename),
+ None => open_internal(),
+ }
+ }
+ })
+ }
+
+ const LAZY: libc::c_int = 1;
+
+ unsafe fn open_external(filename: &[u8]) -> *mut u8 {
let s = CString::from_slice(filename);
- dlopen(s.as_ptr(), Lazy as libc::c_int) as *mut u8
+ dlopen(s.as_ptr(), LAZY) as *mut u8
}
- pub unsafe fn open_internal() -> *mut u8 {
- dlopen(ptr::null(), Lazy as libc::c_int) as *mut u8
+ unsafe fn open_internal() -> *mut u8 {
+ dlopen(ptr::null(), LAZY) as *mut u8
}
pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
dlclose(handle as *mut libc::c_void); ()
}
- #[derive(Copy)]
- pub enum Rtld {
- Lazy = 1,
- Now = 2,
- Global = 256,
- Local = 0,
- }
-
#[link_name = "dl"]
extern {
fn dlopen(filename: *const libc::c_char,
}
#[cfg(target_os = "windows")]
-pub mod dl {
+mod dl {
use iter::IteratorExt;
use libc;
+ use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED;
use ops::FnOnce;
use os;
+ use option::Option::{self, Some, None};
use ptr;
use result::Result;
use result::Result::{Ok, Err};
use str;
use string::String;
use vec::Vec;
+ use sys::c::compat::kernel32::SetThreadErrorMode;
+
+ pub fn open(filename: Option<&[u8]>) -> Result<*mut u8, String> {
+ // disable "dll load failed" error dialog.
+ let mut use_thread_mode = true;
+ let prev_error_mode = unsafe {
+ // SEM_FAILCRITICALERRORS 0x01
+ let new_error_mode = 1;
+ let mut prev_error_mode = 0;
+ // Windows >= 7 supports thread error mode.
+ let result = SetThreadErrorMode(new_error_mode, &mut prev_error_mode);
+ if result == 0 {
+ let err = os::errno();
+ if err as libc::c_int == ERROR_CALL_NOT_IMPLEMENTED {
+ use_thread_mode = false;
+ // SetThreadErrorMode not found. use fallback solution: SetErrorMode()
+ // Note that SetErrorMode is process-wide so this can cause race condition!
+ // However, since even Windows APIs do not care of such problem (#20650),
+ // we just assume SetErrorMode race is not a great deal.
+ prev_error_mode = SetErrorMode(new_error_mode);
+ }
+ }
+ prev_error_mode
+ };
- pub unsafe fn open_external(filename: &[u8]) -> *mut u8 {
- // Windows expects Unicode data
- let filename_str = str::from_utf8(filename).unwrap();
- let mut filename_str: Vec<u16> = filename_str.utf16_units().collect();
- filename_str.push(0);
- LoadLibraryW(filename_str.as_ptr() as *const libc::c_void) as *mut u8
- }
+ unsafe {
+ SetLastError(0);
+ }
+
+ let result = match filename {
+ Some(filename) => {
+ let filename_str = str::from_utf8(filename).unwrap();
+ let mut filename_str: Vec<u16> = filename_str.utf16_units().collect();
+ filename_str.push(0);
+ let result = unsafe {
+ LoadLibraryW(filename_str.as_ptr() as *const libc::c_void)
+ };
+ // beware: Vec/String may change errno during drop!
+ // so we get error here.
+ if result == ptr::null_mut() {
+ let errno = os::errno();
+ Err(os::error_string(errno))
+ } else {
+ Ok(result as *mut u8)
+ }
+ }
+ None => {
+ let mut handle = ptr::null_mut();
+ let succeeded = unsafe {
+ GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &mut handle)
+ };
+ if succeeded == libc::FALSE {
+ let errno = os::errno();
+ Err(os::error_string(errno))
+ } else {
+ Ok(handle as *mut u8)
+ }
+ }
+ };
+
+ unsafe {
+ if use_thread_mode {
+ SetThreadErrorMode(prev_error_mode, ptr::null_mut());
+ } else {
+ SetErrorMode(prev_error_mode);
+ }
+ }
- pub unsafe fn open_internal() -> *mut u8 {
- let mut handle = ptr::null_mut();
- GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &mut handle);
- handle as *mut u8
+ result
}
pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
fn SetLastError(error: libc::size_t);
fn LoadLibraryW(name: *const libc::c_void) -> *mut libc::c_void;
fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *const u16,
- handle: *mut *mut libc::c_void)
- -> *mut libc::c_void;
+ handle: *mut *mut libc::c_void) -> libc::BOOL;
fn GetProcAddress(handle: *mut libc::c_void,
name: *const libc::c_char) -> *mut libc::c_void;
fn FreeLibrary(handle: *mut libc::c_void);
+ fn SetErrorMode(uMode: libc::c_uint) -> libc::c_uint;
}
}
/// * `CreateSymbolicLinkW`: Windows XP, Windows Server 2003
/// * `GetFinalPathNameByHandleW`: Windows XP, Windows Server 2003
pub mod kernel32 {
+ use libc::c_uint;
use libc::types::os::arch::extra::{DWORD, LPCWSTR, BOOLEAN, HANDLE};
use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED;
unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0 }
}
}
+
+ compat_fn! {
+ kernel32::SetThreadErrorMode(_dwNewMode: DWORD, _lpOldMode: *mut DWORD) -> c_uint {
+ unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0 }
+ }
+ }
}
}
/// Functions with return type ! that always
/// raise an error or exit (i.e. never return to the caller)
NoReturn(Span),
+ /// Return type is not specified. Functions default to () and
+ /// closures default to inference. Span points to where return
+ /// type would be inserted.
+ DefaultReturn(Span),
/// Everything else
Return(P<Ty>),
}
pub fn span(&self) -> Span {
match *self {
NoReturn(span) => span,
+ DefaultReturn(span) => span,
Return(ref ty) => ty.span
}
}
inputs: inputs.move_map(|x| fld.fold_arg(x)),
output: match output {
Return(ty) => Return(fld.fold_ty(ty)),
+ DefaultReturn(span) => DefaultReturn(span),
NoReturn(span) => NoReturn(span)
},
variadic: variadic
attrs: attrs.move_map(|x| folder.fold_attribute(x)),
node: match node {
ForeignItemFn(fdec, generics) => {
- ForeignItemFn(fdec.map(|FnDecl {inputs, output, variadic}| FnDecl {
- inputs: inputs.move_map(|a| folder.fold_arg(a)),
- output: match output {
- Return(ty) => Return(folder.fold_ty(ty)),
- NoReturn(span) => NoReturn(span)
- },
- variadic: variadic
- }), folder.fold_generics(generics))
+ ForeignItemFn(folder.fold_fn_decl(fdec), folder.fold_generics(generics))
}
ForeignItemStatic(t, m) => {
ForeignItemStatic(folder.fold_ty(t), m)
}),
id: ast::DUMMY_NODE_ID
}),
- output: ast::Return(P(ast::Ty{id: ast::DUMMY_NODE_ID,
- node: ast::TyTup(vec![]),
- span:sp(15,15)})), // not sure
+ output: ast::DefaultReturn(sp(15, 15)),
variadic: false
}),
ast::Unsafety::Normal,
use ast::{BiBitAnd, BiBitOr, BiBitXor, BiRem, BiLt, BiGt, Block};
use ast::{BlockCheckMode, CaptureByRef, CaptureByValue, CaptureClause};
use ast::{Crate, CrateConfig, Decl, DeclItem};
-use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, EnumDef, ExplicitSelf};
+use ast::{DeclLocal, DefaultBlock, DefaultReturn};
+use ast::{UnDeref, BiDiv, EMPTY_CTXT, EnumDef, ExplicitSelf};
use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
use ast::{ExprBreak, ExprCall, ExprCast};
}
} else {
let pos = self.span.lo;
- Return(P(Ty {
- id: ast::DUMMY_NODE_ID,
- node: TyTup(vec![]),
- span: mk_sp(pos, pos),
- }))
+ DefaultReturn(mk_sp(pos, pos))
}
}
(optional_unboxed_closure_kind, args)
}
};
- let output = if self.check(&token::RArrow) {
- self.parse_ret_ty()
- } else {
- Return(P(Ty {
- id: ast::DUMMY_NODE_ID,
- node: TyInfer,
- span: self.span,
- }))
- };
+ let output = self.parse_ret_ty();
(P(FnDecl {
inputs: inputs_captures,
seq_sep_trailing_allowed(token::Comma),
|p| p.parse_fn_block_arg());
- let output = if self.check(&token::RArrow) {
- self.parse_ret_ty()
- } else {
- Return(P(Ty {
- id: ast::DUMMY_NODE_ID,
- node: TyInfer,
- span: self.span,
- }))
- };
+ let output = self.parse_ret_ty();
P(FnDecl {
inputs: inputs,
try!(self.print_fn_args(decl, None));
try!(word(&mut self.s, "|"));
- if let ast::Return(ref ty) = decl.output {
- if ty.node == ast::TyInfer {
- return self.maybe_print_comment(ty.span.lo);
- }
+ if let ast::DefaultReturn(..) = decl.output {
+ return Ok(());
}
try!(self.space_if_not_bol());
try!(self.print_type(&**ty));
self.maybe_print_comment(ty.span.lo)
}
+ ast::DefaultReturn(..) => unreachable!(),
ast::NoReturn(span) => {
try!(self.word_nbsp("!"));
self.maybe_print_comment(span.lo)
try!(self.print_fn_args(decl, None));
try!(word(&mut self.s, ")"));
- if let ast::Return(ref ty) = decl.output {
- if ty.node == ast::TyInfer {
- return self.maybe_print_comment(ty.span.lo);
- }
+ if let ast::DefaultReturn(..) = decl.output {
+ return Ok(());
}
try!(self.space_if_not_bol());
try!(self.print_type(&**ty));
self.maybe_print_comment(ty.span.lo)
}
+ ast::DefaultReturn(..) => unreachable!(),
ast::NoReturn(span) => {
try!(self.word_nbsp("!"));
self.maybe_print_comment(span.lo)
}
pub fn print_fn_output(&mut self, decl: &ast::FnDecl) -> IoResult<()> {
- if let ast::Return(ref ty) = decl.output {
- match ty.node {
- ast::TyTup(ref tys) if tys.is_empty() => {
- return self.maybe_print_comment(ty.span.lo);
- }
- _ => ()
- }
+ if let ast::DefaultReturn(..) = decl.output {
+ return Ok(());
}
try!(self.space_if_not_bol());
match decl.output {
ast::NoReturn(_) =>
try!(self.word_nbsp("!")),
+ ast::DefaultReturn(..) => unreachable!(),
ast::Return(ref ty) =>
try!(self.print_type(&**ty))
}
let decl = ast::FnDecl {
inputs: Vec::new(),
- output: ast::Return(P(ast::Ty {id: 0,
- node: ast::TyTup(vec![]),
- span: codemap::DUMMY_SP})),
+ output: ast::DefaultReturn(codemap::DUMMY_SP),
variadic: false
};
let generics = ast_util::empty_generics();
match &i.node {
&ast::ItemFn(ref decl, _, _, ref generics, _) => {
let no_output = match decl.output {
- ast::Return(ref ret_ty) => match ret_ty.node {
- ast::TyTup(ref tys) if tys.is_empty() => true,
- _ => false,
- },
- ast::NoReturn(_) => false
+ ast::DefaultReturn(..) => true,
+ _ => false
};
if decl.inputs.is_empty()
&& no_output
ast::ItemFn(ref decl, _, _, ref generics, _) => {
let input_cnt = decl.inputs.len();
let no_output = match decl.output {
- ast::Return(ref ret_ty) => match ret_ty.node {
- ast::TyTup(ref tys) if tys.is_empty() => true,
- _ => false,
- },
- ast::NoReturn(_) => false
+ ast::DefaultReturn(..) => true,
+ _ => false
};
let tparm_cnt = generics.ty_params.len();
// NB: inadequate check, but we're running
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// pp-exact
+
+// Check that `fn f() -> () { }` does not print as `fn f() { }`.
+
+fn f() -> () { }
+
+fn main() { }