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/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); diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 0b8666800a5a5..10fa379924b1f 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -194,11 +194,12 @@ 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::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 +213,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 +332,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 +956,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 +970,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 +992,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_mono_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 = main_ret_ty.no_late_bound_regions().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_mono_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..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,7 +313,28 @@ 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() { + // 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) { + can_be_internalized = false; + Visibility::Hidden + } else if def_id.is_local() { if tcx.is_exported_symbol(def_id) { Visibility::Default } else { @@ -346,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); } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 0efe5f9a5cb6f..680821d6d681e 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,18 +542,26 @@ 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)); + 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 = 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. ccx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times") @@ -577,8 +587,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 { @@ -587,8 +597,6 @@ 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)); } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ab81d26e77175..7a49c3549abdf 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -96,14 +96,14 @@ use rustc::middle::region; 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 +115,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 +1065,30 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, } fcx.demand_suptype(span, ret_ty, actual_return_ty); + 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())); + }, + _ => {}, + } + } + } + } + } + (fcx, gen_ty) } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 129511ee64c62..0b2f59abf4f78 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -116,6 +116,7 @@ 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,10 +201,22 @@ 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() + && 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() + } else { + // standard () main return type + tcx.mk_nil() + }; + let se_ty = tcx.mk_fn_ptr(ty::Binder( tcx.mk_fn_sig( iter::empty(), - tcx.mk_nil(), + expected_return_type, false, hir::Unsafety::Normal, Abi::Rust @@ -214,7 +227,7 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx, &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType), se_ty, - tcx.mk_fn_ptr(tcx.fn_sig(main_def_id))); + tcx.mk_fn_ptr(actual)); } _ => { span_bug!(main_span, diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 12e6231136e16..171c108e3aa55 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 = "43301")] +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..e2c1bba50c409 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -26,7 +26,57 @@ // 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))] +// 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_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe), + argc: isize, argv: *const *const u8) -> isize { + use panic; + use sys; + use sys_common; + use sys_common::thread_info; + use thread::Thread; + #[cfg(not(feature = "backtrace"))] + use mem; + + sys::init(); + + 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()) + }); + #[cfg(not(feature = "backtrace"))] + let exit_code = panic::catch_unwind(move || main()); + + sys_common::cleanup(); + exit_code.unwrap_or(101) as isize + } +} + +#[cfg(not(any(test, stage0)))] +#[lang = "start"] +fn lang_start + (main: fn() -> T, argc: isize, argv: *const *const u8) -> isize +{ + lang_start_internal(&move || main().report(), argc, argv) +} + +#[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/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: F) -> T - where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static + where F: FnOnce() -> T, F: Send, T: Send { f() } diff --git a/src/libstd/termination.rs b/src/libstd/termination.rs new file mode 100644 index 0000000000000..61137ba492299 --- /dev/null +++ b/src/libstd/termination.rs @@ -0,0 +1,86 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use error::Error; +#[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. +/// +/// 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(any(stage0, test)), lang = "termination")] +#[unstable(feature = "termination_trait", issue = "43301")] +#[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. + fn report(self) -> i32; +} + +#[unstable(feature = "termination_trait", issue = "43301")] +impl Termination for () { + fn report(self) -> i32 { exit::SUCCESS } +} + +#[unstable(feature = "termination_trait", issue = "43301")] +impl Termination for Result { + fn report(self) -> i32 { + match self { + Ok(val) => val.report(), + Err(err) => { + print_error(err); + exit::FAILURE + } + } + } +} + +#[unstable(feature = "termination_trait", issue = "43301")] +fn print_error(err: E) { + eprintln!("Error: {}", err.description()); + + if let Some(ref err) = err.cause() { + eprintln!("Caused by: {}", err.description()); + } +} + +#[unstable(feature = "termination_trait", issue = "43301")] +impl Termination for ! { + fn report(self) -> i32 { unreachable!(); } +} + +#[unstable(feature = "termination_trait", issue = "43301")] +impl Termination for bool { + fn report(self) -> i32 { + if self { exit::SUCCESS } else { exit::FAILURE } + } +} + +#[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/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 eb4f9e8e28e2d..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,13 +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 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] //~ TRANS_ITEM fn cgu_generic_function::foo[0] let _ = cgu_generic_function::foo(1u32); @@ -29,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 195125793be8a..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,15 +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 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); @@ -55,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] 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 b8033b88fb75e..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_intrinsic0[Internal] struct StructWithDtor(u32); @@ -20,13 +22,16 @@ impl Drop for StructWithDtor { fn drop(&mut self) {} } -//~ 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 c3d46ff5314fe..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(f: F, x: T1, y: T2) { (f)(x, y) @@ -23,8 +24,9 @@ fn take_fn_pointer(f: fn(T1, T2), x: T1, y: T2) { (f)(x, y) } -//~ 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] //~ TRANS_ITEM fn function_as_argument::function[0] @@ -43,4 +45,6 @@ fn main() { //~ TRANS_ITEM fn function_as_argument::take_fn_pointer[0] //~ TRANS_ITEM fn function_as_argument::function[0] 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 65936d12e316f..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 { x: T1, @@ -53,8 +54,9 @@ impl Drop for NonGenericWithDrop { fn drop(&mut self) {} } -//~ 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_glue0[Internal] //~ TRANS_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0] let _ = StructWithDrop { x: 0i8, y: 'a' }.x; @@ -94,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 afe6ffc8bfe03..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(a: T1) -> (T1, u32) { (a, 1) @@ -31,8 +32,9 @@ pub fn lifetime_only<'a>(a: &'a u32) -> &'a u32 { a } -//~ 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] let _ = foo1(2i32); //~ TRANS_ITEM fn generic_functions::foo1[0] @@ -59,4 +61,6 @@ fn main() { let _ = foo3(0i16, "a", 2usize); //~ TRANS_ITEM fn generic_functions::foo3[0] 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 14316a557328b..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 { x: T, @@ -50,9 +51,9 @@ impl<'a> LifeTimeOnly<'a> { pub fn non_instantiated(&self) {} } - -//~ 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] //~ TRANS_ITEM fn generic_impl::id[0] //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::get[0] @@ -76,4 +77,6 @@ fn main() { //~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]> //~ TRANS_ITEM fn generic_impl::id[0]> 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 c43c254f33911..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,7 +29,10 @@ pub fn generic_function(x: T) -> (T, i32) { (x, 0) } -//~ 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 e32366d15c337..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,8 +29,9 @@ impl Trait for Struct { fn bar(&self) {} } -//~ 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_vtable0[Internal] @@ -42,4 +44,6 @@ fn main() { //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0] //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0] 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 75d842d3c0bfc..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(a: T) -> (T, i32) { //~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]::nested_fn[0] @@ -31,12 +32,15 @@ fn generic_fn(a: T) -> (T, i32) { return (a, x + nested_fn(0)); } -//~ 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] let _ = generic_fn(0i64); //~ TRANS_ITEM fn items_within_generic_items::generic_fn[0] let _ = generic_fn(0u16); //~ TRANS_ITEM fn items_within_generic_items::generic_fn[0] 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 5765f230e8bd4..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_glue0[Internal] struct StructWithDrop { @@ -42,8 +43,9 @@ enum EnumNoDrop { A(i32) } -//~ 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) { @@ -52,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 26f9eb11876cb..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,11 +70,14 @@ impl Struct { } } -//~ 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 3c9dcf32e0c78..5ff7c3480b126 100644 --- a/src/test/codegen-units/item-collection/static-init.rs +++ b/src/test/codegen-units/item-collection/static-init.rs @@ -9,6 +9,9 @@ // except according to those terms. // compile-flags:-Zprint-trans-items=eager +// ignore-tidy-linelength + +#![feature(start)] pub static FN : fn() = foo::; @@ -17,6 +20,9 @@ pub fn foo() { } //~ TRANS_ITEM fn static_init::foo[0] //~ 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 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..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,5 +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 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..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,8 +56,9 @@ impl SomeGenericTrait for f32 { fn bar(&self, _: T, _: T2) {} } -//~ 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] 0i32.bar('x'); @@ -77,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 21c9c254e51cf..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,8 +37,9 @@ fn take_foo_mut T>(mut f: F, arg: T) -> T { (f)(arg) } -//~ 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> //~ TRANS_ITEM fn trait_method_as_argument::{{impl}}[0]::foo[0] //~ TRANS_ITEM fn core::ops[0]::function[0]::FnOnce[0]::call_once[0] u32, (u32)> @@ -63,4 +65,6 @@ fn main() { //~ TRANS_ITEM fn trait_method_as_argument::take_foo_mut[0] char> //~ TRANS_ITEM fn core::ops[0]::function[0]::FnMut[0]::call_mut[0] 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 5b24a219f354b..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,8 +47,9 @@ impl SomeGenericTrait for u32 { // since nothing is monomorphic here, nothing should be generated unless used somewhere. } -//~ 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] let _ = 1i8.bar('c'); @@ -65,4 +67,6 @@ fn main() { //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] 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 be560690e5190..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_glue0[Internal] struct Root(Intermediate); @@ -34,9 +35,9 @@ impl Drop for LeafGen { fn drop(&mut self) {} } -//~ 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_glue0[Internal] @@ -50,4 +51,6 @@ fn main() { //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue0[Internal] //~ TRANS_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0] 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 ad1475a73f7cc..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_glue0[Internal] struct Dropped; @@ -22,12 +23,15 @@ impl Drop for Dropped { fn drop(&mut self) {} } -//~ 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 d7e457cde8a90..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,9 +54,9 @@ struct Wrapper(*const T); impl, U: ?Sized> CoerceUnsized> for Wrapper {} -//~ 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] @@ unsizing0[Internal] @@ -83,4 +84,6 @@ fn main() //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing0[Internal] //~ TRANS_ITEM fn unsizing::{{impl}}[3]::foo[0] let _wrapper_sized = wrapper_sized as Wrapper; + + 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] @@ 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] @@ 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.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 302f9312b5709..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(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 = &0u32 as &Trait1Gen; pub const ID_CHAR: fn(char) -> char = id::; @@ -68,8 +70,9 @@ mod mod1 { pub const ID_I64: fn(i64) -> i64 = id::; } -//~ 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] @@ vtable_through_const[Internal] // Since Trait1::do_something() is instantiated via its default implementation, @@ -90,4 +93,6 @@ fn main() { //~ TRANS_ITEM fn vtable_through_const::mod1[0]::id[0] @@ vtable_through_const-mod1.volatile[External] mod1::ID_CHAR('x'); + + 0 } 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**) 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 or the MIT license +// , 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/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 @@ // , 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 ' ' } 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..788c38c55be0a --- /dev/null +++ b/src/test/compile-fail/termination-trait-not-satisfied.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 or the MIT license +// , at your +// 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 + ReturnType {} +} 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 } diff --git a/src/test/compile-fail/E0580.rs b/src/test/run-pass/termination-trait-for-empty.rs similarity index 78% rename from src/test/compile-fail/E0580.rs rename to src/test/run-pass/termination-trait-for-empty.rs index a2ef7da78a843..5e534da012875 100644 --- a/src/test/compile-fail/E0580.rs +++ b/src/test/run-pass/termination-trait-for-empty.rs @@ -1,4 +1,4 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,4 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() -> i32 { 0 } //~ ERROR E0580 +#![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 or the MIT license +// , 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 or the MIT license +// , 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(()) +} 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(x: T) { Pair::new(FiftyBytes::new(), FiftyBytes::new()); } -pub fn main() { +#[start] +fn start(_: isize, _: *const *const u8) -> isize { let _b: Pair = Pair::new(0, 0); let _s: Pair = Pair::new(SevenBytes::new(), SevenBytes::new()); let _z: ZeroSized = ZeroSized; f1::(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 { Four(D) } -pub fn main() { +#[start] +fn start(_: isize, _: *const *const u8) -> isize { let _x: MyOption> = Default::default(); let _y: EmbeddedDiscr = Default::default(); let _z: MyOption> = 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> = 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 = 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 }