From d7918fb2e889c5ccb58ab8b97d2581cc763f2306 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Sun, 3 Dec 2017 22:16:24 +0100
Subject: [PATCH 01/25] Implements RFC 1937: `?` in `main`

This is the first part of the RFC 1937 that supports new
`Termination` trait in the rust `main` function.
---
 src/librustc/middle/lang_items.rs             |  2 +
 src/librustc_mir/monomorphize/collector.rs    | 84 ++++++++++++++-----
 src/librustc_mir/monomorphize/partitioning.rs | 11 ++-
 src/librustc_trans/base.rs                    | 34 ++++++--
 src/librustc_typeck/check/mod.rs              | 24 +++++-
 src/librustc_typeck/lib.rs                    | 16 ----
 src/libstd/lib.rs                             |  6 ++
 src/libstd/rt.rs                              | 45 +++++++++-
 src/libstd/termination.rs                     | 74 ++++++++++++++++
 .../termination-trait-not-satisfied.rs        | 15 ++++
 .../run-pass/termination-trait-for-empty.rs   | 13 +++
 .../run-pass/termination-trait-for-i32.rs     | 15 ++++
 .../run-pass/termination-trait-for-result.rs  | 17 ++++
 13 files changed, 304 insertions(+), 52 deletions(-)
 create mode 100644 src/libstd/termination.rs
 create mode 100644 src/test/compile-fail/termination-trait-not-satisfied.rs
 create mode 100644 src/test/run-pass/termination-trait-for-empty.rs
 create mode 100644 src/test/run-pass/termination-trait-for-i32.rs
 create mode 100644 src/test/run-pass/termination-trait-for-result.rs

diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index f8933d06360e0..dca676130b9a7 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -338,6 +338,8 @@ language_item_table! {
     U128ShloFnLangItem,              "u128_shlo",               u128_shlo_fn;
     I128ShroFnLangItem,              "i128_shro",               i128_shro_fn;
     U128ShroFnLangItem,              "u128_shro",               u128_shro_fn;
+
+    TerminationTraitLangItem,        "termination",             termination;
 }
 
 impl<'a, 'tcx, 'gcx> TyCtxt<'a, 'tcx, 'gcx> {
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 0b8666800a5a5..056c6989abac8 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -194,11 +194,13 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir::map as hir_map;
 use rustc::hir::def_id::DefId;
 use rustc::middle::const_val::ConstVal;
-use rustc::middle::lang_items::{ExchangeMallocFnLangItem};
+use rustc::middle::lang_items::{ExchangeMallocFnLangItem,StartFnLangItem};
+use rustc::middle::trans::TransItem;
 use rustc::traits;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{Substs, Kind};
 use rustc::ty::{self, TypeFoldable, Ty, TyCtxt};
 use rustc::ty::adjustment::CustomCoerceUnsized;
+use rustc::session::config;
 use rustc::mir::{self, Location};
 use rustc::mir::visit::Visitor as MirVisitor;
 use rustc::mir::mono::MonoItem;
@@ -212,6 +214,8 @@ use rustc_data_structures::bitvec::BitVector;
 
 use syntax::attr;
 
+use std::iter;
+
 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
 pub enum MonoItemCollectionMode {
     Eager,
@@ -329,6 +333,8 @@ fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             tcx.hir.local_def_id(node_id)
         });
 
+        debug!("collect_roots: entry_fn = {:?}", entry_fn);
+
         let mut visitor = RootCollector {
             tcx,
             mode,
@@ -951,16 +957,8 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
                 // actually used somewhere. Just declaring them is insufficient.
             }
             hir::ItemFn(..) => {
-                let tcx = self.tcx;
-                let def_id = tcx.hir.local_def_id(item.id);
-
-                if self.is_root(def_id) {
-                    debug!("RootCollector: ItemFn({})",
-                           def_id_to_string(tcx, def_id));
-
-                    let instance = Instance::mono(tcx, def_id);
-                    self.output.push(MonoItem::Fn(instance));
-                }
+                let def_id = self.tcx.hir.local_def_id(item.id);
+                self.push_if_root(def_id);
             }
         }
     }
@@ -973,16 +971,8 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
     fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
         match ii.node {
             hir::ImplItemKind::Method(hir::MethodSig { .. }, _) => {
-                let tcx = self.tcx;
-                let def_id = tcx.hir.local_def_id(ii.id);
-
-                if self.is_root(def_id) {
-                    debug!("RootCollector: MethodImplItem({})",
-                           def_id_to_string(tcx, def_id));
-
-                    let instance = Instance::mono(tcx, def_id);
-                    self.output.push(MonoItem::Fn(instance));
-                }
+                let def_id = self.tcx.hir.local_def_id(ii.id);
+                self.push_if_root(def_id);
             }
             _ => { /* Nothing to do here */ }
         }
@@ -1003,6 +993,56 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> {
             }
         }
     }
+
+    /// If `def_id` represents a root, then push it onto the list of
+    /// outputs. (Note that all roots must be monomorphic.)
+    fn push_if_root(&mut self, def_id: DefId) {
+        if self.is_root(def_id) {
+            debug!("RootCollector::push_if_root: found root def_id={:?}", def_id);
+
+            let instance = Instance::mono(self.tcx, def_id);
+            self.output.push(create_fn_trans_item(instance));
+
+            self.push_extra_entry_roots(def_id);
+        }
+    }
+
+    /// As a special case, when/if we encounter the
+    /// `main()` function, we also have to generate a
+    /// monomorphized copy of the start lang item based on
+    /// the return type of `main`. This is not needed when
+    /// the user writes their own `start` manually.
+    fn push_extra_entry_roots(&mut self, def_id: DefId) {
+        if self.entry_fn != Some(def_id) {
+            return;
+        }
+
+        if self.tcx.sess.entry_type.get() != Some(config::EntryMain) {
+            return;
+        }
+
+        let start_def_id = match self.tcx.lang_items().require(StartFnLangItem) {
+            Ok(s) => s,
+            Err(err) => self.tcx.sess.fatal(&err),
+        };
+        let main_ret_ty = self.tcx.fn_sig(def_id).output();
+
+        // Given that `main()` has no arguments,
+        // then its return type cannot have
+        // late-bound regions, since late-bound
+        // regions must appear in the argument
+        // listing.
+        let main_ret_ty = self.tcx.no_late_bound_regions(&main_ret_ty).unwrap();
+
+        let start_instance = Instance::resolve(
+            self.tcx,
+            ty::ParamEnv::empty(traits::Reveal::All),
+            start_def_id,
+            self.tcx.mk_substs(iter::once(Kind::from(main_ret_ty)))
+        ).unwrap();
+
+        self.output.push(create_fn_trans_item(start_instance));
+    }
 }
 
 fn item_has_type_parameters<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index b1fef274cba4b..e34698da4dafb 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -106,7 +106,8 @@ use monomorphize::collector::InliningMap;
 use rustc::dep_graph::WorkProductId;
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::DefPathData;
-use rustc::mir::mono::{Linkage, Visibility};
+use rustc::middle::lang_items::StartFnLangItem;
+use rustc::middle::trans::{Linkage, Visibility};
 use rustc::ty::{self, TyCtxt, InstanceDef};
 use rustc::ty::item_path::characteristic_def_id_of_type;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
@@ -312,7 +313,13 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     MonoItem::Fn(ref instance) => {
                         let visibility = match instance.def {
                             InstanceDef::Item(def_id) => {
-                                if def_id.is_local() {
+                                let start_def_id = tcx.lang_items().require(StartFnLangItem);
+
+                                // If we encounter the lang start item, we set the visibility to
+                                // default.
+                                if start_def_id == Ok(def_id) {
+                                    Visibility::Default
+                                } else if def_id.is_local() {
                                     if tcx.is_exported_symbol(def_id) {
                                         Visibility::Default
                                     } else {
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 0efe5f9a5cb6f..b2d516e786883 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -44,6 +44,7 @@ use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
 use rustc::ty::maps::Providers;
 use rustc::dep_graph::{DepNode, DepConstructor};
+use rustc::ty::subst::Kind;
 use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
 use rustc::util::common::{time, print_time_passes_entry};
 use rustc::session::config::{self, NoDebugInfo};
@@ -79,6 +80,7 @@ use std::str;
 use std::sync::Arc;
 use std::time::{Instant, Duration};
 use std::i32;
+use std::iter;
 use std::sync::mpsc;
 use syntax_pos::Span;
 use syntax_pos::symbol::InternedString;
@@ -540,17 +542,28 @@ fn maybe_create_entry_wrapper(ccx: &CrateContext) {
 
     let et = ccx.sess().entry_type.get().unwrap();
     match et {
-        config::EntryMain => create_entry_fn(ccx, span, main_llfn, true),
-        config::EntryStart => create_entry_fn(ccx, span, main_llfn, false),
+        config::EntryMain => create_entry_fn(ccx, span, main_llfn, main_def_id, true),
+        config::EntryStart => create_entry_fn(ccx, span, main_llfn, main_def_id, false),
         config::EntryNone => {}    // Do nothing.
     }
 
-    fn create_entry_fn(ccx: &CrateContext,
+    fn create_entry_fn<'ccx>(ccx: &'ccx CrateContext,
                        sp: Span,
                        rust_main: ValueRef,
+                       rust_main_def_id: DefId,
                        use_start_lang_item: bool) {
-        // Signature of native main(), corresponding to C's `int main(int, char **)`
-        let llfty = Type::func(&[Type::c_int(ccx), Type::i8p(ccx).ptr_to()], &Type::c_int(ccx));
+        // The libstd lang_start function does not return anything, while user defined lang start
+        // returns a isize
+        let start_output_ty = if use_start_lang_item { Type::void(ccx) } else { Type::c_int(ccx) };
+        let llfty = Type::func(&[Type::c_int(ccx), Type::i8p(ccx).ptr_to()], &start_output_ty);
+
+        let main_ret_ty = ccx.tcx().fn_sig(rust_main_def_id).output();
+        // Given that `main()` has no arguments,
+        // then its return type cannot have
+        // late-bound regions, since late-bound
+        // regions must appear in the argument
+        // listing.
+        let main_ret_ty = ccx.tcx().no_late_bound_regions(&main_ret_ty).unwrap();
 
         if declare::get_defined_value(ccx, "main").is_some() {
             // FIXME: We should be smart and show a better diagnostic here.
@@ -577,8 +590,8 @@ fn maybe_create_entry_wrapper(ccx: &CrateContext) {
 
         let (start_fn, args) = if use_start_lang_item {
             let start_def_id = ccx.tcx().require_lang_item(StartFnLangItem);
-            let start_instance = Instance::mono(ccx.tcx(), start_def_id);
-            let start_fn = callee::get_fn(ccx, start_instance);
+            let start_fn = callee::resolve_and_get_fn(ccx, start_def_id, ccx.tcx().mk_substs(
+                iter::once(Kind::from(main_ret_ty))));
             (start_fn, vec![bld.pointercast(rust_main, Type::i8p(ccx).ptr_to()),
                             arg_argc, arg_argv])
         } else {
@@ -588,8 +601,11 @@ fn maybe_create_entry_wrapper(ccx: &CrateContext) {
 
         let result = bld.call(start_fn, &args, None);
 
-        // Return rust start function's result from native main()
-        bld.ret(bld.intcast(result, Type::c_int(ccx), true));
+        if use_start_lang_item {
+            bld.ret_void();
+        } else {
+            bld.ret(bld.intcast(result, Type::c_int(ccx), true));
+        }
     }
 }
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index ab81d26e77175..159340d19a7fe 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -93,17 +93,18 @@ use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin};
 use rustc::infer::anon_types::AnonTypeDecl;
 use rustc::infer::type_variable::{TypeVariableOrigin};
 use rustc::middle::region;
+use rustc::middle::lang_items::TerminationTraitLangItem;
 use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode};
 use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue};
-use rustc::ty::{self, Ty, TyCtxt, Visibility};
+use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate};
 use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::maps::Providers;
 use rustc::ty::util::{Representability, IntTypeExt};
 use errors::{DiagnosticBuilder, DiagnosticId};
 use require_c_abi_if_variadic;
-use session::{CompileIncomplete, Session};
+use session::{CompileIncomplete, config, Session};
 use TypeAndSubsts;
 use lint;
 use util::common::{ErrorReported, indenter};
@@ -115,6 +116,7 @@ use std::collections::hash_map::Entry;
 use std::cmp;
 use std::fmt::Display;
 use std::mem::replace;
+use std::iter;
 use std::ops::{self, Deref};
 use syntax::abi::Abi;
 use syntax::ast;
@@ -1064,6 +1066,24 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
     }
     fcx.demand_suptype(span, ret_ty, actual_return_ty);
 
+    if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() {
+        if id == fn_id {
+            match fcx.sess().entry_type.get() {
+                Some(config::EntryMain) => {
+                    let term_id = fcx.tcx.require_lang_item(TerminationTraitLangItem);
+
+                    let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty)));
+                    let trait_ref = ty::TraitRef::new(term_id, substs);
+                    let cause = traits::ObligationCause::new(span, fn_id,
+                                                             ObligationCauseCode::MainFunctionType);
+                    inherited.register_predicate(
+                        traits::Obligation::new(cause, param_env, trait_ref.to_predicate()));
+                },
+                _ => {},
+            }
+        }
+    }
+
     (fcx, gen_ty)
 }
 
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 129511ee64c62..47022eb152dd0 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -115,7 +115,6 @@ use syntax::ast;
 use syntax::abi::Abi;
 use syntax_pos::Span;
 
-use std::iter;
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
 mod diagnostics;
@@ -200,21 +199,6 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 }
                 _ => ()
             }
-            let se_ty = tcx.mk_fn_ptr(ty::Binder(
-                tcx.mk_fn_sig(
-                    iter::empty(),
-                    tcx.mk_nil(),
-                    false,
-                    hir::Unsafety::Normal,
-                    Abi::Rust
-                )
-            ));
-
-            require_same_types(
-                tcx,
-                &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
-                se_ty,
-                tcx.mk_fn_ptr(tcx.fn_sig(main_def_id)));
         }
         _ => {
             span_bug!(main_span,
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 12e6231136e16..3a7a57fe2b83f 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -308,6 +308,7 @@
 #![feature(str_char)]
 #![feature(str_internals)]
 #![feature(str_utf16)]
+#![feature(termination_trait)]
 #![feature(test, rustc_private)]
 #![feature(thread_local)]
 #![feature(toowned_clone_into)]
@@ -499,6 +500,11 @@ mod memchr;
 // The runtime entry point and a few unstable public functions used by the
 // compiler
 pub mod rt;
+// The trait to support returning arbitrary types in the main function
+mod termination;
+
+#[unstable(feature = "termination_trait", issue = "0")]
+pub use self::termination::Termination;
 
 // Include a number of private modules that exist solely to provide
 // the rustdoc documentation for primitive types. Using `include!`
diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs
index 40b24cedcdcf5..2b75201ad2b08 100644
--- a/src/libstd/rt.rs
+++ b/src/libstd/rt.rs
@@ -26,7 +26,50 @@
 // Reexport some of our utilities which are expected by other crates.
 pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
 
-#[cfg(not(test))]
+#[cfg(not(any(test, stage0)))]
+#[lang = "start"]
+fn lang_start<T: ::termination::Termination + 'static>
+    (main: fn() -> T, argc: isize, argv: *const *const u8) -> !
+{
+    use panic;
+    use sys;
+    use sys_common;
+    use sys_common::thread_info;
+    use thread::Thread;
+    use process;
+    #[cfg(not(feature = "backtrace"))]
+    use mem;
+
+    sys::init();
+
+    process::exit(unsafe {
+        let main_guard = sys::thread::guard::init();
+        sys::stack_overflow::init();
+
+        // Next, set up the current Thread with the guard information we just
+        // created. Note that this isn't necessary in general for new threads,
+        // but we just do this to name the main thread and to give it correct
+        // info about the stack bounds.
+        let thread = Thread::new(Some("main".to_owned()));
+        thread_info::set(main_guard, thread);
+
+        // Store our args if necessary in a squirreled away location
+        sys::args::init(argc, argv);
+
+        // Let's run some code!
+        #[cfg(feature = "backtrace")]
+        let exit_code = panic::catch_unwind(|| {
+            ::sys_common::backtrace::__rust_begin_short_backtrace(move || main().report())
+        });
+        #[cfg(not(feature = "backtrace"))]
+        let exit_code = panic::catch_unwind(mem::transmute::<_, fn()>(main).report());
+
+        sys_common::cleanup();
+        exit_code.unwrap_or(101)
+    });
+}
+
+#[cfg(all(not(test), stage0))]
 #[lang = "start"]
 fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize {
     use panic;
diff --git a/src/libstd/termination.rs b/src/libstd/termination.rs
new file mode 100644
index 0000000000000..a08d3dd2d52bc
--- /dev/null
+++ b/src/libstd/termination.rs
@@ -0,0 +1,74 @@
+// Copyright 2017 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.
+
+use error::Error;
+use libc;
+
+/// A trait for implementing arbitrary return types in the `main` function.
+///
+/// The c-main function only supports to return integers as return type.
+/// So, every type implementing the `Termination` trait has to be converted
+/// to an integer.
+///
+/// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
+/// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
+#[cfg_attr(not(stage0), lang = "termination")]
+#[unstable(feature = "termination_trait", issue = "0")]
+pub trait Termination {
+    /// Is called to get the representation of the value as status code.
+    /// This status code is returned to the operating system.
+    fn report(self) -> i32;
+}
+
+#[unstable(feature = "termination_trait", issue = "0")]
+impl Termination for () {
+    fn report(self) -> i32 { libc::EXIT_SUCCESS }
+}
+
+#[unstable(feature = "termination_trait", issue = "0")]
+impl<T: Termination, E: Error> Termination for Result<T, E> {
+    fn report(self) -> i32 {
+        match self {
+            Ok(val) => val.report(),
+            Err(err) => {
+                print_error(err);
+                libc::EXIT_FAILURE
+            }
+        }
+    }
+}
+
+#[unstable(feature = "termination_trait", issue = "0")]
+fn print_error<E: Error>(err: E) {
+    eprintln!("Error: {}", err.description());
+
+    if let Some(ref err) = err.cause() {
+        eprintln!("Caused by: {}", err.description());
+    }
+}
+
+#[unstable(feature = "termination_trait", issue = "0")]
+impl Termination for ! {
+    fn report(self) -> i32 { unreachable!(); }
+}
+
+#[unstable(feature = "termination_trait", issue = "0")]
+impl Termination for bool {
+    fn report(self) -> i32 {
+        if self { libc::EXIT_SUCCESS } else { libc::EXIT_FAILURE }
+    }
+}
+
+#[unstable(feature = "termination_trait", issue = "0")]
+impl Termination for i32 {
+    fn report(self) -> i32 {
+        self
+    }
+}
diff --git a/src/test/compile-fail/termination-trait-not-satisfied.rs b/src/test/compile-fail/termination-trait-not-satisfied.rs
new file mode 100644
index 0000000000000..178a9b8cf5918
--- /dev/null
+++ b/src/test/compile-fail/termination-trait-not-satisfied.rs
@@ -0,0 +1,15 @@
+// Copyright 2017 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.
+
+struct ReturnType {}
+
+fn main() -> ReturnType { //~ ERROR `ReturnType: std::Termination` is not satisfied
+    ReturnType {}
+}
diff --git a/src/test/run-pass/termination-trait-for-empty.rs b/src/test/run-pass/termination-trait-for-empty.rs
new file mode 100644
index 0000000000000..5e534da012875
--- /dev/null
+++ b/src/test/run-pass/termination-trait-for-empty.rs
@@ -0,0 +1,13 @@
+// Copyright 2017 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.
+
+#![feature(termination_trait)]
+
+fn main() {}
diff --git a/src/test/run-pass/termination-trait-for-i32.rs b/src/test/run-pass/termination-trait-for-i32.rs
new file mode 100644
index 0000000000000..fa7cb023b447c
--- /dev/null
+++ b/src/test/run-pass/termination-trait-for-i32.rs
@@ -0,0 +1,15 @@
+// Copyright 2017 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.
+
+#![feature(termination_trait)]
+
+fn main() -> i32 {
+    0
+}
diff --git a/src/test/run-pass/termination-trait-for-result.rs b/src/test/run-pass/termination-trait-for-result.rs
new file mode 100644
index 0000000000000..751db0fb50082
--- /dev/null
+++ b/src/test/run-pass/termination-trait-for-result.rs
@@ -0,0 +1,17 @@
+// Copyright 2017 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.
+
+#![feature(termination_trait)]
+
+use std::io::Error;
+
+fn main() -> Result<(), Error> {
+    Ok(())
+}

From b452c432cd16e7d71c8311a574b0dcbbb66a6583 Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Tue, 5 Dec 2017 05:00:35 -0500
Subject: [PATCH 02/25] avoid ICE when fields are not laid out in order

---
 src/librustc/session/code_stats.rs | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs
index 118b84113a0ff..64f405e0f24b6 100644
--- a/src/librustc/session/code_stats.rs
+++ b/src/librustc/session/code_stats.rs
@@ -155,11 +155,19 @@ impl CodeStats {
 
                     // Include field alignment in output only if it caused padding injection
                     if min_offset != offset {
-                        let pad = offset - min_offset;
-                        println!("print-type-size {}padding: {} bytes",
-                                 indent, pad);
-                        println!("print-type-size {}field `.{}`: {} bytes, alignment: {} bytes",
-                                 indent, name, size, align);
+                        if offset > min_offset {
+                            let pad = offset - min_offset;
+                            println!("print-type-size {}padding: {} bytes",
+                                     indent, pad);
+                            println!("print-type-size {}field `.{}`: {} bytes, \
+                                      alignment: {} bytes",
+                                     indent, name, size, align);
+                        } else {
+                            println!("print-type-size {}field `.{}`: {} bytes, \
+                                      offset: {} bytes, \
+                                      alignment: {} bytes",
+                                     indent, name, size, offset, align);
+                        }
                     } else {
                         println!("print-type-size {}field `.{}`: {} bytes",
                                  indent, name, size);

From 19adeaa3c6482fb52a7926cba1e3842e788177eb Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Tue, 5 Dec 2017 05:03:59 -0500
Subject: [PATCH 03/25] convert print-type-sizes to use `start` instead of
 `main`

This avoids bringing in unwind machinery.
---
 src/test/ui/print_type_sizes/anonymous.rs      | 7 ++++++-
 src/test/ui/print_type_sizes/generics.rs       | 6 +++++-
 src/test/ui/print_type_sizes/multiple_types.rs | 6 +++++-
 src/test/ui/print_type_sizes/niche-filling.rs  | 5 ++++-
 src/test/ui/print_type_sizes/no_duplicates.rs  | 6 +++++-
 src/test/ui/print_type_sizes/packed.rs         | 5 ++++-
 src/test/ui/print_type_sizes/padding.rs        | 6 +++++-
 src/test/ui/print_type_sizes/repr-align.rs     | 5 ++++-
 src/test/ui/print_type_sizes/uninhabited.rs    | 5 ++++-
 src/test/ui/print_type_sizes/variants.rs       | 6 +++++-
 10 files changed, 47 insertions(+), 10 deletions(-)

diff --git a/src/test/ui/print_type_sizes/anonymous.rs b/src/test/ui/print_type_sizes/anonymous.rs
index cf0bedee2ab3e..56c05f566c9ab 100644
--- a/src/test/ui/print_type_sizes/anonymous.rs
+++ b/src/test/ui/print_type_sizes/anonymous.rs
@@ -15,7 +15,10 @@
 // that one cannot control the sizes of these types with the same sort
 // of enum-variant manipulation tricks.
 
-pub fn main() {
+#![feature(start)]
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _byte: u8 = 0;
     let _word: usize = 0;
     let _tuple: (u8, usize)= (0, 0);
@@ -25,4 +28,6 @@ pub fn main() {
 
     fn id(x: u8) -> u8 { x };
     fn bye(_: u8) -> ! { loop { } }
+
+    0
 }
diff --git a/src/test/ui/print_type_sizes/generics.rs b/src/test/ui/print_type_sizes/generics.rs
index 7bc4822359e2a..d0e5bd1d92abf 100644
--- a/src/test/ui/print_type_sizes/generics.rs
+++ b/src/test/ui/print_type_sizes/generics.rs
@@ -15,6 +15,8 @@
 // monomorphized, in the MIR of the original function in which they
 // occur, to have their size reported.
 
+#![feature(start)]
+
 // In an ad-hoc attempt to avoid the injection of unwinding code
 // (which clutters the output of `-Z print-type-sizes` with types from
 // `unwind::libunwind`):
@@ -66,9 +68,11 @@ pub fn f1<T:Copy>(x: T) {
         Pair::new(FiftyBytes::new(), FiftyBytes::new());
 }
 
-pub fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _b: Pair<u8> = Pair::new(0, 0);
     let _s: Pair<SevenBytes> = Pair::new(SevenBytes::new(), SevenBytes::new());
     let _z: ZeroSized = ZeroSized;
     f1::<SevenBytes>(SevenBytes::new());
+    0
 }
diff --git a/src/test/ui/print_type_sizes/multiple_types.rs b/src/test/ui/print_type_sizes/multiple_types.rs
index a9f294490159d..a50b28f3c4952 100644
--- a/src/test/ui/print_type_sizes/multiple_types.rs
+++ b/src/test/ui/print_type_sizes/multiple_types.rs
@@ -14,6 +14,8 @@
 // This file illustrates that when multiple structural types occur in
 // a function, every one of them is included in the output.
 
+#![feature(start)]
+
 pub struct SevenBytes([u8;  7]);
 pub struct FiftyBytes([u8; 50]);
 
@@ -22,8 +24,10 @@ pub enum Enum {
     Large(FiftyBytes),
 }
 
-pub fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _e: Enum;
     let _f: FiftyBytes;
     let _s: SevenBytes;
+    0
 }
diff --git a/src/test/ui/print_type_sizes/niche-filling.rs b/src/test/ui/print_type_sizes/niche-filling.rs
index 08b58704022ec..7f234e243e926 100644
--- a/src/test/ui/print_type_sizes/niche-filling.rs
+++ b/src/test/ui/print_type_sizes/niche-filling.rs
@@ -21,6 +21,7 @@
 // aligned (while on most it is 8-byte aligned) and so the resulting
 // padding and overall computed sizes can be quite different.
 
+#![feature(start)]
 #![feature(nonzero)]
 #![allow(dead_code)]
 
@@ -76,7 +77,8 @@ pub enum Enum4<A, B, C, D> {
     Four(D)
 }
 
-pub fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _x: MyOption<NonZero<u32>> = Default::default();
     let _y: EmbeddedDiscr = Default::default();
     let _z: MyOption<IndirectNonZero<u32>> = Default::default();
@@ -87,4 +89,5 @@ pub fn main() {
     let _e: Enum4<(), char, (), ()> = Enum4::One(());
     let _f: Enum4<(), (), bool, ()> = Enum4::One(());
     let _g: Enum4<(), (), (), MyOption<u8>> = Enum4::One(());
+    0
 }
diff --git a/src/test/ui/print_type_sizes/no_duplicates.rs b/src/test/ui/print_type_sizes/no_duplicates.rs
index 40c41aae9109d..d9b90260364b2 100644
--- a/src/test/ui/print_type_sizes/no_duplicates.rs
+++ b/src/test/ui/print_type_sizes/no_duplicates.rs
@@ -15,12 +15,16 @@
 // (even if multiple functions), it is only printed once in the
 // print-type-sizes output.
 
+#![feature(start)]
+
 pub struct SevenBytes([u8; 7]);
 
 pub fn f1() {
     let _s: SevenBytes = SevenBytes([0; 7]);
 }
 
-pub fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _s: SevenBytes = SevenBytes([0; 7]);
+    0
 }
diff --git a/src/test/ui/print_type_sizes/packed.rs b/src/test/ui/print_type_sizes/packed.rs
index 1ee6395ac6cba..a4288f67899a2 100644
--- a/src/test/ui/print_type_sizes/packed.rs
+++ b/src/test/ui/print_type_sizes/packed.rs
@@ -20,6 +20,7 @@
 // padding and overall computed sizes can be quite different.
 
 #![allow(dead_code)]
+#![feature(start)]
 
 #[derive(Default)]
 #[repr(packed)]
@@ -42,7 +43,9 @@ struct Padded {
     d: u8,
 }
 
-pub fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _c: Packed = Default::default();
     let _d: Padded = Default::default();
+    0
 }
diff --git a/src/test/ui/print_type_sizes/padding.rs b/src/test/ui/print_type_sizes/padding.rs
index b3cd213234305..b4661efdd27a2 100644
--- a/src/test/ui/print_type_sizes/padding.rs
+++ b/src/test/ui/print_type_sizes/padding.rs
@@ -19,6 +19,7 @@
 // aligned (while on most it is 8-byte aligned) and so the resulting
 // padding and overall computed sizes can be quite different.
 
+#![feature(start)]
 #![allow(dead_code)]
 
 struct S {
@@ -37,4 +38,7 @@ enum E2 {
     B(S),
 }
 
-fn main() { }
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    0
+}
diff --git a/src/test/ui/print_type_sizes/repr-align.rs b/src/test/ui/print_type_sizes/repr-align.rs
index 1bf76da811552..108b8dbba0198 100644
--- a/src/test/ui/print_type_sizes/repr-align.rs
+++ b/src/test/ui/print_type_sizes/repr-align.rs
@@ -20,6 +20,7 @@
 // padding and overall computed sizes can be quite different.
 #![feature(attr_literals)]
 #![feature(repr_align)]
+#![feature(start)]
 #![allow(dead_code)]
 
 #[repr(align(16))]
@@ -39,6 +40,8 @@ struct S {
     d: i8,
 }
 
-fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _s: S = Default::default();
+    0
 }
diff --git a/src/test/ui/print_type_sizes/uninhabited.rs b/src/test/ui/print_type_sizes/uninhabited.rs
index fae6cd4009c30..4d0396903e555 100644
--- a/src/test/ui/print_type_sizes/uninhabited.rs
+++ b/src/test/ui/print_type_sizes/uninhabited.rs
@@ -12,8 +12,11 @@
 // must-compile-successfully
 
 #![feature(never_type)]
+#![feature(start)]
 
-pub fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _x: Option<!> = None;
     let _y: Result<u32, !> = Ok(42);
+    0
 }
diff --git a/src/test/ui/print_type_sizes/variants.rs b/src/test/ui/print_type_sizes/variants.rs
index 2725bb09b4bc0..e4d54162e73af 100644
--- a/src/test/ui/print_type_sizes/variants.rs
+++ b/src/test/ui/print_type_sizes/variants.rs
@@ -19,6 +19,8 @@
 // 2. For an enum, the print-type-sizes output will also include the
 //    size of each variant.
 
+#![feature(start)]
+
 pub struct SevenBytes([u8;  7]);
 pub struct FiftyBytes([u8; 50]);
 
@@ -27,6 +29,8 @@ pub enum Enum {
     Large(FiftyBytes),
 }
 
-pub fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _e: Enum;
+    0
 }

From 011c9eac357ea4a02a4e4f821d0cb1e043b0227d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Tue, 5 Dec 2017 12:10:47 +0100
Subject: [PATCH 04/25] Fixes compile bug caused by upstream changes

---
 src/librustc_mir/monomorphize/collector.rs | 2 +-
 src/librustc_trans/base.rs                 | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 056c6989abac8..afd895eb7ca0f 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -1032,7 +1032,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> {
         // late-bound regions, since late-bound
         // regions must appear in the argument
         // listing.
-        let main_ret_ty = self.tcx.no_late_bound_regions(&main_ret_ty).unwrap();
+        let main_ret_ty = main_ret_ty.no_late_bound_regions().unwrap();
 
         let start_instance = Instance::resolve(
             self.tcx,
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index b2d516e786883..3955171f93980 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -563,7 +563,7 @@ fn maybe_create_entry_wrapper(ccx: &CrateContext) {
         // late-bound regions, since late-bound
         // regions must appear in the argument
         // listing.
-        let main_ret_ty = ccx.tcx().no_late_bound_regions(&main_ret_ty).unwrap();
+        let main_ret_ty = main_ret_ty.no_late_bound_regions().unwrap();
 
         if declare::get_defined_value(ccx, "main").is_some() {
             // FIXME: We should be smart and show a better diagnostic here.

From 99a108c03654cd9d2df21223eb55a5dfd6552cb8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Thu, 21 Dec 2017 12:03:01 +0100
Subject: [PATCH 05/25] Fixes compilation errors and adds proposed improvements

---
 src/librustc_mir/monomorphize/collector.rs    | 5 ++---
 src/librustc_mir/monomorphize/partitioning.rs | 7 ++-----
 src/libstd/termination.rs                     | 2 ++
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index afd895eb7ca0f..ccb648cd92988 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -195,7 +195,6 @@ use rustc::hir::map as hir_map;
 use rustc::hir::def_id::DefId;
 use rustc::middle::const_val::ConstVal;
 use rustc::middle::lang_items::{ExchangeMallocFnLangItem,StartFnLangItem};
-use rustc::middle::trans::TransItem;
 use rustc::traits;
 use rustc::ty::subst::{Substs, Kind};
 use rustc::ty::{self, TypeFoldable, Ty, TyCtxt};
@@ -1001,7 +1000,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> {
             debug!("RootCollector::push_if_root: found root def_id={:?}", def_id);
 
             let instance = Instance::mono(self.tcx, def_id);
-            self.output.push(create_fn_trans_item(instance));
+            self.output.push(create_fn_mono_item(instance));
 
             self.push_extra_entry_roots(def_id);
         }
@@ -1041,7 +1040,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> {
             self.tcx.mk_substs(iter::once(Kind::from(main_ret_ty)))
         ).unwrap();
 
-        self.output.push(create_fn_trans_item(start_instance));
+        self.output.push(create_fn_mono_item(start_instance));
     }
 }
 
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index e34698da4dafb..1a4849ac199a0 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -106,8 +106,7 @@ use monomorphize::collector::InliningMap;
 use rustc::dep_graph::WorkProductId;
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::DefPathData;
-use rustc::middle::lang_items::StartFnLangItem;
-use rustc::middle::trans::{Linkage, Visibility};
+use rustc::mir::mono::{Linkage, Visibility};
 use rustc::ty::{self, TyCtxt, InstanceDef};
 use rustc::ty::item_path::characteristic_def_id_of_type;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
@@ -313,11 +312,9 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     MonoItem::Fn(ref instance) => {
                         let visibility = match instance.def {
                             InstanceDef::Item(def_id) => {
-                                let start_def_id = tcx.lang_items().require(StartFnLangItem);
-
                                 // If we encounter the lang start item, we set the visibility to
                                 // default.
-                                if start_def_id == Ok(def_id) {
+                                if tcx.lang_items().start_fn() == Some(def_id) {
                                     Visibility::Default
                                 } else if def_id.is_local() {
                                     if tcx.is_exported_symbol(def_id) {
diff --git a/src/libstd/termination.rs b/src/libstd/termination.rs
index a08d3dd2d52bc..5eeaa542b41dd 100644
--- a/src/libstd/termination.rs
+++ b/src/libstd/termination.rs
@@ -21,6 +21,8 @@ use libc;
 /// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
 #[cfg_attr(not(stage0), lang = "termination")]
 #[unstable(feature = "termination_trait", issue = "0")]
+#[rustc_on_unimplemented =
+  "`main` can only return types that implement {Termination}, not `{Self}`"]
 pub trait Termination {
     /// Is called to get the representation of the value as status code.
     /// This status code is returned to the operating system.

From f842f7547ec1d58261426447cd87d6e0362d9d9a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Thu, 21 Dec 2017 13:07:50 +0100
Subject: [PATCH 06/25] Fixes tests

---
 src/librustc_typeck/lib.rs                 | 21 +++++++++++++++++++++
 src/test/compile-fail/E0580.rs             | 11 -----------
 src/test/compile-fail/main-wrong-type-2.rs |  3 ++-
 3 files changed, 23 insertions(+), 12 deletions(-)
 delete mode 100644 src/test/compile-fail/E0580.rs

diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 47022eb152dd0..f11328b2424ed 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -115,6 +115,8 @@ use syntax::ast;
 use syntax::abi::Abi;
 use syntax_pos::Span;
 
+use std::iter;
+
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
 mod diagnostics;
@@ -199,6 +201,25 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 }
                 _ => ()
             }
+
+            let actual = tcx.fn_sig(main_def_id);
+
+            let se_ty = tcx.mk_fn_ptr(ty::Binder(
+                tcx.mk_fn_sig(
+                    iter::empty(),
+                    // the return type is checked in `check_fn`
+                    actual.output().skip_binder(),
+                    false,
+                    hir::Unsafety::Normal,
+                    Abi::Rust
+                )
+            ));
+
+            require_same_types(
+                tcx,
+                &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
+                se_ty,
+                tcx.mk_fn_ptr(actual));
         }
         _ => {
             span_bug!(main_span,
diff --git a/src/test/compile-fail/E0580.rs b/src/test/compile-fail/E0580.rs
deleted file mode 100644
index a2ef7da78a843..0000000000000
--- a/src/test/compile-fail/E0580.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2016 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.
-
-fn main() -> i32 { 0 } //~ ERROR E0580
diff --git a/src/test/compile-fail/main-wrong-type-2.rs b/src/test/compile-fail/main-wrong-type-2.rs
index 9d74d1a90493b..a63162cf73d1c 100644
--- a/src/test/compile-fail/main-wrong-type-2.rs
+++ b/src/test/compile-fail/main-wrong-type-2.rs
@@ -7,8 +7,9 @@
 // <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.
+#![feature(termination_trait)]
 
 fn main() -> char {
-//~^ ERROR: main function has wrong type [E0580]
+//~^ ERROR: the trait bound `char: std::Termination` is not satisfied
     ' '
 }

From 823273421695d7a07e53cd48206c283f35163d52 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Thu, 21 Dec 2017 14:20:03 +0100
Subject: [PATCH 07/25] Fall back to main -> () when termination trait language
 item is not enabled

---
 src/librustc_typeck/check/mod.rs | 33 ++++++++++++++++++--------------
 src/librustc_typeck/lib.rs       | 11 +++++++++--
 2 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 159340d19a7fe..e99633519f4d8 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1066,20 +1066,25 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
     }
     fcx.demand_suptype(span, ret_ty, actual_return_ty);
 
-    if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() {
-        if id == fn_id {
-            match fcx.sess().entry_type.get() {
-                Some(config::EntryMain) => {
-                    let term_id = fcx.tcx.require_lang_item(TerminationTraitLangItem);
-
-                    let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty)));
-                    let trait_ref = ty::TraitRef::new(term_id, substs);
-                    let cause = traits::ObligationCause::new(span, fn_id,
-                                                             ObligationCauseCode::MainFunctionType);
-                    inherited.register_predicate(
-                        traits::Obligation::new(cause, param_env, trait_ref.to_predicate()));
-                },
-                _ => {},
+    // If the termination trait language item is activated, check that the main return type
+    // implements the termination trait.
+    if fcx.tcx.lang_items().termination().is_some() {
+        if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() {
+            if id == fn_id {
+                match fcx.sess().entry_type.get() {
+                    Some(config::EntryMain) => {
+                        let term_id = fcx.tcx.require_lang_item(TerminationTraitLangItem);
+
+                        let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty)));
+                        let trait_ref = ty::TraitRef::new(term_id, substs);
+                        let cause = traits::ObligationCause::new(
+                            span, fn_id, ObligationCauseCode::MainFunctionType);
+
+                        inherited.register_predicate(
+                            traits::Obligation::new(cause, param_env, trait_ref.to_predicate()));
+                    },
+                    _ => {},
+                }
             }
         }
     }
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index f11328b2424ed..f02998f7edf74 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -203,12 +203,19 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
 
             let actual = tcx.fn_sig(main_def_id);
+            let expected_return_type = if tcx.lang_items().termination().is_some() {
+                // we take the return type of the given main function, the real check is done
+                // in `check_fn`
+                actual.output().skip_binder()
+            } else {
+                // standard () main return type
+                tcx.mk_nil()
+            };
 
             let se_ty = tcx.mk_fn_ptr(ty::Binder(
                 tcx.mk_fn_sig(
                     iter::empty(),
-                    // the return type is checked in `check_fn`
-                    actual.output().skip_binder(),
+                    expected_return_type,
                     false,
                     hir::Unsafety::Normal,
                     Abi::Rust

From 267800a7c0834dd8ca93a82a20cb0cdd9e7dc025 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Thu, 21 Dec 2017 16:37:14 +0100
Subject: [PATCH 08/25] New generated main returns void

---
 src/test/codegen/abi-main-signature-16bit-c-int.rs | 2 +-
 src/test/codegen/abi-main-signature-32bit-c-int.rs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/test/codegen/abi-main-signature-16bit-c-int.rs b/src/test/codegen/abi-main-signature-16bit-c-int.rs
index fbe2fd10e7a14..55863ab163314 100644
--- a/src/test/codegen/abi-main-signature-16bit-c-int.rs
+++ b/src/test/codegen/abi-main-signature-16bit-c-int.rs
@@ -29,4 +29,4 @@
 fn main() {
 }
 
-// CHECK: define i16 @main(i16, i8**)
+// CHECK: define void @main(i16, i8**)
diff --git a/src/test/codegen/abi-main-signature-32bit-c-int.rs b/src/test/codegen/abi-main-signature-32bit-c-int.rs
index 3139749dfcb06..d7c70354ee0cc 100644
--- a/src/test/codegen/abi-main-signature-32bit-c-int.rs
+++ b/src/test/codegen/abi-main-signature-32bit-c-int.rs
@@ -17,4 +17,4 @@
 fn main() {
 }
 
-// CHECK: define i32 @main(i32, i8**)
+// CHECK: define void @main(i32, i8**)

From 8f539b09df7f47c3b962c28179803ae0289bfe5e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Thu, 21 Dec 2017 17:25:36 +0100
Subject: [PATCH 09/25] Fixes codegen-units tests

---
 .../cross-crate-generic-functions.rs          | 19 ++++++++++++++++++
 .../cross-crate-trait-method.rs               | 19 ++++++++++++++++++
 .../drop_in_place_intrinsic.rs                | 19 ++++++++++++++++++
 .../item-collection/function-as-argument.rs   | 19 ++++++++++++++++++
 .../item-collection/generic-drop-glue.rs      | 19 ++++++++++++++++++
 .../item-collection/generic-functions.rs      | 19 ++++++++++++++++++
 .../item-collection/generic-impl.rs           | 20 ++++++++++++++++++-
 .../impl-in-non-instantiated-generic.rs       | 19 ++++++++++++++++++
 .../instantiation-through-vtable.rs           | 19 ++++++++++++++++++
 .../items-within-generic-items.rs             | 19 ++++++++++++++++++
 .../item-collection/non-generic-drop-glue.rs  | 19 ++++++++++++++++++
 .../item-collection/non-generic-functions.rs  | 19 ++++++++++++++++++
 .../item-collection/static-init.rs            | 20 +++++++++++++++++++
 .../item-collection/statics-and-consts.rs     | 19 ++++++++++++++++++
 .../item-collection/trait-implementations.rs  | 19 ++++++++++++++++++
 .../trait-method-as-argument.rs               | 19 ++++++++++++++++++
 .../trait-method-default-impl.rs              | 19 ++++++++++++++++++
 .../item-collection/transitive-drop-glue.rs   | 19 ++++++++++++++++++
 .../item-collection/tuple-drop-glue.rs        | 19 ++++++++++++++++++
 .../codegen-units/item-collection/unsizing.rs | 19 ++++++++++++++++++
 .../partitioning/vtable-through-const.rs      | 19 ++++++++++++++++++
 21 files changed, 400 insertions(+), 1 deletion(-)

diff --git a/src/test/codegen-units/item-collection/cross-crate-generic-functions.rs b/src/test/codegen-units/item-collection/cross-crate-generic-functions.rs
index eb4f9e8e28e2d..411f3da9182bd 100644
--- a/src/test/codegen-units/item-collection/cross-crate-generic-functions.rs
+++ b/src/test/codegen-units/item-collection/cross-crate-generic-functions.rs
@@ -16,6 +16,25 @@
 // aux-build:cgu_generic_function.rs
 extern crate cgu_generic_function;
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ cross_crate_generic_functions0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ cross_crate_generic_functions0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ cross_crate_generic_functions0[Internal]
 //~ TRANS_ITEM fn cross_crate_generic_functions::main[0]
 fn main()
 {
diff --git a/src/test/codegen-units/item-collection/cross-crate-trait-method.rs b/src/test/codegen-units/item-collection/cross-crate-trait-method.rs
index 195125793be8a..a269b6da230d1 100644
--- a/src/test/codegen-units/item-collection/cross-crate-trait-method.rs
+++ b/src/test/codegen-units/item-collection/cross-crate-trait-method.rs
@@ -18,6 +18,25 @@ extern crate cgu_export_trait_method;
 
 use cgu_export_trait_method::Trait;
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ cross_crate_trait_method0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ cross_crate_trait_method0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ cross_crate_trait_method0[Internal]
 //~ TRANS_ITEM fn cross_crate_trait_method::main[0]
 fn main()
 {
diff --git a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
index b8033b88fb75e..88888afa69300 100644
--- a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
+++ b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
@@ -20,6 +20,25 @@ impl Drop for StructWithDtor {
     fn drop(&mut self) {}
 }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ drop_in_place_intrinsic0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ drop_in_place_intrinsic0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ drop_in_place_intrinsic0[Internal]
 //~ TRANS_ITEM fn drop_in_place_intrinsic::main[0]
 fn main() {
 
diff --git a/src/test/codegen-units/item-collection/function-as-argument.rs b/src/test/codegen-units/item-collection/function-as-argument.rs
index c3d46ff5314fe..3fb25d9b2a0da 100644
--- a/src/test/codegen-units/item-collection/function-as-argument.rs
+++ b/src/test/codegen-units/item-collection/function-as-argument.rs
@@ -23,6 +23,25 @@ fn take_fn_pointer<T1, T2>(f: fn(T1, T2), x: T1, y: T2) {
     (f)(x, y)
 }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ function_as_argument0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ function_as_argument0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ function_as_argument0[Internal]
 //~ TRANS_ITEM fn function_as_argument::main[0]
 fn main() {
 
diff --git a/src/test/codegen-units/item-collection/generic-drop-glue.rs b/src/test/codegen-units/item-collection/generic-drop-glue.rs
index 65936d12e316f..0d08611d1cc96 100644
--- a/src/test/codegen-units/item-collection/generic-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/generic-drop-glue.rs
@@ -53,6 +53,25 @@ impl Drop for NonGenericWithDrop {
     fn drop(&mut self) {}
 }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ generic_drop_glue0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ generic_drop_glue0[Internal]
 //~ TRANS_ITEM fn generic_drop_glue::main[0]
 fn main() {
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<i8, char>> @@ generic_drop_glue0[Internal]
diff --git a/src/test/codegen-units/item-collection/generic-functions.rs b/src/test/codegen-units/item-collection/generic-functions.rs
index afe6ffc8bfe03..41133f0f797db 100644
--- a/src/test/codegen-units/item-collection/generic-functions.rs
+++ b/src/test/codegen-units/item-collection/generic-functions.rs
@@ -31,6 +31,25 @@ pub fn lifetime_only<'a>(a: &'a u32) -> &'a u32 {
     a
 }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ generic_functions0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ generic_functions0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ generic_functions0[Internal]
 //~ TRANS_ITEM fn generic_functions::main[0]
 fn main() {
     //~ TRANS_ITEM fn generic_functions::foo1[0]<i32>
diff --git a/src/test/codegen-units/item-collection/generic-impl.rs b/src/test/codegen-units/item-collection/generic-impl.rs
index 14316a557328b..6212ad0417c74 100644
--- a/src/test/codegen-units/item-collection/generic-impl.rs
+++ b/src/test/codegen-units/item-collection/generic-impl.rs
@@ -50,7 +50,25 @@ impl<'a> LifeTimeOnly<'a> {
     pub fn non_instantiated<T>(&self) {}
 }
 
-
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ generic_impl0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ generic_impl0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ generic_impl0[Internal]
 //~ TRANS_ITEM fn generic_impl::main[0]
 fn main() {
     //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<i32>
diff --git a/src/test/codegen-units/item-collection/impl-in-non-instantiated-generic.rs b/src/test/codegen-units/item-collection/impl-in-non-instantiated-generic.rs
index c43c254f33911..aa3de2095fbde 100644
--- a/src/test/codegen-units/item-collection/impl-in-non-instantiated-generic.rs
+++ b/src/test/codegen-units/item-collection/impl-in-non-instantiated-generic.rs
@@ -28,6 +28,25 @@ pub fn generic_function<T>(x: T) -> (T, i32) {
     (x, 0)
 }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ impl_in_non_instantiated_generic0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ impl_in_non_instantiated_generic0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ impl_in_non_instantiated_generic0[Internal]
 //~ TRANS_ITEM fn impl_in_non_instantiated_generic::main[0]
 fn main() {
     0i64.foo();
diff --git a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs
index e32366d15c337..8b46984f72fce 100644
--- a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs
+++ b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs
@@ -28,6 +28,25 @@ impl<T> Trait for Struct<T> {
     fn bar(&self) {}
 }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ instantiation_through_vtable0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ instantiation_through_vtable0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ instantiation_through_vtable0[Internal]
 //~ TRANS_ITEM fn instantiation_through_vtable::main[0]
 fn main() {
     let s1 = Struct { _a: 0u32 };
diff --git a/src/test/codegen-units/item-collection/items-within-generic-items.rs b/src/test/codegen-units/item-collection/items-within-generic-items.rs
index 75d842d3c0bfc..abd79dd39d628 100644
--- a/src/test/codegen-units/item-collection/items-within-generic-items.rs
+++ b/src/test/codegen-units/item-collection/items-within-generic-items.rs
@@ -31,6 +31,25 @@ fn generic_fn<T>(a: T) -> (T, i32) {
     return (a, x + nested_fn(0));
 }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ items_within_generic_items0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ items_within_generic_items0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ items_within_generic_items0[Internal]
 //~ TRANS_ITEM fn items_within_generic_items::main[0]
 fn main() {
     //~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<i64>
diff --git a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs
index 5765f230e8bd4..df89b3fca9f11 100644
--- a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs
@@ -42,6 +42,25 @@ enum EnumNoDrop {
     A(i32)
 }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ non_generic_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ non_generic_drop_glue0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ non_generic_drop_glue0[Internal]
 //~ TRANS_ITEM fn non_generic_drop_glue::main[0]
 fn main() {
     let _ = StructWithDrop { x: 0 }.x;
diff --git a/src/test/codegen-units/item-collection/non-generic-functions.rs b/src/test/codegen-units/item-collection/non-generic-functions.rs
index 26f9eb11876cb..6f254ffde60b0 100644
--- a/src/test/codegen-units/item-collection/non-generic-functions.rs
+++ b/src/test/codegen-units/item-collection/non-generic-functions.rs
@@ -69,6 +69,25 @@ impl Struct {
     }
 }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ non_generic_functions0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ non_generic_functions0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ non_generic_functions0[Internal]
 //~ TRANS_ITEM fn non_generic_functions::main[0]
 fn main() {
     foo();
diff --git a/src/test/codegen-units/item-collection/static-init.rs b/src/test/codegen-units/item-collection/static-init.rs
index 3c9dcf32e0c78..9921c9b84d2f1 100644
--- a/src/test/codegen-units/item-collection/static-init.rs
+++ b/src/test/codegen-units/item-collection/static-init.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Zprint-trans-items=eager
+// ignore-tidy-linelength
 
 pub static FN : fn() = foo::<i32>;
 
@@ -19,4 +20,23 @@ pub fn foo<T>() { }
 
 fn main() { }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ static_init0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ static_init0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ static_init0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ static_init0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ static_init0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ static_init0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ static_init0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ static_init0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ static_init0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ static_init0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ static_init0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ static_init0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ static_init0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ static_init0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ static_init0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ static_init0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ static_init0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ static_init0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ static_init0[Internal]
 //~ TRANS_ITEM fn static_init::main[0]
diff --git a/src/test/codegen-units/item-collection/statics-and-consts.rs b/src/test/codegen-units/item-collection/statics-and-consts.rs
index 89bc620b7c552..bd3dcd2fe79a7 100644
--- a/src/test/codegen-units/item-collection/statics-and-consts.rs
+++ b/src/test/codegen-units/item-collection/statics-and-consts.rs
@@ -59,4 +59,23 @@ fn main() {
 //~ TRANS_ITEM static statics_and_consts::foo[0]::STATIC2[1]
 //~ TRANS_ITEM static statics_and_consts::foo[0]::STATIC2[2]
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ statics_and_consts0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ statics_and_consts0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ statics_and_consts0[Internal]
 //~ TRANS_ITEM fn statics_and_consts::main[0]
diff --git a/src/test/codegen-units/item-collection/trait-implementations.rs b/src/test/codegen-units/item-collection/trait-implementations.rs
index e8a7d8f25b22c..e8f727cbd12bd 100644
--- a/src/test/codegen-units/item-collection/trait-implementations.rs
+++ b/src/test/codegen-units/item-collection/trait-implementations.rs
@@ -55,6 +55,25 @@ impl<T> SomeGenericTrait<T> for f32 {
     fn bar<T2>(&self, _: T, _: T2) {}
 }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ trait_implementations0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ trait_implementations0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ trait_implementations0[Internal]
 //~ TRANS_ITEM fn trait_implementations::main[0]
 fn main() {
    //~ TRANS_ITEM fn trait_implementations::{{impl}}[1]::bar[0]<char>
diff --git a/src/test/codegen-units/item-collection/trait-method-as-argument.rs b/src/test/codegen-units/item-collection/trait-method-as-argument.rs
index 21c9c254e51cf..f6e3c1cf9747c 100644
--- a/src/test/codegen-units/item-collection/trait-method-as-argument.rs
+++ b/src/test/codegen-units/item-collection/trait-method-as-argument.rs
@@ -36,6 +36,25 @@ fn take_foo_mut<T, F: FnMut(T) -> T>(mut f: F, arg: T) -> T {
     (f)(arg)
 }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ trait_method_as_argument0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ trait_method_as_argument0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ trait_method_as_argument0[Internal]
 //~ TRANS_ITEM fn trait_method_as_argument::main[0]
 fn main() {
     //~ TRANS_ITEM fn trait_method_as_argument::take_foo_once[0]<u32, fn(u32) -> u32>
diff --git a/src/test/codegen-units/item-collection/trait-method-default-impl.rs b/src/test/codegen-units/item-collection/trait-method-default-impl.rs
index 5b24a219f354b..6e6793076da59 100644
--- a/src/test/codegen-units/item-collection/trait-method-default-impl.rs
+++ b/src/test/codegen-units/item-collection/trait-method-default-impl.rs
@@ -46,6 +46,25 @@ impl<T1> SomeGenericTrait<T1> for u32 {
     // since nothing is monomorphic here, nothing should be generated unless used somewhere.
 }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ trait_method_default_impl0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ trait_method_default_impl0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ trait_method_default_impl0[Internal]
 //~ TRANS_ITEM fn trait_method_default_impl::main[0]
 fn main() {
     //~ TRANS_ITEM fn trait_method_default_impl::SomeTrait[0]::bar[0]<i8, char>
diff --git a/src/test/codegen-units/item-collection/transitive-drop-glue.rs b/src/test/codegen-units/item-collection/transitive-drop-glue.rs
index be560690e5190..e966b9f92e441 100644
--- a/src/test/codegen-units/item-collection/transitive-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/transitive-drop-glue.rs
@@ -34,6 +34,25 @@ impl<T> Drop for LeafGen<T> {
     fn drop(&mut self) {}
 }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ transitive_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ transitive_drop_glue0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ transitive_drop_glue0[Internal]
 //~ TRANS_ITEM fn transitive_drop_glue::main[0]
 fn main() {
 
diff --git a/src/test/codegen-units/item-collection/tuple-drop-glue.rs b/src/test/codegen-units/item-collection/tuple-drop-glue.rs
index ad1475a73f7cc..93b3f832e99cb 100644
--- a/src/test/codegen-units/item-collection/tuple-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/tuple-drop-glue.rs
@@ -22,6 +22,25 @@ impl Drop for Dropped {
     fn drop(&mut self) {}
 }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ tuple_drop_glue0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ tuple_drop_glue0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ tuple_drop_glue0[Internal]
 //~ TRANS_ITEM fn tuple_drop_glue::main[0]
 fn main() {
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue0[Internal]
diff --git a/src/test/codegen-units/item-collection/unsizing.rs b/src/test/codegen-units/item-collection/unsizing.rs
index d7e457cde8a90..4c07177b7396d 100644
--- a/src/test/codegen-units/item-collection/unsizing.rs
+++ b/src/test/codegen-units/item-collection/unsizing.rs
@@ -53,6 +53,25 @@ struct Wrapper<T: ?Sized>(*const T);
 
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ unsizing0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ unsizing0[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ unsizing0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ unsizing0[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ unsizing0[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ unsizing0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ unsizing0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ unsizing0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ unsizing0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ unsizing0[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ unsizing0[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ unsizing0[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ unsizing0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ unsizing0[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ unsizing0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ unsizing0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ unsizing0[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ unsizing0[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ unsizing0[Internal]
 //~ TRANS_ITEM fn unsizing::main[0]
 fn main()
 {
diff --git a/src/test/codegen-units/partitioning/vtable-through-const.rs b/src/test/codegen-units/partitioning/vtable-through-const.rs
index 302f9312b5709..05c36810c1f25 100644
--- a/src/test/codegen-units/partitioning/vtable-through-const.rs
+++ b/src/test/codegen-units/partitioning/vtable-through-const.rs
@@ -68,6 +68,25 @@ mod mod1 {
     pub const ID_I64: fn(i64) -> i64 = id::<i64>;
 }
 
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ std-rt.volatile[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ std-rt.volatile[Internal]
+//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ std-rt.volatile[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ std-rt.volatile[Internal]
+//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ std-rt.volatile[Internal]
+//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ std-panicking.volatile[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ std-rt.volatile[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ std-rt.volatile[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ std-rt.volatile[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ std-panicking.volatile[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ std-panicking.volatile[Internal]
+//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ std-rt.volatile[Internal]
+//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ std-panic.volatile[External]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ std-panicking.volatile[Internal]
+//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ std-panicking.volatile[External]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ std-sys_common-backtrace.volatile[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ std-panicking.volatile[Internal]
+//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ std-rt.volatile[External]
+//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ std-sys_common-backtrace.volatile[External]
 //~ TRANS_ITEM fn vtable_through_const::main[0] @@ vtable_through_const[Internal]
 fn main() {
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ vtable_through_const[Internal]

From c7a57d285517f1e22d34ace98fbb0c64e40b12bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Fri, 22 Dec 2017 01:11:57 +0100
Subject: [PATCH 10/25] Adds termination_trait feature gate

---
 src/librustc_typeck/check/mod.rs              | 38 +++++++++----------
 src/librustc_typeck/lib.rs                    |  3 +-
 src/libstd/lib.rs                             |  2 +-
 src/libstd/termination.rs                     | 14 +++----
 src/libsyntax/feature_gate.rs                 |  3 ++
 .../feature-gate-termination_trait.rs         | 13 +++++++
 .../termination-trait-not-satisfied.rs        |  2 +
 7 files changed, 47 insertions(+), 28 deletions(-)
 create mode 100644 src/test/compile-fail/feature-gate-termination_trait.rs

diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index e99633519f4d8..7a49c3549abdf 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -93,7 +93,6 @@ use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin};
 use rustc::infer::anon_types::AnonTypeDecl;
 use rustc::infer::type_variable::{TypeVariableOrigin};
 use rustc::middle::region;
-use rustc::middle::lang_items::TerminationTraitLangItem;
 use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode};
 use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue};
@@ -1066,24 +1065,25 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
     }
     fcx.demand_suptype(span, ret_ty, actual_return_ty);
 
-    // If the termination trait language item is activated, check that the main return type
-    // implements the termination trait.
-    if fcx.tcx.lang_items().termination().is_some() {
-        if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() {
-            if id == fn_id {
-                match fcx.sess().entry_type.get() {
-                    Some(config::EntryMain) => {
-                        let term_id = fcx.tcx.require_lang_item(TerminationTraitLangItem);
-
-                        let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty)));
-                        let trait_ref = ty::TraitRef::new(term_id, substs);
-                        let cause = traits::ObligationCause::new(
-                            span, fn_id, ObligationCauseCode::MainFunctionType);
-
-                        inherited.register_predicate(
-                            traits::Obligation::new(cause, param_env, trait_ref.to_predicate()));
-                    },
-                    _ => {},
+    if fcx.tcx.sess.features.borrow().termination_trait {
+        // If the termination trait language item is activated, check that the main return type
+        // implements the termination trait.
+        if let Some(term_id) = fcx.tcx.lang_items().termination() {
+            if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() {
+                if id == fn_id {
+                    match fcx.sess().entry_type.get() {
+                        Some(config::EntryMain) => {
+                            let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty)));
+                            let trait_ref = ty::TraitRef::new(term_id, substs);
+                            let cause = traits::ObligationCause::new(
+                                span, fn_id, ObligationCauseCode::MainFunctionType);
+
+                            inherited.register_predicate(
+                                traits::Obligation::new(
+                                    cause, param_env, trait_ref.to_predicate()));
+                        },
+                        _ => {},
+                    }
                 }
             }
         }
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index f02998f7edf74..0b2f59abf4f78 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -203,7 +203,8 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
 
             let actual = tcx.fn_sig(main_def_id);
-            let expected_return_type = if tcx.lang_items().termination().is_some() {
+            let expected_return_type = if tcx.lang_items().termination().is_some()
+                && tcx.sess.features.borrow().termination_trait {
                 // we take the return type of the given main function, the real check is done
                 // in `check_fn`
                 actual.output().skip_binder()
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 3a7a57fe2b83f..171c108e3aa55 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -503,7 +503,7 @@ pub mod rt;
 // The trait to support returning arbitrary types in the main function
 mod termination;
 
-#[unstable(feature = "termination_trait", issue = "0")]
+#[unstable(feature = "termination_trait", issue = "43301")]
 pub use self::termination::Termination;
 
 // Include a number of private modules that exist solely to provide
diff --git a/src/libstd/termination.rs b/src/libstd/termination.rs
index 5eeaa542b41dd..ee1dc5470a849 100644
--- a/src/libstd/termination.rs
+++ b/src/libstd/termination.rs
@@ -20,7 +20,7 @@ use libc;
 /// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
 /// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
 #[cfg_attr(not(stage0), lang = "termination")]
-#[unstable(feature = "termination_trait", issue = "0")]
+#[unstable(feature = "termination_trait", issue = "43301")]
 #[rustc_on_unimplemented =
   "`main` can only return types that implement {Termination}, not `{Self}`"]
 pub trait Termination {
@@ -29,12 +29,12 @@ pub trait Termination {
     fn report(self) -> i32;
 }
 
-#[unstable(feature = "termination_trait", issue = "0")]
+#[unstable(feature = "termination_trait", issue = "43301")]
 impl Termination for () {
     fn report(self) -> i32 { libc::EXIT_SUCCESS }
 }
 
-#[unstable(feature = "termination_trait", issue = "0")]
+#[unstable(feature = "termination_trait", issue = "43301")]
 impl<T: Termination, E: Error> Termination for Result<T, E> {
     fn report(self) -> i32 {
         match self {
@@ -47,7 +47,7 @@ impl<T: Termination, E: Error> Termination for Result<T, E> {
     }
 }
 
-#[unstable(feature = "termination_trait", issue = "0")]
+#[unstable(feature = "termination_trait", issue = "43301")]
 fn print_error<E: Error>(err: E) {
     eprintln!("Error: {}", err.description());
 
@@ -56,19 +56,19 @@ fn print_error<E: Error>(err: E) {
     }
 }
 
-#[unstable(feature = "termination_trait", issue = "0")]
+#[unstable(feature = "termination_trait", issue = "43301")]
 impl Termination for ! {
     fn report(self) -> i32 { unreachable!(); }
 }
 
-#[unstable(feature = "termination_trait", issue = "0")]
+#[unstable(feature = "termination_trait", issue = "43301")]
 impl Termination for bool {
     fn report(self) -> i32 {
         if self { libc::EXIT_SUCCESS } else { libc::EXIT_FAILURE }
     }
 }
 
-#[unstable(feature = "termination_trait", issue = "0")]
+#[unstable(feature = "termination_trait", issue = "43301")]
 impl Termination for i32 {
     fn report(self) -> i32 {
         self
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index f8d6b419f7ada..dde917b4d9591 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -444,6 +444,9 @@ declare_features! (
 
     // Nested `impl Trait`
     (active, nested_impl_trait, "1.24.0", Some(34511)),
+
+    // Termination trait in main (RFC 1937)
+    (active, termination_trait, "1.24.0", Some(43301)),
 );
 
 declare_features! (
diff --git a/src/test/compile-fail/feature-gate-termination_trait.rs b/src/test/compile-fail/feature-gate-termination_trait.rs
new file mode 100644
index 0000000000000..5a56445b64e57
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-termination_trait.rs
@@ -0,0 +1,13 @@
+// Copyright 2017 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.
+
+fn main() -> i32 { //~ ERROR main function has wrong type [E0580]
+    0
+}
diff --git a/src/test/compile-fail/termination-trait-not-satisfied.rs b/src/test/compile-fail/termination-trait-not-satisfied.rs
index 178a9b8cf5918..788c38c55be0a 100644
--- a/src/test/compile-fail/termination-trait-not-satisfied.rs
+++ b/src/test/compile-fail/termination-trait-not-satisfied.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(termination_trait)]
+
 struct ReturnType {}
 
 fn main() -> ReturnType { //~ ERROR `ReturnType: std::Termination` is not satisfied

From a8a9a05abb27e24cccd07a9cbab190ca54eb8e06 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Fri, 22 Dec 2017 15:31:51 +0100
Subject: [PATCH 11/25] Convert codegen-unit tests to use `start` instead of
 `main`

The new Termination traits brings in the unwinding machinery and that
blows up the required `TRANS_ITEM`s.
---
 .../item-collection/cross-crate-closures.rs   |  8 +++--
 .../cross-crate-generic-functions.rs          | 28 ++++-------------
 .../cross-crate-trait-method.rs               | 28 ++++-------------
 .../drop_in_place_intrinsic.rs                | 28 +++++------------
 .../item-collection/function-as-argument.rs   | 27 ++++-------------
 .../item-collection/generic-drop-glue.rs      | 27 ++++-------------
 .../item-collection/generic-functions.rs      | 27 ++++-------------
 .../item-collection/generic-impl.rs           | 27 ++++-------------
 .../impl-in-non-instantiated-generic.rs       | 27 ++++-------------
 .../instantiation-through-vtable.rs           | 27 ++++-------------
 .../items-within-generic-items.rs             | 27 ++++-------------
 .../item-collection/non-generic-closures.rs   |  8 +++--
 .../item-collection/non-generic-drop-glue.rs  | 27 ++++-------------
 .../item-collection/non-generic-functions.rs  | 27 ++++-------------
 .../item-collection/static-init.rs            | 28 +++++------------
 .../item-collection/statics-and-consts.rs     | 28 ++++-------------
 .../item-collection/trait-implementations.rs  | 27 ++++-------------
 .../trait-method-as-argument.rs               | 27 ++++-------------
 .../trait-method-default-impl.rs              | 27 ++++-------------
 .../item-collection/transitive-drop-glue.rs   | 28 ++++-------------
 .../item-collection/tuple-drop-glue.rs        | 27 ++++-------------
 .../codegen-units/item-collection/unsizing.rs | 28 ++++-------------
 .../methods-are-with-self-type.rs             |  9 ++++--
 .../partitioning/vtable-through-const.rs      | 30 +++++--------------
 24 files changed, 148 insertions(+), 454 deletions(-)

diff --git a/src/test/codegen-units/item-collection/cross-crate-closures.rs b/src/test/codegen-units/item-collection/cross-crate-closures.rs
index 2b5ac7e8d80de..320be27819812 100644
--- a/src/test/codegen-units/item-collection/cross-crate-closures.rs
+++ b/src/test/codegen-units/item-collection/cross-crate-closures.rs
@@ -17,12 +17,14 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 // aux-build:cgu_extern_closures.rs
 extern crate cgu_extern_closures;
 
-//~ TRANS_ITEM fn cross_crate_closures::main[0]
-fn main() {
+//~ TRANS_ITEM fn cross_crate_closures::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
 
     //~ TRANS_ITEM fn cgu_extern_closures::inlined_fn[0]
     //~ TRANS_ITEM fn cgu_extern_closures::inlined_fn[0]::{{closure}}[0]
@@ -35,6 +37,8 @@ fn main() {
     // Nothing should be generated for this call, we just link to the instance
     // in the extern crate.
     let _ = cgu_extern_closures::non_inlined_fn(6, 7);
+
+    0
 }
 
 //~ TRANS_ITEM drop-glue i8
diff --git a/src/test/codegen-units/item-collection/cross-crate-generic-functions.rs b/src/test/codegen-units/item-collection/cross-crate-generic-functions.rs
index 411f3da9182bd..bcb3b7b1dadf4 100644
--- a/src/test/codegen-units/item-collection/cross-crate-generic-functions.rs
+++ b/src/test/codegen-units/item-collection/cross-crate-generic-functions.rs
@@ -12,32 +12,14 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 // aux-build:cgu_generic_function.rs
 extern crate cgu_generic_function;
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ cross_crate_generic_functions0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ cross_crate_generic_functions0[Internal]
-//~ TRANS_ITEM fn cross_crate_generic_functions::main[0]
-fn main()
-{
+//~ TRANS_ITEM fn cross_crate_generic_functions::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn cgu_generic_function::bar[0]<u32>
     //~ TRANS_ITEM fn cgu_generic_function::foo[0]<u32>
     let _ = cgu_generic_function::foo(1u32);
@@ -48,4 +30,6 @@ fn main()
 
     // This should not introduce a codegen item
     let _ = cgu_generic_function::exported_but_not_generic(3);
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/cross-crate-trait-method.rs b/src/test/codegen-units/item-collection/cross-crate-trait-method.rs
index a269b6da230d1..910ae000848e5 100644
--- a/src/test/codegen-units/item-collection/cross-crate-trait-method.rs
+++ b/src/test/codegen-units/item-collection/cross-crate-trait-method.rs
@@ -12,34 +12,16 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 // aux-build:cgu_export_trait_method.rs
 extern crate cgu_export_trait_method;
 
 use cgu_export_trait_method::Trait;
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ cross_crate_trait_method0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ cross_crate_trait_method0[Internal]
-//~ TRANS_ITEM fn cross_crate_trait_method::main[0]
-fn main()
-{
+//~ TRANS_ITEM fn cross_crate_trait_method::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     // The object code of these methods is contained in the external crate, so
     // calling them should *not* introduce codegen items in the current crate.
     let _: (u32, u32) = Trait::without_default_impl(0);
@@ -74,4 +56,6 @@ fn main()
     let _: (char, char) = Trait::without_default_impl_generic('c');
     //~ TRANS_ITEM fn cgu_export_trait_method::{{impl}}[0]::without_default_impl_generic[0]<bool>
     let _: (char, bool) = Trait::without_default_impl_generic(false);
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
index 88888afa69300..52af81650329c 100644
--- a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
+++ b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
@@ -12,6 +12,8 @@
 // compile-flags:-Zprint-trans-items=eager
 // compile-flags:-Zinline-in-all-cgus
 
+#![feature(start)]
+
 //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<drop_in_place_intrinsic::StructWithDtor[0]> @@ drop_in_place_intrinsic0[Internal]
 struct StructWithDtor(u32);
 
@@ -20,32 +22,16 @@ impl Drop for StructWithDtor {
     fn drop(&mut self) {}
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ drop_in_place_intrinsic0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ drop_in_place_intrinsic0[Internal]
-//~ TRANS_ITEM fn drop_in_place_intrinsic::main[0]
-fn main() {
+//~ TRANS_ITEM fn drop_in_place_intrinsic::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
 
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic0[Internal]
     let x = [StructWithDtor(0), StructWithDtor(1)];
 
     drop_slice_in_place(&x);
+
+    0
 }
 
 //~ TRANS_ITEM fn drop_in_place_intrinsic::drop_slice_in_place[0]
diff --git a/src/test/codegen-units/item-collection/function-as-argument.rs b/src/test/codegen-units/item-collection/function-as-argument.rs
index 3fb25d9b2a0da..65707c1aa4d65 100644
--- a/src/test/codegen-units/item-collection/function-as-argument.rs
+++ b/src/test/codegen-units/item-collection/function-as-argument.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 fn take_fn_once<T1, T2, F: FnOnce(T1, T2)>(f: F, x: T1, y: T2) {
     (f)(x, y)
@@ -23,27 +24,9 @@ fn take_fn_pointer<T1, T2>(f: fn(T1, T2), x: T1, y: T2) {
     (f)(x, y)
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ function_as_argument0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ function_as_argument0[Internal]
-//~ TRANS_ITEM fn function_as_argument::main[0]
-fn main() {
+//~ TRANS_ITEM fn function_as_argument::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
 
     //~ TRANS_ITEM fn function_as_argument::take_fn_once[0]<u32, &str, fn(u32, &str)>
     //~ TRANS_ITEM fn function_as_argument::function[0]<u32, &str>
@@ -62,4 +45,6 @@ fn main() {
     //~ TRANS_ITEM fn function_as_argument::take_fn_pointer[0]<f32, i64>
     //~ TRANS_ITEM fn function_as_argument::function[0]<f32, i64>
     take_fn_pointer(function, 0f32, 0i64);
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/generic-drop-glue.rs b/src/test/codegen-units/item-collection/generic-drop-glue.rs
index 0d08611d1cc96..d3d9aa3aefc77 100644
--- a/src/test/codegen-units/item-collection/generic-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/generic-drop-glue.rs
@@ -13,6 +13,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![deny(dead_code)]
+#![feature(start)]
 
 struct StructWithDrop<T1, T2> {
     x: T1,
@@ -53,27 +54,9 @@ impl Drop for NonGenericWithDrop {
     fn drop(&mut self) {}
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ generic_drop_glue0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn generic_drop_glue::main[0]
-fn main() {
+//~ TRANS_ITEM fn generic_drop_glue::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<i8, char>> @@ generic_drop_glue0[Internal]
     //~ TRANS_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<i8, char>
     let _ = StructWithDrop { x: 0i8, y: 'a' }.x;
@@ -113,4 +96,6 @@ fn main() {
         EnumNoDrop::A(x) => x,
         EnumNoDrop::B(x) => x as f64
     };
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/generic-functions.rs b/src/test/codegen-units/item-collection/generic-functions.rs
index 41133f0f797db..8efe4b2762a56 100644
--- a/src/test/codegen-units/item-collection/generic-functions.rs
+++ b/src/test/codegen-units/item-collection/generic-functions.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 fn foo1<T1>(a: T1) -> (T1, u32) {
     (a, 1)
@@ -31,27 +32,9 @@ pub fn lifetime_only<'a>(a: &'a u32) -> &'a u32 {
     a
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ generic_functions0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ generic_functions0[Internal]
-//~ TRANS_ITEM fn generic_functions::main[0]
-fn main() {
+//~ TRANS_ITEM fn generic_functions::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn generic_functions::foo1[0]<i32>
     let _ = foo1(2i32);
     //~ TRANS_ITEM fn generic_functions::foo1[0]<i64>
@@ -78,4 +61,6 @@ fn main() {
     let _ = foo3(0i16, "a", 2usize);
     //~ TRANS_ITEM fn generic_functions::foo3[0]<char, (), ()>
     let _ = foo3('v', (), ());
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/generic-impl.rs b/src/test/codegen-units/item-collection/generic-impl.rs
index 6212ad0417c74..d1ee8ee624c28 100644
--- a/src/test/codegen-units/item-collection/generic-impl.rs
+++ b/src/test/codegen-units/item-collection/generic-impl.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 struct Struct<T> {
     x: T,
@@ -50,27 +51,9 @@ impl<'a> LifeTimeOnly<'a> {
     pub fn non_instantiated<T>(&self) {}
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ generic_impl0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ generic_impl0[Internal]
-//~ TRANS_ITEM fn generic_impl::main[0]
-fn main() {
+//~ TRANS_ITEM fn generic_impl::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<i32>
     //~ TRANS_ITEM fn generic_impl::id[0]<i32>
     //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::get[0]<i32, i16>
@@ -94,4 +77,6 @@ fn main() {
     //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<generic_impl::Struct[0]<&str>>
     //~ TRANS_ITEM fn generic_impl::id[0]<generic_impl::Struct[0]<&str>>
     let _ = (Struct::new(Struct::new("str")).f)(Struct::new("str"));
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/impl-in-non-instantiated-generic.rs b/src/test/codegen-units/item-collection/impl-in-non-instantiated-generic.rs
index aa3de2095fbde..c07d26c3f8d8b 100644
--- a/src/test/codegen-units/item-collection/impl-in-non-instantiated-generic.rs
+++ b/src/test/codegen-units/item-collection/impl-in-non-instantiated-generic.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 trait SomeTrait {
     fn foo(&self);
@@ -28,26 +29,10 @@ pub fn generic_function<T>(x: T) -> (T, i32) {
     (x, 0)
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ impl_in_non_instantiated_generic0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ impl_in_non_instantiated_generic0[Internal]
-//~ TRANS_ITEM fn impl_in_non_instantiated_generic::main[0]
-fn main() {
+//~ TRANS_ITEM fn impl_in_non_instantiated_generic::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     0i64.foo();
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs
index 8b46984f72fce..2e1138ef1283e 100644
--- a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs
+++ b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs
@@ -13,6 +13,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![deny(dead_code)]
+#![feature(start)]
 
 trait Trait {
     fn foo(&self) -> u32;
@@ -28,27 +29,9 @@ impl<T> Trait for Struct<T> {
     fn bar(&self) {}
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ instantiation_through_vtable0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ instantiation_through_vtable0[Internal]
-//~ TRANS_ITEM fn instantiation_through_vtable::main[0]
-fn main() {
+//~ TRANS_ITEM fn instantiation_through_vtable::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let s1 = Struct { _a: 0u32 };
 
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<instantiation_through_vtable::Struct[0]<u32>> @@ instantiation_through_vtable0[Internal]
@@ -61,4 +44,6 @@ fn main() {
     //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0]<u64>
     //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0]<u64>
     let _ = &s1 as &Trait;
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/items-within-generic-items.rs b/src/test/codegen-units/item-collection/items-within-generic-items.rs
index abd79dd39d628..04b54de3ce23e 100644
--- a/src/test/codegen-units/item-collection/items-within-generic-items.rs
+++ b/src/test/codegen-units/item-collection/items-within-generic-items.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 fn generic_fn<T>(a: T) -> (T, i32) {
     //~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]::nested_fn[0]
@@ -31,31 +32,15 @@ fn generic_fn<T>(a: T) -> (T, i32) {
     return (a, x + nested_fn(0));
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ items_within_generic_items0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ items_within_generic_items0[Internal]
-//~ TRANS_ITEM fn items_within_generic_items::main[0]
-fn main() {
+//~ TRANS_ITEM fn items_within_generic_items::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<i64>
     let _ = generic_fn(0i64);
     //~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<u16>
     let _ = generic_fn(0u16);
     //~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<i8>
     let _ = generic_fn(0i8);
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/non-generic-closures.rs b/src/test/codegen-units/item-collection/non-generic-closures.rs
index 278e9189dd6a7..f0121d56cec60 100644
--- a/src/test/codegen-units/item-collection/non-generic-closures.rs
+++ b/src/test/codegen-units/item-collection/non-generic-closures.rs
@@ -17,6 +17,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 //~ TRANS_ITEM fn non_generic_closures::temporary[0]
 fn temporary() {
@@ -52,12 +53,15 @@ fn assigned_to_variable_executed_directly() {
     f(4);
 }
 
-//~ TRANS_ITEM fn non_generic_closures::main[0]
-fn main() {
+//~ TRANS_ITEM fn non_generic_closures::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     temporary();
     assigned_to_variable_but_not_executed();
     assigned_to_variable_executed_directly();
     assigned_to_variable_executed_indirectly();
+
+    0
 }
 
 //~ TRANS_ITEM fn non_generic_closures::run_closure[0]
diff --git a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs
index df89b3fca9f11..bf084aa96eafe 100644
--- a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs
@@ -13,6 +13,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![deny(dead_code)]
+#![feature(start)]
 
 //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<non_generic_drop_glue::StructWithDrop[0]> @@ non_generic_drop_glue0[Internal]
 struct StructWithDrop {
@@ -42,27 +43,9 @@ enum EnumNoDrop {
     A(i32)
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ non_generic_drop_glue0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ non_generic_drop_glue0[Internal]
-//~ TRANS_ITEM fn non_generic_drop_glue::main[0]
-fn main() {
+//~ TRANS_ITEM fn non_generic_drop_glue::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _ = StructWithDrop { x: 0 }.x;
     let _ = StructNoDrop { x: 0 }.x;
     let _ = match EnumWithDrop::A(0) {
@@ -71,4 +54,6 @@ fn main() {
     let _ = match EnumNoDrop::A(0) {
         EnumNoDrop::A(x) => x
     };
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/non-generic-functions.rs b/src/test/codegen-units/item-collection/non-generic-functions.rs
index 6f254ffde60b0..8c487db5c9611 100644
--- a/src/test/codegen-units/item-collection/non-generic-functions.rs
+++ b/src/test/codegen-units/item-collection/non-generic-functions.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 //~ TRANS_ITEM fn non_generic_functions::foo[0]
 fn foo() {
@@ -69,30 +70,14 @@ impl Struct {
     }
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ non_generic_functions0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ non_generic_functions0[Internal]
-//~ TRANS_ITEM fn non_generic_functions::main[0]
-fn main() {
+//~ TRANS_ITEM fn non_generic_functions::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     foo();
     bar();
     Struct::foo();
     let x = Struct { _x: 0 };
     x.bar();
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/static-init.rs b/src/test/codegen-units/item-collection/static-init.rs
index 9921c9b84d2f1..5ff7c3480b126 100644
--- a/src/test/codegen-units/item-collection/static-init.rs
+++ b/src/test/codegen-units/item-collection/static-init.rs
@@ -11,6 +11,8 @@
 // compile-flags:-Zprint-trans-items=eager
 // ignore-tidy-linelength
 
+#![feature(start)]
+
 pub static FN : fn() = foo::<i32>;
 
 pub fn foo<T>() { }
@@ -18,25 +20,9 @@ pub fn foo<T>() { }
 //~ TRANS_ITEM fn static_init::foo[0]<i32>
 //~ TRANS_ITEM static static_init::FN[0]
 
-fn main() { }
+//~ TRANS_ITEM fn static_init::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    0
+}
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ static_init0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ static_init0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ static_init0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ static_init0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ static_init0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ static_init0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ static_init0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ static_init0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ static_init0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ static_init0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ static_init0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ static_init0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ static_init0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ static_init0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ static_init0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ static_init0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ static_init0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ static_init0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ static_init0[Internal]
-//~ TRANS_ITEM fn static_init::main[0]
diff --git a/src/test/codegen-units/item-collection/statics-and-consts.rs b/src/test/codegen-units/item-collection/statics-and-consts.rs
index bd3dcd2fe79a7..11df1da3a78b9 100644
--- a/src/test/codegen-units/item-collection/statics-and-consts.rs
+++ b/src/test/codegen-units/item-collection/statics-and-consts.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 static STATIC1: i64 = {
     const STATIC1_CONST1: i64 = 2;
@@ -47,9 +48,13 @@ fn foo() {
     };
 }
 
-fn main() {
+//~ TRANS_ITEM fn statics_and_consts::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     foo();
     let _ = STATIC1;
+
+    0
 }
 
 //~ TRANS_ITEM static statics_and_consts::STATIC1[0]
@@ -58,24 +63,3 @@ fn main() {
 //~ TRANS_ITEM static statics_and_consts::foo[0]::STATIC2[0]
 //~ TRANS_ITEM static statics_and_consts::foo[0]::STATIC2[1]
 //~ TRANS_ITEM static statics_and_consts::foo[0]::STATIC2[2]
-
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ statics_and_consts0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ statics_and_consts0[Internal]
-//~ TRANS_ITEM fn statics_and_consts::main[0]
diff --git a/src/test/codegen-units/item-collection/trait-implementations.rs b/src/test/codegen-units/item-collection/trait-implementations.rs
index e8f727cbd12bd..8eb33dd647f64 100644
--- a/src/test/codegen-units/item-collection/trait-implementations.rs
+++ b/src/test/codegen-units/item-collection/trait-implementations.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 pub trait SomeTrait {
     fn foo(&self);
@@ -55,27 +56,9 @@ impl<T> SomeGenericTrait<T> for f32 {
     fn bar<T2>(&self, _: T, _: T2) {}
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ trait_implementations0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ trait_implementations0[Internal]
-//~ TRANS_ITEM fn trait_implementations::main[0]
-fn main() {
+//~ TRANS_ITEM fn trait_implementations::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
    //~ TRANS_ITEM fn trait_implementations::{{impl}}[1]::bar[0]<char>
    0i32.bar('x');
 
@@ -96,4 +79,6 @@ fn main() {
 
    //~ TRANS_ITEM fn trait_implementations::{{impl}}[3]::bar[0]<&str, &str>
    0f32.bar("&str", "&str");
+
+   0
 }
diff --git a/src/test/codegen-units/item-collection/trait-method-as-argument.rs b/src/test/codegen-units/item-collection/trait-method-as-argument.rs
index f6e3c1cf9747c..10b216303087c 100644
--- a/src/test/codegen-units/item-collection/trait-method-as-argument.rs
+++ b/src/test/codegen-units/item-collection/trait-method-as-argument.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 trait Trait : Sized {
     fn foo(self) -> Self { self }
@@ -36,27 +37,9 @@ fn take_foo_mut<T, F: FnMut(T) -> T>(mut f: F, arg: T) -> T {
     (f)(arg)
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ trait_method_as_argument0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ trait_method_as_argument0[Internal]
-//~ TRANS_ITEM fn trait_method_as_argument::main[0]
-fn main() {
+//~ TRANS_ITEM fn trait_method_as_argument::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn trait_method_as_argument::take_foo_once[0]<u32, fn(u32) -> u32>
     //~ TRANS_ITEM fn trait_method_as_argument::{{impl}}[0]::foo[0]
     //~ TRANS_ITEM fn core::ops[0]::function[0]::FnOnce[0]::call_once[0]<fn(u32) -> u32, (u32)>
@@ -82,4 +65,6 @@ fn main() {
     //~ TRANS_ITEM fn trait_method_as_argument::take_foo_mut[0]<char, fn(char) -> char>
     //~ TRANS_ITEM fn core::ops[0]::function[0]::FnMut[0]::call_mut[0]<fn(u32) -> u32, (u32)>
     take_foo_mut(Trait::foo, 'c');
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/trait-method-default-impl.rs b/src/test/codegen-units/item-collection/trait-method-default-impl.rs
index 6e6793076da59..a6ae3765b2ed7 100644
--- a/src/test/codegen-units/item-collection/trait-method-default-impl.rs
+++ b/src/test/codegen-units/item-collection/trait-method-default-impl.rs
@@ -12,6 +12,7 @@
 // compile-flags:-Zprint-trans-items=eager
 
 #![deny(dead_code)]
+#![feature(start)]
 
 trait SomeTrait {
     fn foo(&self) { }
@@ -46,27 +47,9 @@ impl<T1> SomeGenericTrait<T1> for u32 {
     // since nothing is monomorphic here, nothing should be generated unless used somewhere.
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ trait_method_default_impl0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ trait_method_default_impl0[Internal]
-//~ TRANS_ITEM fn trait_method_default_impl::main[0]
-fn main() {
+//~ TRANS_ITEM fn trait_method_default_impl::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn trait_method_default_impl::SomeTrait[0]::bar[0]<i8, char>
     let _ = 1i8.bar('c');
 
@@ -84,4 +67,6 @@ fn main() {
 
     //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<u32, i16, ()>
     0u32.bar(0i16, ());
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/transitive-drop-glue.rs b/src/test/codegen-units/item-collection/transitive-drop-glue.rs
index e966b9f92e441..57cd10187a267 100644
--- a/src/test/codegen-units/item-collection/transitive-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/transitive-drop-glue.rs
@@ -13,6 +13,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![deny(dead_code)]
+#![feature(start)]
 
 //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Root[0]> @@ transitive_drop_glue0[Internal]
 struct Root(Intermediate);
@@ -34,28 +35,9 @@ impl<T> Drop for LeafGen<T> {
     fn drop(&mut self) {}
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ transitive_drop_glue0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ transitive_drop_glue0[Internal]
-//~ TRANS_ITEM fn transitive_drop_glue::main[0]
-fn main() {
-
+//~ TRANS_ITEM fn transitive_drop_glue::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     let _ = Root(Intermediate(Leaf));
 
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::RootGen[0]<u32>> @@ transitive_drop_glue0[Internal]
@@ -69,4 +51,6 @@ fn main() {
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::LeafGen[0]<i16>> @@ transitive_drop_glue0[Internal]
     //~ TRANS_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0]<i16>
     let _ = RootGen(IntermediateGen(LeafGen(0i16)));
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/tuple-drop-glue.rs b/src/test/codegen-units/item-collection/tuple-drop-glue.rs
index 93b3f832e99cb..a5f2409b8aea3 100644
--- a/src/test/codegen-units/item-collection/tuple-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/tuple-drop-glue.rs
@@ -13,6 +13,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![deny(dead_code)]
+#![feature(start)]
 
 //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<tuple_drop_glue::Dropped[0]> @@ tuple_drop_glue0[Internal]
 struct Dropped;
@@ -22,31 +23,15 @@ impl Drop for Dropped {
     fn drop(&mut self) {}
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ tuple_drop_glue0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ tuple_drop_glue0[Internal]
-//~ TRANS_ITEM fn tuple_drop_glue::main[0]
-fn main() {
+//~ TRANS_ITEM fn tuple_drop_glue::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue0[Internal]
     let x = (0u32, Dropped);
 
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue0[Internal]
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue0[Internal]
     let x = (0i16, (Dropped, true));
+
+    0
 }
diff --git a/src/test/codegen-units/item-collection/unsizing.rs b/src/test/codegen-units/item-collection/unsizing.rs
index 4c07177b7396d..87d2581e1f81b 100644
--- a/src/test/codegen-units/item-collection/unsizing.rs
+++ b/src/test/codegen-units/item-collection/unsizing.rs
@@ -15,6 +15,7 @@
 #![deny(dead_code)]
 #![feature(coerce_unsized)]
 #![feature(unsize)]
+#![feature(start)]
 
 use std::marker::Unsize;
 use std::ops::CoerceUnsized;
@@ -53,28 +54,9 @@ struct Wrapper<T: ?Sized>(*const T);
 
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ unsizing0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ unsizing0[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ unsizing0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ unsizing0[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ unsizing0[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ unsizing0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ unsizing0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ unsizing0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ unsizing0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ unsizing0[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ unsizing0[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ unsizing0[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ unsizing0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ unsizing0[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ unsizing0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ unsizing0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ unsizing0[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ unsizing0[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ unsizing0[Internal]
-//~ TRANS_ITEM fn unsizing::main[0]
-fn main()
-{
+//~ TRANS_ITEM fn unsizing::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     // simple case
     let bool_sized = &true;
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<bool> @@ unsizing0[Internal]
@@ -102,4 +84,6 @@ fn main()
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ unsizing0[Internal]
     //~ TRANS_ITEM fn unsizing::{{impl}}[3]::foo[0]
     let _wrapper_sized = wrapper_sized as Wrapper<Trait>;
+
+    0
 }
diff --git a/src/test/codegen-units/partitioning/methods-are-with-self-type.rs b/src/test/codegen-units/partitioning/methods-are-with-self-type.rs
index 1ea5aafd401d2..aa01289de592c 100644
--- a/src/test/codegen-units/partitioning/methods-are-with-self-type.rs
+++ b/src/test/codegen-units/partitioning/methods-are-with-self-type.rs
@@ -19,6 +19,7 @@
 // compile-flags:-Zprint-trans-items=lazy -Zincremental=tmp/partitioning-tests/methods-are-with-self-type
 
 #![allow(dead_code)]
+#![feature(start)]
 
 struct SomeType;
 
@@ -63,9 +64,9 @@ mod type2 {
     pub struct Struct;
 }
 
-//~ TRANS_ITEM fn methods_are_with_self_type::main[0]
-fn main()
-{
+//~ TRANS_ITEM fn methods_are_with_self_type::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[1]::method[0]<u32, u64> @@ methods_are_with_self_type.volatile[WeakODR]
     SomeGenericType(0u32, 0u64).method();
     //~ TRANS_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[1]::associated_fn[0]<char, &str> @@ methods_are_with_self_type.volatile[WeakODR]
@@ -80,6 +81,8 @@ fn main()
     type1::Struct.default();
     //~ TRANS_ITEM fn methods_are_with_self_type::Trait[0]::default[0]<methods_are_with_self_type::type2[0]::Struct[0]> @@ methods_are_with_self_type-type2.volatile[WeakODR]
     type2::Struct.default();
+
+    0
 }
 
 //~ TRANS_ITEM drop-glue i8
diff --git a/src/test/codegen-units/partitioning/vtable-through-const.rs b/src/test/codegen-units/partitioning/vtable-through-const.rs
index 05c36810c1f25..d0acddda63714 100644
--- a/src/test/codegen-units/partitioning/vtable-through-const.rs
+++ b/src/test/codegen-units/partitioning/vtable-through-const.rs
@@ -18,6 +18,8 @@
 // This test case makes sure, that references made through constants are
 // recorded properly in the InliningMap.
 
+#![feature(start)]
+
 mod mod1 {
     pub trait Trait1 {
         fn do_something(&self) {}
@@ -38,7 +40,7 @@ mod mod1 {
 
     fn id<T>(x: T) -> T { x }
 
-    // These are referenced, so they produce trans-items (see main())
+    // These are referenced, so they produce trans-items (see start())
     pub const TRAIT1_REF: &'static Trait1 = &0u32 as &Trait1;
     pub const TRAIT1_GEN_REF: &'static Trait1Gen<u8> = &0u32 as &Trait1Gen<u8>;
     pub const ID_CHAR: fn(char) -> char = id::<char>;
@@ -68,27 +70,9 @@ mod mod1 {
     pub const ID_I64: fn(i64) -> i64 = id::<i64>;
 }
 
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::align[0] @@ std-rt.volatile[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::from_size_align_unchecked[0] @@ std-rt.volatile[Internal]
-//~ TRANS_ITEM fn alloc::allocator[0]::{{impl}}[0]::size[0] @@ std-rt.volatile[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::box_free[0]<core::any[0]::Any[0]> @@ std-rt.volatile[Internal]
-//~ TRANS_ITEM fn alloc::heap[0]::{{impl}}[0]::dealloc[0] @@ std-rt.volatile[Internal]
-//~ TRANS_ITEM fn core::mem[0]::uninitialized[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ std-panicking.volatile[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ std-rt.volatile[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::any[0]::Any[0]> @@ std-rt.volatile[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<core::result[0]::Result[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>>> @@ std-rt.volatile[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::read[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ std-panicking.volatile[Internal]
-//~ TRANS_ITEM fn core::ptr[0]::write[0]<i32> @@ std-panicking.volatile[Internal]
-//~ TRANS_ITEM fn core::result[0]::{{impl}}[0]::unwrap_or[0]<i32, alloc::boxed[0]::Box[0]<core::any[0]::Any[0]>> @@ std-rt.volatile[Internal]
-//~ TRANS_ITEM fn std::panic[0]::catch_unwind[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ std-panic.volatile[External]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]::do_call[0]<std::rt[0]::lang_start[0]::{{closure}}[0]<()>, i32> @@ std-panicking.volatile[Internal]
-//~ TRANS_ITEM fn std::panicking[0]::try[0]<i32, std::rt[0]::lang_start[0]::{{closure}}[0]<()>> @@ std-panicking.volatile[External]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, fn()> @@ std-sys_common-backtrace.volatile[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]::{{closure}}[0]<(), i32, extern "rust-call" fn(()) -> i32, &fn()> @@ std-panicking.volatile[Internal]
-//~ TRANS_ITEM fn std::rt[0]::lang_start[0]<()> @@ std-rt.volatile[External]
-//~ TRANS_ITEM fn std::sys_common[0]::backtrace[0]::__rust_begin_short_backtrace[0]<std::rt[0]::lang_start[0]::{{closure}}[0]::{{closure}}[0]<()>, i32> @@ std-sys_common-backtrace.volatile[External]
-//~ TRANS_ITEM fn vtable_through_const::main[0] @@ vtable_through_const[Internal]
-fn main() {
+//~ TRANS_ITEM fn vtable_through_const::start[0]
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ vtable_through_const[Internal]
 
     // Since Trait1::do_something() is instantiated via its default implementation,
@@ -109,4 +93,6 @@ fn main() {
 
     //~ TRANS_ITEM fn vtable_through_const::mod1[0]::id[0]<char> @@ vtable_through_const-mod1.volatile[External]
     mod1::ID_CHAR('x');
+
+    0
 }

From 83cb299e3eb93d9fee5e3a2730a4f9c14de6cdd9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Fri, 22 Dec 2017 15:50:42 +0100
Subject: [PATCH 12/25] Just compare the symbol names and types, not the
 addresses

---
 src/test/run-make/reproducible-build/Makefile | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/test/run-make/reproducible-build/Makefile b/src/test/run-make/reproducible-build/Makefile
index 8e799ca1a4303..a62cdb70b86f4 100644
--- a/src/test/run-make/reproducible-build/Makefile
+++ b/src/test/run-make/reproducible-build/Makefile
@@ -3,18 +3,18 @@ all:
 	$(RUSTC) reproducible-build-aux.rs
 	$(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build1"
 	$(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build2"
-	nm "$(TMPDIR)/reproducible-build1" | sort > "$(TMPDIR)/reproducible-build1.nm"
-	nm "$(TMPDIR)/reproducible-build2" | sort > "$(TMPDIR)/reproducible-build2.nm"
+	nm "$(TMPDIR)/reproducible-build1" | awk '{ print $2 " " $3 }' | sort > "$(TMPDIR)/reproducible-build1.nm"
+	nm "$(TMPDIR)/reproducible-build2" | awk '{ print $2 " " $3 }' | sort > "$(TMPDIR)/reproducible-build2.nm"
 	cmp "$(TMPDIR)/reproducible-build1.nm" "$(TMPDIR)/reproducible-build2.nm" || exit 1
 	$(RUSTC) reproducible-build-aux.rs -g
 	$(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build1-debug"
 	$(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build2-debug"
-	nm "$(TMPDIR)/reproducible-build1-debug" | sort > "$(TMPDIR)/reproducible-build1-debug.nm"
-	nm "$(TMPDIR)/reproducible-build2-debug" | sort > "$(TMPDIR)/reproducible-build2-debug.nm"
+	nm "$(TMPDIR)/reproducible-build1-debug" | awk '{ print $2 " " $3 }' | sort > "$(TMPDIR)/reproducible-build1-debug.nm"
+	nm "$(TMPDIR)/reproducible-build2-debug" | awk '{ print $2 " " $3 }' | sort > "$(TMPDIR)/reproducible-build2-debug.nm"
 	cmp "$(TMPDIR)/reproducible-build1-debug.nm" "$(TMPDIR)/reproducible-build2-debug.nm" || exit 1
 	$(RUSTC) reproducible-build-aux.rs -O
 	$(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build1-opt"
 	$(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build2-opt"
-	nm "$(TMPDIR)/reproducible-build1-opt" | sort > "$(TMPDIR)/reproducible-build1-opt.nm"
-	nm "$(TMPDIR)/reproducible-build2-opt" | sort > "$(TMPDIR)/reproducible-build2-opt.nm"
+	nm "$(TMPDIR)/reproducible-build1-opt" | awk '{ print $2 " " $3 }' | sort > "$(TMPDIR)/reproducible-build1-opt.nm"
+	nm "$(TMPDIR)/reproducible-build2-opt" | awk '{ print $2 " " $3 }' | sort > "$(TMPDIR)/reproducible-build2-opt.nm"
 	cmp "$(TMPDIR)/reproducible-build1-opt.nm" "$(TMPDIR)/reproducible-build2-opt.nm" || exit 1

From 88bf2b4630ca52c4949665ff3016731fd924eaf1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Fri, 22 Dec 2017 16:11:09 +0100
Subject: [PATCH 13/25] Removes some obscure transmute call in `lang_start`

---
 src/libstd/rt.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs
index 2b75201ad2b08..bfea64153c6fe 100644
--- a/src/libstd/rt.rs
+++ b/src/libstd/rt.rs
@@ -62,7 +62,7 @@ fn lang_start<T: ::termination::Termination + 'static>
             ::sys_common::backtrace::__rust_begin_short_backtrace(move || main().report())
         });
         #[cfg(not(feature = "backtrace"))]
-        let exit_code = panic::catch_unwind(mem::transmute::<_, fn()>(main).report());
+        let exit_code = panic::catch_unwind(|| main().report());
 
         sys_common::cleanup();
         exit_code.unwrap_or(101)

From 347165fd5cd0004721be6cb4cb5d3b8f5670584e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Fri, 22 Dec 2017 16:50:50 +0100
Subject: [PATCH 14/25] The test functions are now in the same compile unit

---
 src/test/run-make/sepcomp-inlining/Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/test/run-make/sepcomp-inlining/Makefile b/src/test/run-make/sepcomp-inlining/Makefile
index 1d20d940000f4..db4edb71fb7ad 100644
--- a/src/test/run-make/sepcomp-inlining/Makefile
+++ b/src/test/run-make/sepcomp-inlining/Makefile
@@ -10,6 +10,6 @@ all:
 	$(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=3 \
 		-Z inline-in-all-cgus
 	[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ i32\ .*inlined)" -eq "0" ]
-	[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ internal\ i32\ .*inlined)" -eq "2" ]
+	[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ internal\ i32\ .*inlined)" -eq "1" ]
 	[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ hidden\ i32\ .*normal)" -eq "1" ]
-	[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c declare\ hidden\ i32\ .*normal)" -eq "2" ]
+	[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c declare\ hidden\ i32\ .*normal)" -eq "1" ]

From faff382c3d5756265726e57d0928b5a1815f5485 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Fri, 22 Dec 2017 18:23:47 +0100
Subject: [PATCH 15/25] Don't emit the termination lang item in tests

---
 src/libstd/termination.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libstd/termination.rs b/src/libstd/termination.rs
index ee1dc5470a849..cfbeff0de1550 100644
--- a/src/libstd/termination.rs
+++ b/src/libstd/termination.rs
@@ -19,7 +19,7 @@ use libc;
 ///
 /// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
 /// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
-#[cfg_attr(not(stage0), lang = "termination")]
+#[cfg_attr(not(any(stage0, test)), lang = "termination")]
 #[unstable(feature = "termination_trait", issue = "43301")]
 #[rustc_on_unimplemented =
   "`main` can only return types that implement {Termination}, not `{Self}`"]

From 072f3ebd878ad044abedd3324469ae1b01eca67b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Fri, 22 Dec 2017 20:39:31 +0100
Subject: [PATCH 16/25] Use move for optimization purposes

---
 src/libstd/rt.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs
index bfea64153c6fe..1fd7c270d1941 100644
--- a/src/libstd/rt.rs
+++ b/src/libstd/rt.rs
@@ -62,7 +62,7 @@ fn lang_start<T: ::termination::Termination + 'static>
             ::sys_common::backtrace::__rust_begin_short_backtrace(move || main().report())
         });
         #[cfg(not(feature = "backtrace"))]
-        let exit_code = panic::catch_unwind(|| main().report());
+        let exit_code = panic::catch_unwind(move || main().report());
 
         sys_common::cleanup();
         exit_code.unwrap_or(101)

From 7efeeba13a2ca862f8d0f6e1f0f6fd936478b78f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Fri, 22 Dec 2017 21:06:18 +0100
Subject: [PATCH 17/25] Use `start` for the `sepcomp-inlining` test

---
 src/test/run-make/sepcomp-inlining/Makefile | 4 ++--
 src/test/run-make/sepcomp-inlining/foo.rs   | 7 ++++++-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/test/run-make/sepcomp-inlining/Makefile b/src/test/run-make/sepcomp-inlining/Makefile
index db4edb71fb7ad..1d20d940000f4 100644
--- a/src/test/run-make/sepcomp-inlining/Makefile
+++ b/src/test/run-make/sepcomp-inlining/Makefile
@@ -10,6 +10,6 @@ all:
 	$(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=3 \
 		-Z inline-in-all-cgus
 	[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ i32\ .*inlined)" -eq "0" ]
-	[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ internal\ i32\ .*inlined)" -eq "1" ]
+	[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ internal\ i32\ .*inlined)" -eq "2" ]
 	[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ hidden\ i32\ .*normal)" -eq "1" ]
-	[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c declare\ hidden\ i32\ .*normal)" -eq "1" ]
+	[ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c declare\ hidden\ i32\ .*normal)" -eq "2" ]
diff --git a/src/test/run-make/sepcomp-inlining/foo.rs b/src/test/run-make/sepcomp-inlining/foo.rs
index 20fd18b829562..5b62c1b062673 100644
--- a/src/test/run-make/sepcomp-inlining/foo.rs
+++ b/src/test/run-make/sepcomp-inlining/foo.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(start)]
+
 #[inline]
 fn inlined() -> u32 {
     1234
@@ -29,7 +31,10 @@ mod b {
     }
 }
 
-fn main() {
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
     a::f();
     b::f();
+
+    0
 }

From f972f529b2e17e7b6b8ed4a4b4a6ad29917acfce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Fri, 22 Dec 2017 21:16:09 +0100
Subject: [PATCH 18/25] Revert "Just compare the symbol names and types, not
 the addresses"

This reverts commit 7d4d98e5c870a2dcdca8ea3aa47ecee680a35e60.
---
 src/test/run-make/reproducible-build/Makefile | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/test/run-make/reproducible-build/Makefile b/src/test/run-make/reproducible-build/Makefile
index a62cdb70b86f4..8e799ca1a4303 100644
--- a/src/test/run-make/reproducible-build/Makefile
+++ b/src/test/run-make/reproducible-build/Makefile
@@ -3,18 +3,18 @@ all:
 	$(RUSTC) reproducible-build-aux.rs
 	$(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build1"
 	$(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build2"
-	nm "$(TMPDIR)/reproducible-build1" | awk '{ print $2 " " $3 }' | sort > "$(TMPDIR)/reproducible-build1.nm"
-	nm "$(TMPDIR)/reproducible-build2" | awk '{ print $2 " " $3 }' | sort > "$(TMPDIR)/reproducible-build2.nm"
+	nm "$(TMPDIR)/reproducible-build1" | sort > "$(TMPDIR)/reproducible-build1.nm"
+	nm "$(TMPDIR)/reproducible-build2" | sort > "$(TMPDIR)/reproducible-build2.nm"
 	cmp "$(TMPDIR)/reproducible-build1.nm" "$(TMPDIR)/reproducible-build2.nm" || exit 1
 	$(RUSTC) reproducible-build-aux.rs -g
 	$(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build1-debug"
 	$(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build2-debug"
-	nm "$(TMPDIR)/reproducible-build1-debug" | awk '{ print $2 " " $3 }' | sort > "$(TMPDIR)/reproducible-build1-debug.nm"
-	nm "$(TMPDIR)/reproducible-build2-debug" | awk '{ print $2 " " $3 }' | sort > "$(TMPDIR)/reproducible-build2-debug.nm"
+	nm "$(TMPDIR)/reproducible-build1-debug" | sort > "$(TMPDIR)/reproducible-build1-debug.nm"
+	nm "$(TMPDIR)/reproducible-build2-debug" | sort > "$(TMPDIR)/reproducible-build2-debug.nm"
 	cmp "$(TMPDIR)/reproducible-build1-debug.nm" "$(TMPDIR)/reproducible-build2-debug.nm" || exit 1
 	$(RUSTC) reproducible-build-aux.rs -O
 	$(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build1-opt"
 	$(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build2-opt"
-	nm "$(TMPDIR)/reproducible-build1-opt" | awk '{ print $2 " " $3 }' | sort > "$(TMPDIR)/reproducible-build1-opt.nm"
-	nm "$(TMPDIR)/reproducible-build2-opt" | awk '{ print $2 " " $3 }' | sort > "$(TMPDIR)/reproducible-build2-opt.nm"
+	nm "$(TMPDIR)/reproducible-build1-opt" | sort > "$(TMPDIR)/reproducible-build1-opt.nm"
+	nm "$(TMPDIR)/reproducible-build2-opt" | sort > "$(TMPDIR)/reproducible-build2-opt.nm"
 	cmp "$(TMPDIR)/reproducible-build1-opt.nm" "$(TMPDIR)/reproducible-build2-opt.nm" || exit 1

From dbbba553828b1763951fc0eb02fa436ac61d9a95 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Sat, 23 Dec 2017 00:47:25 +0100
Subject: [PATCH 19/25] Rework the exit failure and success declaration for
 wasm32

---
 src/libstd/termination.rs | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/src/libstd/termination.rs b/src/libstd/termination.rs
index cfbeff0de1550..61137ba492299 100644
--- a/src/libstd/termination.rs
+++ b/src/libstd/termination.rs
@@ -9,7 +9,17 @@
 // except according to those terms.
 
 use error::Error;
-use libc;
+#[cfg(target_arch = "wasm32")]
+mod exit {
+    pub const SUCCESS: i32 = 0;
+    pub const FAILURE: i32 = 1;
+}
+#[cfg(not(target_arch = "wasm32"))]
+mod exit {
+    use libc;
+    pub const SUCCESS: i32 = libc::EXIT_SUCCESS;
+    pub const FAILURE: i32 = libc::EXIT_FAILURE;
+}
 
 /// A trait for implementing arbitrary return types in the `main` function.
 ///
@@ -31,7 +41,7 @@ pub trait Termination {
 
 #[unstable(feature = "termination_trait", issue = "43301")]
 impl Termination for () {
-    fn report(self) -> i32 { libc::EXIT_SUCCESS }
+    fn report(self) -> i32 { exit::SUCCESS }
 }
 
 #[unstable(feature = "termination_trait", issue = "43301")]
@@ -41,7 +51,7 @@ impl<T: Termination, E: Error> Termination for Result<T, E> {
             Ok(val) => val.report(),
             Err(err) => {
                 print_error(err);
-                libc::EXIT_FAILURE
+                exit::FAILURE
             }
         }
     }
@@ -64,7 +74,7 @@ impl Termination for ! {
 #[unstable(feature = "termination_trait", issue = "43301")]
 impl Termination for bool {
     fn report(self) -> i32 {
-        if self { libc::EXIT_SUCCESS } else { libc::EXIT_FAILURE }
+        if self { exit::SUCCESS } else { exit::FAILURE }
     }
 }
 

From c2f22f01a9263870d33a26e988bb13b8f622ce7a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Sat, 23 Dec 2017 01:30:36 +0100
Subject: [PATCH 20/25] Adds whitespace

---
 src/librustc_mir/monomorphize/collector.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index ccb648cd92988..10fa379924b1f 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -194,7 +194,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir::map as hir_map;
 use rustc::hir::def_id::DefId;
 use rustc::middle::const_val::ConstVal;
-use rustc::middle::lang_items::{ExchangeMallocFnLangItem,StartFnLangItem};
+use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
 use rustc::traits;
 use rustc::ty::subst::{Substs, Kind};
 use rustc::ty::{self, TypeFoldable, Ty, TyCtxt};

From 7dfec34a20af59e50f59f73799f471795a50eeb8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Sun, 24 Dec 2017 00:15:38 +0100
Subject: [PATCH 21/25] Split `lang_start` in two functions to reduce generated
 code

---
 src/libstd/rt.rs | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs
index 1fd7c270d1941..27c20be7a9a32 100644
--- a/src/libstd/rt.rs
+++ b/src/libstd/rt.rs
@@ -26,10 +26,11 @@
 // Reexport some of our utilities which are expected by other crates.
 pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
 
+// To reduce the generated code of the new `lang_start`, this function is doing
+// the real work.
 #[cfg(not(any(test, stage0)))]
-#[lang = "start"]
-fn lang_start<T: ::termination::Termination + 'static>
-    (main: fn() -> T, argc: isize, argv: *const *const u8) -> !
+fn lang_start_real<F>(main: F, argc: isize, argv: *const *const u8) -> !
+    where F: FnOnce() -> i32 + Send + ::panic::UnwindSafe + 'static
 {
     use panic;
     use sys;
@@ -59,16 +60,24 @@ fn lang_start<T: ::termination::Termination + 'static>
         // Let's run some code!
         #[cfg(feature = "backtrace")]
         let exit_code = panic::catch_unwind(|| {
-            ::sys_common::backtrace::__rust_begin_short_backtrace(move || main().report())
+            ::sys_common::backtrace::__rust_begin_short_backtrace(move || main())
         });
         #[cfg(not(feature = "backtrace"))]
-        let exit_code = panic::catch_unwind(move || main().report());
+        let exit_code = panic::catch_unwind(move || main());
 
         sys_common::cleanup();
         exit_code.unwrap_or(101)
     });
 }
 
+#[cfg(not(any(test, stage0)))]
+#[lang = "start"]
+fn lang_start<T: ::termination::Termination + 'static>
+    (main: fn() -> T, argc: isize, argv: *const *const u8) -> !
+{
+    lang_start_real(move || main().report(), argc, argv)
+}
+
 #[cfg(all(not(test), stage0))]
 #[lang = "start"]
 fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize {

From 81e375dba5e7915548dc6067cf16c62cdbce4853 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Sun, 24 Dec 2017 00:35:38 +0100
Subject: [PATCH 22/25] Change name of `lang_start_real` to
 `lang_start_internal`

Also remove `'static` from `__rust_begin_short_backtrace`
---
 src/libstd/rt.rs                   | 7 +++----
 src/libstd/sys_common/backtrace.rs | 2 +-
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs
index 27c20be7a9a32..d17dfb25f311b 100644
--- a/src/libstd/rt.rs
+++ b/src/libstd/rt.rs
@@ -29,9 +29,8 @@ pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
 // To reduce the generated code of the new `lang_start`, this function is doing
 // the real work.
 #[cfg(not(any(test, stage0)))]
-fn lang_start_real<F>(main: F, argc: isize, argv: *const *const u8) -> !
-    where F: FnOnce() -> i32 + Send + ::panic::UnwindSafe + 'static
-{
+fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe),
+                       argc: isize, argv: *const *const u8) -> ! {
     use panic;
     use sys;
     use sys_common;
@@ -75,7 +74,7 @@ fn lang_start_real<F>(main: F, argc: isize, argv: *const *const u8) -> !
 fn lang_start<T: ::termination::Termination + 'static>
     (main: fn() -> T, argc: isize, argv: *const *const u8) -> !
 {
-    lang_start_real(move || main().report(), argc, argv)
+    lang_start_internal(&move || main().report(), argc, argv)
 }
 
 #[cfg(all(not(test), stage0))]
diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs
index b5cf6d7d34fcc..36cbce2df75b5 100644
--- a/src/libstd/sys_common/backtrace.rs
+++ b/src/libstd/sys_common/backtrace.rs
@@ -128,7 +128,7 @@ fn filter_frames(frames: &[Frame],
 /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
 #[inline(never)]
 pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
-    where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
+    where F: FnOnce() -> T, F: Send, T: Send
 {
     f()
 }

From 2cdd1c4df36db6a3d26d2a48afdf715e7fb6d689 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Tue, 26 Dec 2017 14:26:03 -0800
Subject: [PATCH 23/25] rustc: Switch `start_fn` to hidden visibility

This'll avoid exporting a symbol from binaries unnecessarily and should help the
linker clean things up if it can.
---
 src/librustc_mir/monomorphize/partitioning.rs | 26 ++++++++++++++++---
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index 1a4849ac199a0..55c194ae7a584 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -305,6 +305,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let codegen_unit = codegen_units.entry(codegen_unit_name.clone())
                                             .or_insert_with(make_codegen_unit);
 
+        let mut can_be_internalized = true;
         let (linkage, visibility) = match trans_item.explicit_linkage(tcx) {
             Some(explicit_linkage) => (explicit_linkage, Visibility::Default),
             None => {
@@ -312,10 +313,27 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     MonoItem::Fn(ref instance) => {
                         let visibility = match instance.def {
                             InstanceDef::Item(def_id) => {
-                                // If we encounter the lang start item, we set the visibility to
-                                // default.
+                                // The `start_fn` lang item is actually a
+                                // monomorphized instance of a function in the
+                                // standard library, used for the `main`
+                                // function. We don't want to export it so we
+                                // tag it with `Hidden` visibility but this
+                                // symbol is only referenced from the actual
+                                // `main` symbol which we unfortunately don't
+                                // know anything about during
+                                // partitioning/collection. As a result we
+                                // forcibly keep this symbol out of the
+                                // `internalization_candidates` set.
+                                //
+                                // FIXME: eventually we don't want to always
+                                // force this symbol to have hidden
+                                // visibility, it should indeed be a candidate
+                                // for internalization, but we have to
+                                // understand that it's referenced from the
+                                // `main` symbol we'll generate later.
                                 if tcx.lang_items().start_fn() == Some(def_id) {
-                                    Visibility::Default
+                                    can_be_internalized = false;
+                                    Visibility::Hidden
                                 } else if def_id.is_local() {
                                     if tcx.is_exported_symbol(def_id) {
                                         Visibility::Default
@@ -350,7 +368,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 }
             }
         };
-        if visibility == Visibility::Hidden {
+        if visibility == Visibility::Hidden && can_be_internalized {
             internalization_candidates.insert(trans_item);
         }
 

From 5a4298b6d36c493cabeae1453119d1edc96e1472 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Tue, 26 Dec 2017 23:52:20 +0100
Subject: [PATCH 24/25] Don't use `process::exit` as it is an `unreachable` on
 wasm32

---
 src/librustc_trans/base.rs | 12 ++----------
 src/libstd/rt.rs           | 11 +++++------
 2 files changed, 7 insertions(+), 16 deletions(-)

diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 3955171f93980..680821d6d681e 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -552,10 +552,7 @@ fn maybe_create_entry_wrapper(ccx: &CrateContext) {
                        rust_main: ValueRef,
                        rust_main_def_id: DefId,
                        use_start_lang_item: bool) {
-        // The libstd lang_start function does not return anything, while user defined lang start
-        // returns a isize
-        let start_output_ty = if use_start_lang_item { Type::void(ccx) } else { Type::c_int(ccx) };
-        let llfty = Type::func(&[Type::c_int(ccx), Type::i8p(ccx).ptr_to()], &start_output_ty);
+        let llfty = Type::func(&[Type::c_int(ccx), Type::i8p(ccx).ptr_to()], &Type::c_int(ccx));
 
         let main_ret_ty = ccx.tcx().fn_sig(rust_main_def_id).output();
         // Given that `main()` has no arguments,
@@ -600,12 +597,7 @@ fn maybe_create_entry_wrapper(ccx: &CrateContext) {
         };
 
         let result = bld.call(start_fn, &args, None);
-
-        if use_start_lang_item {
-            bld.ret_void();
-        } else {
-            bld.ret(bld.intcast(result, Type::c_int(ccx), true));
-        }
+        bld.ret(bld.intcast(result, Type::c_int(ccx), true));
     }
 }
 
diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs
index d17dfb25f311b..e2c1bba50c409 100644
--- a/src/libstd/rt.rs
+++ b/src/libstd/rt.rs
@@ -30,19 +30,18 @@ pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
 // the real work.
 #[cfg(not(any(test, stage0)))]
 fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe),
-                       argc: isize, argv: *const *const u8) -> ! {
+                       argc: isize, argv: *const *const u8) -> isize {
     use panic;
     use sys;
     use sys_common;
     use sys_common::thread_info;
     use thread::Thread;
-    use process;
     #[cfg(not(feature = "backtrace"))]
     use mem;
 
     sys::init();
 
-    process::exit(unsafe {
+    unsafe {
         let main_guard = sys::thread::guard::init();
         sys::stack_overflow::init();
 
@@ -65,14 +64,14 @@ fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe),
         let exit_code = panic::catch_unwind(move || main());
 
         sys_common::cleanup();
-        exit_code.unwrap_or(101)
-    });
+        exit_code.unwrap_or(101) as isize
+    }
 }
 
 #[cfg(not(any(test, stage0)))]
 #[lang = "start"]
 fn lang_start<T: ::termination::Termination + 'static>
-    (main: fn() -> T, argc: isize, argv: *const *const u8) -> !
+    (main: fn() -> T, argc: isize, argv: *const *const u8) -> isize
 {
     lang_start_internal(&move || main().report(), argc, argv)
 }

From 09f94bea4aca7696b58dd7e6668ca27d71908984 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Wed, 27 Dec 2017 01:23:28 +0100
Subject: [PATCH 25/25] Revert "New generated main returns void"

This reverts commit 267800a7c0834dd8ca93a82a20cb0cdd9e7dc025.
---
 src/test/codegen/abi-main-signature-16bit-c-int.rs | 2 +-
 src/test/codegen/abi-main-signature-32bit-c-int.rs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/test/codegen/abi-main-signature-16bit-c-int.rs b/src/test/codegen/abi-main-signature-16bit-c-int.rs
index 55863ab163314..fbe2fd10e7a14 100644
--- a/src/test/codegen/abi-main-signature-16bit-c-int.rs
+++ b/src/test/codegen/abi-main-signature-16bit-c-int.rs
@@ -29,4 +29,4 @@
 fn main() {
 }
 
-// CHECK: define void @main(i16, i8**)
+// CHECK: define i16 @main(i16, i8**)
diff --git a/src/test/codegen/abi-main-signature-32bit-c-int.rs b/src/test/codegen/abi-main-signature-32bit-c-int.rs
index d7c70354ee0cc..3139749dfcb06 100644
--- a/src/test/codegen/abi-main-signature-32bit-c-int.rs
+++ b/src/test/codegen/abi-main-signature-32bit-c-int.rs
@@ -17,4 +17,4 @@
 fn main() {
 }
 
-// CHECK: define void @main(i32, i8**)
+// CHECK: define i32 @main(i32, i8**)