]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #21282 - Aatch:init-memzero, r=alexcrichton
authorbors <bors@rust-lang.org>
Mon, 19 Jan 2015 12:17:07 +0000 (12:17 +0000)
committerbors <bors@rust-lang.org>
Mon, 19 Jan 2015 12:17:07 +0000 (12:17 +0000)
LLVM gets overwhelmed when presented with a zeroinitializer for a large
type. In unoptimised builds, it generates a long sequence of stores to
memory. In optmised builds, it manages to generate a standard memset of
zero values, but takes a long time doing so.

Call out to the `llvm.memset` function to zero out the memory instead.

Fixes #21264

17 files changed:
src/liblibc/lib.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc_trans/trans/debuginfo.rs
src/librustc_trans/trans/foreign.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/collect.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/format.rs
src/libstd/dynamic_lib.rs
src/libstd/sys/windows/c.rs
src/libsyntax/ast.rs
src/libsyntax/fold.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/test.rs
src/test/pretty/fn-return.rs [new file with mode: 0644]

index 0ad18e253292711496fe06b9e1fbefcc6fa1c68c..d010615a24c8a5762001fac43760db69bedd032b 100644 (file)
@@ -2207,10 +2207,10 @@ pub mod bsd44 {
             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;
index bbd12c9671d2855c7a58dd79d01264acb1546bbf..1b9d6ec6c33b694162c4451075d24838b7e2f9fb 100644 (file)
@@ -1177,6 +1177,7 @@ fn rebuild_output(&self, ty: &ast::FunctionRetTy,
             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)
         }
     }
index a03a5090c050bc9f73b33618f523a8311c7c596e..ea66b97bbf968e30d5186f7026f68720f9acfc82 100644 (file)
@@ -1450,18 +1450,15 @@ fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         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
index abb961d87de96a23078c165a0e2efb406f08c940..c989d2311be36217597e0cdaaa676be229c094f2 100644 (file)
@@ -445,9 +445,8 @@ fn gate_simd_ffi(tcx: &ty::ctxt, decl: &ast::FnDecl, ty: &ty::BareFnTy) {
         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())
         }
     }
 }
index f2927dfd843400551699b78d77612a71bd5127c7..c2b34acc6c8cc30f47dcac7a8da8967b9d72a4a8 100644 (file)
@@ -1359,7 +1359,8 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
                                                               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 {
@@ -1486,14 +1487,21 @@ pub fn ty_of_closure<'tcx>(
 
     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()));
index c56952abc4419f12bc9eba5b48b71ae1a93f9f2b..25ba7ccdbc4d93f92f07fad03fff836fbca9025e 100644 (file)
@@ -1488,7 +1488,9 @@ fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CollectCtxt<'a, '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
     };
 
index 8dc3adad3b27a010feae9758f61c427960daaf76..7342c9f3e81de583f25e03391cc8a7cc1cc52b33 100644 (file)
@@ -1141,6 +1141,7 @@ fn clean(&self, cx: &DocContext) -> Argument {
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
 pub enum FunctionRetTy {
     Return(Type),
+    DefaultReturn,
     NoReturn
 }
 
@@ -1148,7 +1149,8 @@ impl Clean<FunctionRetTy> for ast::FunctionRetTy {
     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
         }
     }
 }
index d13936b2168658f80472d625bacabfde1bcc6a9f..57b8d666c95b722db8ca3a027d758975e1cfdfc8 100644 (file)
@@ -557,6 +557,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             clean::Return(clean::Tuple(ref tys)) if tys.is_empty() => Ok(()),
             clean::Return(ref ty) => write!(f, " -&gt; {}", ty),
+            clean::DefaultReturn => Ok(()),
             clean::NoReturn => write!(f, " -&gt; !")
         }
     }
index 3eeb09b79dab23904539f68eec00317e540a303a..db1239ae5b5ff3bccc739d7d543f4871def814e0 100644 (file)
@@ -52,21 +52,14 @@ impl DynamicLibrary {
     /// 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 })
         }
     }
 
@@ -198,8 +191,7 @@ fn test_errors_do_not_crash() {
           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};
@@ -207,13 +199,26 @@ pub mod dl {
     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
@@ -249,14 +254,6 @@ pub unsafe fn close(handle: *mut u8) {
         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,
@@ -269,11 +266,13 @@ fn dlsym(handle: *mut libc::c_void,
 }
 
 #[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};
@@ -282,19 +281,75 @@ pub mod dl {
     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
@@ -326,10 +381,10 @@ pub unsafe fn close(handle: *mut u8) {
         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;
     }
 }
index 37ed32fa36773918981d5f4dc20598ec35456114..da3b7ee2f2fd5d7c560b59e658ae0143253ee5a3 100644 (file)
@@ -226,6 +226,7 @@ extern "system" fn fallback($($argname: $argtype),*)
     /// * `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;
 
@@ -249,6 +250,12 @@ pub mod kernel32 {
                 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 }
+            }
+        }
     }
 }
 
index 0ea429116b0bb86308ee7532ce1a8304016139ed..fcf80410da240abc47f15246aa708ed4f5c546f8 100644 (file)
@@ -1390,6 +1390,10 @@ pub enum FunctionRetTy {
     /// 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>),
 }
@@ -1398,6 +1402,7 @@ impl FunctionRetTy {
     pub fn span(&self) -> Span {
         match *self {
             NoReturn(span) => span,
+            DefaultReturn(span) => span,
             Return(ref ty) => ty.span
         }
     }
index 16c29c9b5eb33a4bc206baf8b39b477c3fb09064..f484650ad5b06dfd90fc2e2de05636dd786e9f78 100644 (file)
@@ -726,6 +726,7 @@ pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
         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
@@ -1189,14 +1190,7 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: P<ForeignItem>, folder: &mut T) ->
         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)
index f1f547ba0c7dd52e24855c6f32f558ecb390e743..90e236dfde35bdc4a91cd596f004b24a1ec31a88 100644 (file)
@@ -1066,9 +1066,7 @@ fn parser_done(p: Parser){
                                     }),
                                         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,
index 130972b4582968ad95b5029ffcdfe096b4def384..b2f6938f513e58726aa33c68a9084da57c60b221 100644 (file)
@@ -19,7 +19,8 @@
 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};
@@ -1426,11 +1427,7 @@ pub fn parse_ret_ty(&mut self) -> FunctionRetTy {
             }
         } 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))
         }
     }
 
@@ -4550,15 +4547,7 @@ fn parse_fn_block_decl(&mut self)
                 (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,
@@ -4575,15 +4564,7 @@ fn parse_proc_decl(&mut self) -> P<FnDecl> {
                                      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,
index 5d76dc710060b591e4bed8764fc01ce9a9dfc9c7..b59e770c6ba519520331a4b79c238d91c57ef3bb 100644 (file)
@@ -2351,10 +2351,8 @@ pub fn print_fn_block_args(
         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());
@@ -2364,6 +2362,7 @@ pub fn print_fn_block_args(
                 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)
@@ -2385,10 +2384,8 @@ pub fn print_proc_args(&mut self, decl: &ast::FnDecl) -> IoResult<()> {
         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());
@@ -2398,6 +2395,7 @@ pub fn print_proc_args(&mut self, decl: &ast::FnDecl) -> IoResult<()> {
                 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)
@@ -2684,13 +2682,8 @@ pub fn print_arg(&mut self, input: &ast::Arg) -> IoResult<()> {
     }
 
     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());
@@ -2699,6 +2692,7 @@ pub fn print_fn_output(&mut self, decl: &ast::FnDecl) -> IoResult<()> {
         match decl.output {
             ast::NoReturn(_) =>
                 try!(self.word_nbsp("!")),
+            ast::DefaultReturn(..) => unreachable!(),
             ast::Return(ref ty) =>
                 try!(self.print_type(&**ty))
         }
@@ -3071,9 +3065,7 @@ fn test_fun_to_string() {
 
         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();
index 895268f96c8a8b3c666711b587277b97dd3d3f81..5f869d5093feca6303ca863e0d9fbf238e18b2bb 100644 (file)
@@ -297,11 +297,8 @@ fn has_test_signature(i: &ast::Item) -> HasTestSignature {
         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
@@ -336,11 +333,8 @@ fn has_test_signature(i: &ast::Item) -> bool {
             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
diff --git a/src/test/pretty/fn-return.rs b/src/test/pretty/fn-return.rs
new file mode 100644 (file)
index 0000000..8a22329
--- /dev/null
@@ -0,0 +1,17 @@
+// 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() { }