Auto merge of #46479 - bkchr:termination_trait, r=arielb1
Implements RFC 1937: `?` in `main` This is the first part of the RFC 1937 that supports new `Termination` trait in the rust `main` function. Thanks @nikomatsakis, @arielb1 and all other people in the gitter channel for all your help! The support for doctest and `#[test]` is still missing, bu as @nikomatsakis said, smaller pull requests are better :)
This commit is contained in:
commit
bfbb1f5ce1
|
@ -338,6 +338,8 @@ language_item_table! {
|
||||||
U128ShloFnLangItem, "u128_shlo", u128_shlo_fn;
|
U128ShloFnLangItem, "u128_shlo", u128_shlo_fn;
|
||||||
I128ShroFnLangItem, "i128_shro", i128_shro_fn;
|
I128ShroFnLangItem, "i128_shro", i128_shro_fn;
|
||||||
U128ShroFnLangItem, "u128_shro", u128_shro_fn;
|
U128ShroFnLangItem, "u128_shro", u128_shro_fn;
|
||||||
|
|
||||||
|
TerminationTraitLangItem, "termination", termination;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx, 'gcx> TyCtxt<'a, 'tcx, 'gcx> {
|
impl<'a, 'tcx, 'gcx> TyCtxt<'a, 'tcx, 'gcx> {
|
||||||
|
|
|
@ -155,11 +155,19 @@ impl CodeStats {
|
||||||
|
|
||||||
// Include field alignment in output only if it caused padding injection
|
// Include field alignment in output only if it caused padding injection
|
||||||
if min_offset != offset {
|
if min_offset != offset {
|
||||||
let pad = offset - min_offset;
|
if offset > min_offset {
|
||||||
println!("print-type-size {}padding: {} bytes",
|
let pad = offset - min_offset;
|
||||||
indent, pad);
|
println!("print-type-size {}padding: {} bytes",
|
||||||
println!("print-type-size {}field `.{}`: {} bytes, alignment: {} bytes",
|
indent, pad);
|
||||||
indent, name, size, align);
|
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 {
|
} else {
|
||||||
println!("print-type-size {}field `.{}`: {} bytes",
|
println!("print-type-size {}field `.{}`: {} bytes",
|
||||||
indent, name, size);
|
indent, name, size);
|
||||||
|
|
|
@ -194,11 +194,12 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||||
use rustc::hir::map as hir_map;
|
use rustc::hir::map as hir_map;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::middle::const_val::ConstVal;
|
use rustc::middle::const_val::ConstVal;
|
||||||
use rustc::middle::lang_items::{ExchangeMallocFnLangItem};
|
use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
|
||||||
use rustc::traits;
|
use rustc::traits;
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::{Substs, Kind};
|
||||||
use rustc::ty::{self, TypeFoldable, Ty, TyCtxt};
|
use rustc::ty::{self, TypeFoldable, Ty, TyCtxt};
|
||||||
use rustc::ty::adjustment::CustomCoerceUnsized;
|
use rustc::ty::adjustment::CustomCoerceUnsized;
|
||||||
|
use rustc::session::config;
|
||||||
use rustc::mir::{self, Location};
|
use rustc::mir::{self, Location};
|
||||||
use rustc::mir::visit::Visitor as MirVisitor;
|
use rustc::mir::visit::Visitor as MirVisitor;
|
||||||
use rustc::mir::mono::MonoItem;
|
use rustc::mir::mono::MonoItem;
|
||||||
|
@ -212,6 +213,8 @@ use rustc_data_structures::bitvec::BitVector;
|
||||||
|
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
|
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
|
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
|
||||||
pub enum MonoItemCollectionMode {
|
pub enum MonoItemCollectionMode {
|
||||||
Eager,
|
Eager,
|
||||||
|
@ -329,6 +332,8 @@ fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
tcx.hir.local_def_id(node_id)
|
tcx.hir.local_def_id(node_id)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
debug!("collect_roots: entry_fn = {:?}", entry_fn);
|
||||||
|
|
||||||
let mut visitor = RootCollector {
|
let mut visitor = RootCollector {
|
||||||
tcx,
|
tcx,
|
||||||
mode,
|
mode,
|
||||||
|
@ -951,16 +956,8 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
|
||||||
// actually used somewhere. Just declaring them is insufficient.
|
// actually used somewhere. Just declaring them is insufficient.
|
||||||
}
|
}
|
||||||
hir::ItemFn(..) => {
|
hir::ItemFn(..) => {
|
||||||
let tcx = self.tcx;
|
let def_id = self.tcx.hir.local_def_id(item.id);
|
||||||
let def_id = tcx.hir.local_def_id(item.id);
|
self.push_if_root(def_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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
|
||||||
match ii.node {
|
match ii.node {
|
||||||
hir::ImplItemKind::Method(hir::MethodSig { .. }, _) => {
|
hir::ImplItemKind::Method(hir::MethodSig { .. }, _) => {
|
||||||
let tcx = self.tcx;
|
let def_id = self.tcx.hir.local_def_id(ii.id);
|
||||||
let def_id = tcx.hir.local_def_id(ii.id);
|
self.push_if_root(def_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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => { /* Nothing to do here */ }
|
_ => { /* 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 {
|
fn item_has_type_parameters<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
|
||||||
|
|
|
@ -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())
|
let codegen_unit = codegen_units.entry(codegen_unit_name.clone())
|
||||||
.or_insert_with(make_codegen_unit);
|
.or_insert_with(make_codegen_unit);
|
||||||
|
|
||||||
|
let mut can_be_internalized = true;
|
||||||
let (linkage, visibility) = match trans_item.explicit_linkage(tcx) {
|
let (linkage, visibility) = match trans_item.explicit_linkage(tcx) {
|
||||||
Some(explicit_linkage) => (explicit_linkage, Visibility::Default),
|
Some(explicit_linkage) => (explicit_linkage, Visibility::Default),
|
||||||
None => {
|
None => {
|
||||||
|
@ -312,7 +313,28 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
MonoItem::Fn(ref instance) => {
|
MonoItem::Fn(ref instance) => {
|
||||||
let visibility = match instance.def {
|
let visibility = match instance.def {
|
||||||
InstanceDef::Item(def_id) => {
|
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) {
|
if tcx.is_exported_symbol(def_id) {
|
||||||
Visibility::Default
|
Visibility::Default
|
||||||
} else {
|
} 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);
|
internalization_candidates.insert(trans_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ use rustc::ty::{self, Ty, TyCtxt};
|
||||||
use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
|
use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
|
||||||
use rustc::ty::maps::Providers;
|
use rustc::ty::maps::Providers;
|
||||||
use rustc::dep_graph::{DepNode, DepConstructor};
|
use rustc::dep_graph::{DepNode, DepConstructor};
|
||||||
|
use rustc::ty::subst::Kind;
|
||||||
use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
|
use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
|
||||||
use rustc::util::common::{time, print_time_passes_entry};
|
use rustc::util::common::{time, print_time_passes_entry};
|
||||||
use rustc::session::config::{self, NoDebugInfo};
|
use rustc::session::config::{self, NoDebugInfo};
|
||||||
|
@ -79,6 +80,7 @@ use std::str;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Instant, Duration};
|
use std::time::{Instant, Duration};
|
||||||
use std::i32;
|
use std::i32;
|
||||||
|
use std::iter;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
use syntax_pos::symbol::InternedString;
|
use syntax_pos::symbol::InternedString;
|
||||||
|
@ -540,18 +542,26 @@ fn maybe_create_entry_wrapper(ccx: &CrateContext) {
|
||||||
|
|
||||||
let et = ccx.sess().entry_type.get().unwrap();
|
let et = ccx.sess().entry_type.get().unwrap();
|
||||||
match et {
|
match et {
|
||||||
config::EntryMain => create_entry_fn(ccx, span, main_llfn, true),
|
config::EntryMain => create_entry_fn(ccx, span, main_llfn, main_def_id, true),
|
||||||
config::EntryStart => create_entry_fn(ccx, span, main_llfn, false),
|
config::EntryStart => create_entry_fn(ccx, span, main_llfn, main_def_id, false),
|
||||||
config::EntryNone => {} // Do nothing.
|
config::EntryNone => {} // Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_entry_fn(ccx: &CrateContext,
|
fn create_entry_fn<'ccx>(ccx: &'ccx CrateContext,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
rust_main: ValueRef,
|
rust_main: ValueRef,
|
||||||
|
rust_main_def_id: DefId,
|
||||||
use_start_lang_item: bool) {
|
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 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() {
|
if declare::get_defined_value(ccx, "main").is_some() {
|
||||||
// FIXME: We should be smart and show a better diagnostic here.
|
// FIXME: We should be smart and show a better diagnostic here.
|
||||||
ccx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times")
|
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_fn, args) = if use_start_lang_item {
|
||||||
let start_def_id = ccx.tcx().require_lang_item(StartFnLangItem);
|
let start_def_id = ccx.tcx().require_lang_item(StartFnLangItem);
|
||||||
let start_instance = Instance::mono(ccx.tcx(), start_def_id);
|
let start_fn = callee::resolve_and_get_fn(ccx, start_def_id, ccx.tcx().mk_substs(
|
||||||
let start_fn = callee::get_fn(ccx, start_instance);
|
iter::once(Kind::from(main_ret_ty))));
|
||||||
(start_fn, vec![bld.pointercast(rust_main, Type::i8p(ccx).ptr_to()),
|
(start_fn, vec![bld.pointercast(rust_main, Type::i8p(ccx).ptr_to()),
|
||||||
arg_argc, arg_argv])
|
arg_argc, arg_argv])
|
||||||
} else {
|
} else {
|
||||||
|
@ -587,8 +597,6 @@ fn maybe_create_entry_wrapper(ccx: &CrateContext) {
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = bld.call(start_fn, &args, None);
|
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));
|
bld.ret(bld.intcast(result, Type::c_int(ccx), true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,14 +96,14 @@ use rustc::middle::region;
|
||||||
use rustc::ty::subst::{Kind, Subst, Substs};
|
use rustc::ty::subst::{Kind, Subst, Substs};
|
||||||
use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode};
|
use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode};
|
||||||
use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue};
|
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::adjustment::{Adjust, Adjustment, AutoBorrow};
|
||||||
use rustc::ty::fold::TypeFoldable;
|
use rustc::ty::fold::TypeFoldable;
|
||||||
use rustc::ty::maps::Providers;
|
use rustc::ty::maps::Providers;
|
||||||
use rustc::ty::util::{Representability, IntTypeExt};
|
use rustc::ty::util::{Representability, IntTypeExt};
|
||||||
use errors::{DiagnosticBuilder, DiagnosticId};
|
use errors::{DiagnosticBuilder, DiagnosticId};
|
||||||
use require_c_abi_if_variadic;
|
use require_c_abi_if_variadic;
|
||||||
use session::{CompileIncomplete, Session};
|
use session::{CompileIncomplete, config, Session};
|
||||||
use TypeAndSubsts;
|
use TypeAndSubsts;
|
||||||
use lint;
|
use lint;
|
||||||
use util::common::{ErrorReported, indenter};
|
use util::common::{ErrorReported, indenter};
|
||||||
|
@ -115,6 +115,7 @@ use std::collections::hash_map::Entry;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
|
use std::iter;
|
||||||
use std::ops::{self, Deref};
|
use std::ops::{self, Deref};
|
||||||
use syntax::abi::Abi;
|
use syntax::abi::Abi;
|
||||||
use syntax::ast;
|
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);
|
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)
|
(fcx, gen_ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,7 @@ use syntax::abi::Abi;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
// NB: This module needs to be declared first so diagnostics are
|
// NB: This module needs to be declared first so diagnostics are
|
||||||
// registered before they are used.
|
// registered before they are used.
|
||||||
mod diagnostics;
|
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(
|
let se_ty = tcx.mk_fn_ptr(ty::Binder(
|
||||||
tcx.mk_fn_sig(
|
tcx.mk_fn_sig(
|
||||||
iter::empty(),
|
iter::empty(),
|
||||||
tcx.mk_nil(),
|
expected_return_type,
|
||||||
false,
|
false,
|
||||||
hir::Unsafety::Normal,
|
hir::Unsafety::Normal,
|
||||||
Abi::Rust
|
Abi::Rust
|
||||||
|
@ -214,7 +227,7 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
tcx,
|
tcx,
|
||||||
&ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
|
&ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
|
||||||
se_ty,
|
se_ty,
|
||||||
tcx.mk_fn_ptr(tcx.fn_sig(main_def_id)));
|
tcx.mk_fn_ptr(actual));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
span_bug!(main_span,
|
span_bug!(main_span,
|
||||||
|
|
|
@ -308,6 +308,7 @@
|
||||||
#![feature(str_char)]
|
#![feature(str_char)]
|
||||||
#![feature(str_internals)]
|
#![feature(str_internals)]
|
||||||
#![feature(str_utf16)]
|
#![feature(str_utf16)]
|
||||||
|
#![feature(termination_trait)]
|
||||||
#![feature(test, rustc_private)]
|
#![feature(test, rustc_private)]
|
||||||
#![feature(thread_local)]
|
#![feature(thread_local)]
|
||||||
#![feature(toowned_clone_into)]
|
#![feature(toowned_clone_into)]
|
||||||
|
@ -499,6 +500,11 @@ mod memchr;
|
||||||
// The runtime entry point and a few unstable public functions used by the
|
// The runtime entry point and a few unstable public functions used by the
|
||||||
// compiler
|
// compiler
|
||||||
pub mod rt;
|
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
|
// Include a number of private modules that exist solely to provide
|
||||||
// the rustdoc documentation for primitive types. Using `include!`
|
// the rustdoc documentation for primitive types. Using `include!`
|
||||||
|
|
|
@ -26,7 +26,57 @@
|
||||||
// Reexport some of our utilities which are expected by other crates.
|
// Reexport some of our utilities which are expected by other crates.
|
||||||
pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
|
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<T: ::termination::Termination + 'static>
|
||||||
|
(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"]
|
#[lang = "start"]
|
||||||
fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize {
|
fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize {
|
||||||
use panic;
|
use panic;
|
||||||
|
|
|
@ -128,7 +128,7 @@ fn filter_frames(frames: &[Frame],
|
||||||
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
|
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
|
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()
|
f()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 <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;
|
||||||
|
#[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<T: Termination, E: Error> Termination for Result<T, E> {
|
||||||
|
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<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 = "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
|
||||||
|
}
|
||||||
|
}
|
|
@ -444,6 +444,9 @@ declare_features! (
|
||||||
|
|
||||||
// Nested `impl Trait`
|
// Nested `impl Trait`
|
||||||
(active, nested_impl_trait, "1.24.0", Some(34511)),
|
(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! (
|
declare_features! (
|
||||||
|
|
|
@ -17,12 +17,14 @@
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
// aux-build:cgu_extern_closures.rs
|
// aux-build:cgu_extern_closures.rs
|
||||||
extern crate cgu_extern_closures;
|
extern crate cgu_extern_closures;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn cross_crate_closures::main[0]
|
//~ TRANS_ITEM fn cross_crate_closures::start[0]
|
||||||
fn main() {
|
#[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]
|
||||||
//~ TRANS_ITEM fn cgu_extern_closures::inlined_fn[0]::{{closure}}[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
|
// Nothing should be generated for this call, we just link to the instance
|
||||||
// in the extern crate.
|
// in the extern crate.
|
||||||
let _ = cgu_extern_closures::non_inlined_fn(6, 7);
|
let _ = cgu_extern_closures::non_inlined_fn(6, 7);
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM drop-glue i8
|
//~ TRANS_ITEM drop-glue i8
|
||||||
|
|
|
@ -12,13 +12,14 @@
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
// aux-build:cgu_generic_function.rs
|
// aux-build:cgu_generic_function.rs
|
||||||
extern crate cgu_generic_function;
|
extern crate cgu_generic_function;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn cross_crate_generic_functions::main[0]
|
//~ TRANS_ITEM fn cross_crate_generic_functions::start[0]
|
||||||
fn main()
|
#[start]
|
||||||
{
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
//~ TRANS_ITEM fn cgu_generic_function::bar[0]<u32>
|
//~ TRANS_ITEM fn cgu_generic_function::bar[0]<u32>
|
||||||
//~ TRANS_ITEM fn cgu_generic_function::foo[0]<u32>
|
//~ TRANS_ITEM fn cgu_generic_function::foo[0]<u32>
|
||||||
let _ = cgu_generic_function::foo(1u32);
|
let _ = cgu_generic_function::foo(1u32);
|
||||||
|
@ -29,4 +30,6 @@ fn main()
|
||||||
|
|
||||||
// This should not introduce a codegen item
|
// This should not introduce a codegen item
|
||||||
let _ = cgu_generic_function::exported_but_not_generic(3);
|
let _ = cgu_generic_function::exported_but_not_generic(3);
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,15 +12,16 @@
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
// aux-build:cgu_export_trait_method.rs
|
// aux-build:cgu_export_trait_method.rs
|
||||||
extern crate cgu_export_trait_method;
|
extern crate cgu_export_trait_method;
|
||||||
|
|
||||||
use cgu_export_trait_method::Trait;
|
use cgu_export_trait_method::Trait;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn cross_crate_trait_method::main[0]
|
//~ TRANS_ITEM fn cross_crate_trait_method::start[0]
|
||||||
fn main()
|
#[start]
|
||||||
{
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
// The object code of these methods is contained in the external crate, so
|
// The object code of these methods is contained in the external crate, so
|
||||||
// calling them should *not* introduce codegen items in the current crate.
|
// calling them should *not* introduce codegen items in the current crate.
|
||||||
let _: (u32, u32) = Trait::without_default_impl(0);
|
let _: (u32, u32) = Trait::without_default_impl(0);
|
||||||
|
@ -55,4 +56,6 @@ fn main()
|
||||||
let _: (char, char) = Trait::without_default_impl_generic('c');
|
let _: (char, char) = Trait::without_default_impl_generic('c');
|
||||||
//~ TRANS_ITEM fn cgu_export_trait_method::{{impl}}[0]::without_default_impl_generic[0]<bool>
|
//~ TRANS_ITEM fn cgu_export_trait_method::{{impl}}[0]::without_default_impl_generic[0]<bool>
|
||||||
let _: (char, bool) = Trait::without_default_impl_generic(false);
|
let _: (char, bool) = Trait::without_default_impl_generic(false);
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
// compile-flags:-Zinline-in-all-cgus
|
// 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]
|
//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<drop_in_place_intrinsic::StructWithDtor[0]> @@ drop_in_place_intrinsic0[Internal]
|
||||||
struct StructWithDtor(u32);
|
struct StructWithDtor(u32);
|
||||||
|
|
||||||
|
@ -20,13 +22,16 @@ impl Drop for StructWithDtor {
|
||||||
fn drop(&mut self) {}
|
fn drop(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn drop_in_place_intrinsic::main[0]
|
//~ TRANS_ITEM fn drop_in_place_intrinsic::start[0]
|
||||||
fn main() {
|
#[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]
|
//~ 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)];
|
let x = [StructWithDtor(0), StructWithDtor(1)];
|
||||||
|
|
||||||
drop_slice_in_place(&x);
|
drop_slice_in_place(&x);
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn drop_in_place_intrinsic::drop_slice_in_place[0]
|
//~ TRANS_ITEM fn drop_in_place_intrinsic::drop_slice_in_place[0]
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
fn take_fn_once<T1, T2, F: FnOnce(T1, T2)>(f: F, x: T1, y: T2) {
|
fn take_fn_once<T1, T2, F: FnOnce(T1, T2)>(f: F, x: T1, y: T2) {
|
||||||
(f)(x, y)
|
(f)(x, y)
|
||||||
|
@ -23,8 +24,9 @@ fn take_fn_pointer<T1, T2>(f: fn(T1, T2), x: T1, y: T2) {
|
||||||
(f)(x, y)
|
(f)(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn function_as_argument::main[0]
|
//~ TRANS_ITEM fn function_as_argument::start[0]
|
||||||
fn main() {
|
#[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::take_fn_once[0]<u32, &str, fn(u32, &str)>
|
||||||
//~ TRANS_ITEM fn function_as_argument::function[0]<u32, &str>
|
//~ TRANS_ITEM fn function_as_argument::function[0]<u32, &str>
|
||||||
|
@ -43,4 +45,6 @@ fn main() {
|
||||||
//~ TRANS_ITEM fn function_as_argument::take_fn_pointer[0]<f32, i64>
|
//~ TRANS_ITEM fn function_as_argument::take_fn_pointer[0]<f32, i64>
|
||||||
//~ TRANS_ITEM fn function_as_argument::function[0]<f32, i64>
|
//~ TRANS_ITEM fn function_as_argument::function[0]<f32, i64>
|
||||||
take_fn_pointer(function, 0f32, 0i64);
|
take_fn_pointer(function, 0f32, 0i64);
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// compile-flags:-Zinline-in-all-cgus
|
// compile-flags:-Zinline-in-all-cgus
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
struct StructWithDrop<T1, T2> {
|
struct StructWithDrop<T1, T2> {
|
||||||
x: T1,
|
x: T1,
|
||||||
|
@ -53,8 +54,9 @@ impl Drop for NonGenericWithDrop {
|
||||||
fn drop(&mut self) {}
|
fn drop(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn generic_drop_glue::main[0]
|
//~ TRANS_ITEM fn generic_drop_glue::start[0]
|
||||||
fn main() {
|
#[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 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>
|
//~ TRANS_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<i8, char>
|
||||||
let _ = StructWithDrop { x: 0i8, y: 'a' }.x;
|
let _ = StructWithDrop { x: 0i8, y: 'a' }.x;
|
||||||
|
@ -94,4 +96,6 @@ fn main() {
|
||||||
EnumNoDrop::A(x) => x,
|
EnumNoDrop::A(x) => x,
|
||||||
EnumNoDrop::B(x) => x as f64
|
EnumNoDrop::B(x) => x as f64
|
||||||
};
|
};
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
fn foo1<T1>(a: T1) -> (T1, u32) {
|
fn foo1<T1>(a: T1) -> (T1, u32) {
|
||||||
(a, 1)
|
(a, 1)
|
||||||
|
@ -31,8 +32,9 @@ pub fn lifetime_only<'a>(a: &'a u32) -> &'a u32 {
|
||||||
a
|
a
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn generic_functions::main[0]
|
//~ TRANS_ITEM fn generic_functions::start[0]
|
||||||
fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
//~ TRANS_ITEM fn generic_functions::foo1[0]<i32>
|
//~ TRANS_ITEM fn generic_functions::foo1[0]<i32>
|
||||||
let _ = foo1(2i32);
|
let _ = foo1(2i32);
|
||||||
//~ TRANS_ITEM fn generic_functions::foo1[0]<i64>
|
//~ TRANS_ITEM fn generic_functions::foo1[0]<i64>
|
||||||
|
@ -59,4 +61,6 @@ fn main() {
|
||||||
let _ = foo3(0i16, "a", 2usize);
|
let _ = foo3(0i16, "a", 2usize);
|
||||||
//~ TRANS_ITEM fn generic_functions::foo3[0]<char, (), ()>
|
//~ TRANS_ITEM fn generic_functions::foo3[0]<char, (), ()>
|
||||||
let _ = foo3('v', (), ());
|
let _ = foo3('v', (), ());
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
struct Struct<T> {
|
struct Struct<T> {
|
||||||
x: T,
|
x: T,
|
||||||
|
@ -50,9 +51,9 @@ impl<'a> LifeTimeOnly<'a> {
|
||||||
pub fn non_instantiated<T>(&self) {}
|
pub fn non_instantiated<T>(&self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//~ TRANS_ITEM fn generic_impl::start[0]
|
||||||
//~ TRANS_ITEM fn generic_impl::main[0]
|
#[start]
|
||||||
fn main() {
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
//~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<i32>
|
//~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<i32>
|
||||||
//~ TRANS_ITEM fn generic_impl::id[0]<i32>
|
//~ TRANS_ITEM fn generic_impl::id[0]<i32>
|
||||||
//~ TRANS_ITEM fn generic_impl::{{impl}}[0]::get[0]<i32, i16>
|
//~ TRANS_ITEM fn generic_impl::{{impl}}[0]::get[0]<i32, i16>
|
||||||
|
@ -76,4 +77,6 @@ fn main() {
|
||||||
//~ TRANS_ITEM fn generic_impl::{{impl}}[0]::new[0]<generic_impl::Struct[0]<&str>>
|
//~ 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>>
|
//~ TRANS_ITEM fn generic_impl::id[0]<generic_impl::Struct[0]<&str>>
|
||||||
let _ = (Struct::new(Struct::new("str")).f)(Struct::new("str"));
|
let _ = (Struct::new(Struct::new("str")).f)(Struct::new("str"));
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
trait SomeTrait {
|
trait SomeTrait {
|
||||||
fn foo(&self);
|
fn foo(&self);
|
||||||
|
@ -28,7 +29,10 @@ pub fn generic_function<T>(x: T) -> (T, i32) {
|
||||||
(x, 0)
|
(x, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn impl_in_non_instantiated_generic::main[0]
|
//~ TRANS_ITEM fn impl_in_non_instantiated_generic::start[0]
|
||||||
fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
0i64.foo();
|
0i64.foo();
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// compile-flags:-Zinline-in-all-cgus
|
// compile-flags:-Zinline-in-all-cgus
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
trait Trait {
|
trait Trait {
|
||||||
fn foo(&self) -> u32;
|
fn foo(&self) -> u32;
|
||||||
|
@ -28,8 +29,9 @@ impl<T> Trait for Struct<T> {
|
||||||
fn bar(&self) {}
|
fn bar(&self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn instantiation_through_vtable::main[0]
|
//~ TRANS_ITEM fn instantiation_through_vtable::start[0]
|
||||||
fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
let s1 = Struct { _a: 0u32 };
|
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]
|
//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<instantiation_through_vtable::Struct[0]<u32>> @@ instantiation_through_vtable0[Internal]
|
||||||
|
@ -42,4 +44,6 @@ fn main() {
|
||||||
//~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0]<u64>
|
//~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0]<u64>
|
||||||
//~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0]<u64>
|
//~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0]<u64>
|
||||||
let _ = &s1 as &Trait;
|
let _ = &s1 as &Trait;
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
fn generic_fn<T>(a: T) -> (T, i32) {
|
fn generic_fn<T>(a: T) -> (T, i32) {
|
||||||
//~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]::nested_fn[0]
|
//~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]::nested_fn[0]
|
||||||
|
@ -31,12 +32,15 @@ fn generic_fn<T>(a: T) -> (T, i32) {
|
||||||
return (a, x + nested_fn(0));
|
return (a, x + nested_fn(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn items_within_generic_items::main[0]
|
//~ TRANS_ITEM fn items_within_generic_items::start[0]
|
||||||
fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
//~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<i64>
|
//~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<i64>
|
||||||
let _ = generic_fn(0i64);
|
let _ = generic_fn(0i64);
|
||||||
//~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<u16>
|
//~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<u16>
|
||||||
let _ = generic_fn(0u16);
|
let _ = generic_fn(0u16);
|
||||||
//~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<i8>
|
//~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<i8>
|
||||||
let _ = generic_fn(0i8);
|
let _ = generic_fn(0i8);
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
//~ TRANS_ITEM fn non_generic_closures::temporary[0]
|
//~ TRANS_ITEM fn non_generic_closures::temporary[0]
|
||||||
fn temporary() {
|
fn temporary() {
|
||||||
|
@ -52,12 +53,15 @@ fn assigned_to_variable_executed_directly() {
|
||||||
f(4);
|
f(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn non_generic_closures::main[0]
|
//~ TRANS_ITEM fn non_generic_closures::start[0]
|
||||||
fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
temporary();
|
temporary();
|
||||||
assigned_to_variable_but_not_executed();
|
assigned_to_variable_but_not_executed();
|
||||||
assigned_to_variable_executed_directly();
|
assigned_to_variable_executed_directly();
|
||||||
assigned_to_variable_executed_indirectly();
|
assigned_to_variable_executed_indirectly();
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn non_generic_closures::run_closure[0]
|
//~ TRANS_ITEM fn non_generic_closures::run_closure[0]
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// compile-flags:-Zinline-in-all-cgus
|
// compile-flags:-Zinline-in-all-cgus
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![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]
|
//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<non_generic_drop_glue::StructWithDrop[0]> @@ non_generic_drop_glue0[Internal]
|
||||||
struct StructWithDrop {
|
struct StructWithDrop {
|
||||||
|
@ -42,8 +43,9 @@ enum EnumNoDrop {
|
||||||
A(i32)
|
A(i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn non_generic_drop_glue::main[0]
|
//~ TRANS_ITEM fn non_generic_drop_glue::start[0]
|
||||||
fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
let _ = StructWithDrop { x: 0 }.x;
|
let _ = StructWithDrop { x: 0 }.x;
|
||||||
let _ = StructNoDrop { x: 0 }.x;
|
let _ = StructNoDrop { x: 0 }.x;
|
||||||
let _ = match EnumWithDrop::A(0) {
|
let _ = match EnumWithDrop::A(0) {
|
||||||
|
@ -52,4 +54,6 @@ fn main() {
|
||||||
let _ = match EnumNoDrop::A(0) {
|
let _ = match EnumNoDrop::A(0) {
|
||||||
EnumNoDrop::A(x) => x
|
EnumNoDrop::A(x) => x
|
||||||
};
|
};
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
//~ TRANS_ITEM fn non_generic_functions::foo[0]
|
//~ TRANS_ITEM fn non_generic_functions::foo[0]
|
||||||
fn foo() {
|
fn foo() {
|
||||||
|
@ -69,11 +70,14 @@ impl Struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn non_generic_functions::main[0]
|
//~ TRANS_ITEM fn non_generic_functions::start[0]
|
||||||
fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
foo();
|
foo();
|
||||||
bar();
|
bar();
|
||||||
Struct::foo();
|
Struct::foo();
|
||||||
let x = Struct { _x: 0 };
|
let x = Struct { _x: 0 };
|
||||||
x.bar();
|
x.bar();
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
pub static FN : fn() = foo::<i32>;
|
pub static FN : fn() = foo::<i32>;
|
||||||
|
|
||||||
|
@ -17,6 +20,9 @@ pub fn foo<T>() { }
|
||||||
//~ TRANS_ITEM fn static_init::foo[0]<i32>
|
//~ TRANS_ITEM fn static_init::foo[0]<i32>
|
||||||
//~ TRANS_ITEM static static_init::FN[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]
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
static STATIC1: i64 = {
|
static STATIC1: i64 = {
|
||||||
const STATIC1_CONST1: i64 = 2;
|
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();
|
foo();
|
||||||
let _ = STATIC1;
|
let _ = STATIC1;
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM static statics_and_consts::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[0]
|
||||||
//~ TRANS_ITEM static statics_and_consts::foo[0]::STATIC2[1]
|
//~ TRANS_ITEM static statics_and_consts::foo[0]::STATIC2[1]
|
||||||
//~ TRANS_ITEM static statics_and_consts::foo[0]::STATIC2[2]
|
//~ TRANS_ITEM static statics_and_consts::foo[0]::STATIC2[2]
|
||||||
|
|
||||||
//~ TRANS_ITEM fn statics_and_consts::main[0]
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
pub trait SomeTrait {
|
pub trait SomeTrait {
|
||||||
fn foo(&self);
|
fn foo(&self);
|
||||||
|
@ -55,8 +56,9 @@ impl<T> SomeGenericTrait<T> for f32 {
|
||||||
fn bar<T2>(&self, _: T, _: T2) {}
|
fn bar<T2>(&self, _: T, _: T2) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn trait_implementations::main[0]
|
//~ TRANS_ITEM fn trait_implementations::start[0]
|
||||||
fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
//~ TRANS_ITEM fn trait_implementations::{{impl}}[1]::bar[0]<char>
|
//~ TRANS_ITEM fn trait_implementations::{{impl}}[1]::bar[0]<char>
|
||||||
0i32.bar('x');
|
0i32.bar('x');
|
||||||
|
|
||||||
|
@ -77,4 +79,6 @@ fn main() {
|
||||||
|
|
||||||
//~ TRANS_ITEM fn trait_implementations::{{impl}}[3]::bar[0]<&str, &str>
|
//~ TRANS_ITEM fn trait_implementations::{{impl}}[3]::bar[0]<&str, &str>
|
||||||
0f32.bar("&str", "&str");
|
0f32.bar("&str", "&str");
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
trait Trait : Sized {
|
trait Trait : Sized {
|
||||||
fn foo(self) -> Self { self }
|
fn foo(self) -> Self { self }
|
||||||
|
@ -36,8 +37,9 @@ fn take_foo_mut<T, F: FnMut(T) -> T>(mut f: F, arg: T) -> T {
|
||||||
(f)(arg)
|
(f)(arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn trait_method_as_argument::main[0]
|
//~ TRANS_ITEM fn trait_method_as_argument::start[0]
|
||||||
fn main() {
|
#[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::take_foo_once[0]<u32, fn(u32) -> u32>
|
||||||
//~ TRANS_ITEM fn trait_method_as_argument::{{impl}}[0]::foo[0]
|
//~ 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)>
|
//~ TRANS_ITEM fn core::ops[0]::function[0]::FnOnce[0]::call_once[0]<fn(u32) -> u32, (u32)>
|
||||||
|
@ -63,4 +65,6 @@ fn main() {
|
||||||
//~ TRANS_ITEM fn trait_method_as_argument::take_foo_mut[0]<char, fn(char) -> char>
|
//~ 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)>
|
//~ TRANS_ITEM fn core::ops[0]::function[0]::FnMut[0]::call_mut[0]<fn(u32) -> u32, (u32)>
|
||||||
take_foo_mut(Trait::foo, 'c');
|
take_foo_mut(Trait::foo, 'c');
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// compile-flags:-Zprint-trans-items=eager
|
// compile-flags:-Zprint-trans-items=eager
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
trait SomeTrait {
|
trait SomeTrait {
|
||||||
fn foo(&self) { }
|
fn foo(&self) { }
|
||||||
|
@ -46,8 +47,9 @@ impl<T1> SomeGenericTrait<T1> for u32 {
|
||||||
// since nothing is monomorphic here, nothing should be generated unless used somewhere.
|
// since nothing is monomorphic here, nothing should be generated unless used somewhere.
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn trait_method_default_impl::main[0]
|
//~ TRANS_ITEM fn trait_method_default_impl::start[0]
|
||||||
fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
//~ TRANS_ITEM fn trait_method_default_impl::SomeTrait[0]::bar[0]<i8, char>
|
//~ TRANS_ITEM fn trait_method_default_impl::SomeTrait[0]::bar[0]<i8, char>
|
||||||
let _ = 1i8.bar('c');
|
let _ = 1i8.bar('c');
|
||||||
|
|
||||||
|
@ -65,4 +67,6 @@ fn main() {
|
||||||
|
|
||||||
//~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<u32, i16, ()>
|
//~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<u32, i16, ()>
|
||||||
0u32.bar(0i16, ());
|
0u32.bar(0i16, ());
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// compile-flags:-Zinline-in-all-cgus
|
// compile-flags:-Zinline-in-all-cgus
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Root[0]> @@ transitive_drop_glue0[Internal]
|
//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Root[0]> @@ transitive_drop_glue0[Internal]
|
||||||
struct Root(Intermediate);
|
struct Root(Intermediate);
|
||||||
|
@ -34,9 +35,9 @@ impl<T> Drop for LeafGen<T> {
|
||||||
fn drop(&mut self) {}
|
fn drop(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn transitive_drop_glue::main[0]
|
//~ TRANS_ITEM fn transitive_drop_glue::start[0]
|
||||||
fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
let _ = Root(Intermediate(Leaf));
|
let _ = Root(Intermediate(Leaf));
|
||||||
|
|
||||||
//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::RootGen[0]<u32>> @@ transitive_drop_glue0[Internal]
|
//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::RootGen[0]<u32>> @@ transitive_drop_glue0[Internal]
|
||||||
|
@ -50,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 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>
|
//~ TRANS_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0]<i16>
|
||||||
let _ = RootGen(IntermediateGen(LeafGen(0i16)));
|
let _ = RootGen(IntermediateGen(LeafGen(0i16)));
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// compile-flags:-Zinline-in-all-cgus
|
// compile-flags:-Zinline-in-all-cgus
|
||||||
|
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<tuple_drop_glue::Dropped[0]> @@ tuple_drop_glue0[Internal]
|
//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<tuple_drop_glue::Dropped[0]> @@ tuple_drop_glue0[Internal]
|
||||||
struct Dropped;
|
struct Dropped;
|
||||||
|
@ -22,12 +23,15 @@ impl Drop for Dropped {
|
||||||
fn drop(&mut self) {}
|
fn drop(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn tuple_drop_glue::main[0]
|
//~ TRANS_ITEM fn tuple_drop_glue::start[0]
|
||||||
fn main() {
|
#[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]
|
//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue0[Internal]
|
||||||
let x = (0u32, Dropped);
|
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]<(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]
|
//~ 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));
|
let x = (0i16, (Dropped, true));
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
#![feature(coerce_unsized)]
|
#![feature(coerce_unsized)]
|
||||||
#![feature(unsize)]
|
#![feature(unsize)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
use std::marker::Unsize;
|
use std::marker::Unsize;
|
||||||
use std::ops::CoerceUnsized;
|
use std::ops::CoerceUnsized;
|
||||||
|
@ -53,9 +54,9 @@ struct Wrapper<T: ?Sized>(*const T);
|
||||||
|
|
||||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn unsizing::main[0]
|
//~ TRANS_ITEM fn unsizing::start[0]
|
||||||
fn main()
|
#[start]
|
||||||
{
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
// simple case
|
// simple case
|
||||||
let bool_sized = &true;
|
let bool_sized = &true;
|
||||||
//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<bool> @@ unsizing0[Internal]
|
//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<bool> @@ unsizing0[Internal]
|
||||||
|
@ -83,4 +84,6 @@ fn main()
|
||||||
//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ unsizing0[Internal]
|
//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ unsizing0[Internal]
|
||||||
//~ TRANS_ITEM fn unsizing::{{impl}}[3]::foo[0]
|
//~ TRANS_ITEM fn unsizing::{{impl}}[3]::foo[0]
|
||||||
let _wrapper_sized = wrapper_sized as Wrapper<Trait>;
|
let _wrapper_sized = wrapper_sized as Wrapper<Trait>;
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
// compile-flags:-Zprint-trans-items=lazy -Zincremental=tmp/partitioning-tests/methods-are-with-self-type
|
// compile-flags:-Zprint-trans-items=lazy -Zincremental=tmp/partitioning-tests/methods-are-with-self-type
|
||||||
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
struct SomeType;
|
struct SomeType;
|
||||||
|
|
||||||
|
@ -63,9 +64,9 @@ mod type2 {
|
||||||
pub struct Struct;
|
pub struct Struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn methods_are_with_self_type::main[0]
|
//~ TRANS_ITEM fn methods_are_with_self_type::start[0]
|
||||||
fn main()
|
#[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]
|
//~ 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();
|
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]
|
//~ 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();
|
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]
|
//~ 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();
|
type2::Struct.default();
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM drop-glue i8
|
//~ TRANS_ITEM drop-glue i8
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
// This test case makes sure, that references made through constants are
|
// This test case makes sure, that references made through constants are
|
||||||
// recorded properly in the InliningMap.
|
// recorded properly in the InliningMap.
|
||||||
|
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
mod mod1 {
|
mod mod1 {
|
||||||
pub trait Trait1 {
|
pub trait Trait1 {
|
||||||
fn do_something(&self) {}
|
fn do_something(&self) {}
|
||||||
|
@ -38,7 +40,7 @@ mod mod1 {
|
||||||
|
|
||||||
fn id<T>(x: T) -> T { x }
|
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_REF: &'static Trait1 = &0u32 as &Trait1;
|
||||||
pub const TRAIT1_GEN_REF: &'static Trait1Gen<u8> = &0u32 as &Trait1Gen<u8>;
|
pub const TRAIT1_GEN_REF: &'static Trait1Gen<u8> = &0u32 as &Trait1Gen<u8>;
|
||||||
pub const ID_CHAR: fn(char) -> char = id::<char>;
|
pub const ID_CHAR: fn(char) -> char = id::<char>;
|
||||||
|
@ -68,8 +70,9 @@ mod mod1 {
|
||||||
pub const ID_I64: fn(i64) -> i64 = id::<i64>;
|
pub const ID_I64: fn(i64) -> i64 = id::<i64>;
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn vtable_through_const::main[0] @@ vtable_through_const[Internal]
|
//~ TRANS_ITEM fn vtable_through_const::start[0]
|
||||||
fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ vtable_through_const[Internal]
|
//~ 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,
|
// 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]<char> @@ vtable_through_const-mod1.volatile[External]
|
//~ TRANS_ITEM fn vtable_through_const::mod1[0]::id[0]<char> @@ vtable_through_const-mod1.volatile[External]
|
||||||
mod1::ID_CHAR('x');
|
mod1::ID_CHAR('x');
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -7,8 +7,9 @@
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
#![feature(termination_trait)]
|
||||||
|
|
||||||
fn main() -> char {
|
fn main() -> char {
|
||||||
//~^ ERROR: main function has wrong type [E0580]
|
//~^ ERROR: the trait bound `char: std::Termination` is not satisfied
|
||||||
' '
|
' '
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
||||||
|
struct ReturnType {}
|
||||||
|
|
||||||
|
fn main() -> ReturnType { //~ ERROR `ReturnType: std::Termination` is not satisfied
|
||||||
|
ReturnType {}
|
||||||
|
}
|
|
@ -8,6 +8,8 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn inlined() -> u32 {
|
fn inlined() -> u32 {
|
||||||
1234
|
1234
|
||||||
|
@ -29,7 +31,10 @@ mod b {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
a::f();
|
a::f();
|
||||||
b::f();
|
b::f();
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
@ -8,4 +8,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
fn main() -> i32 { 0 } //~ ERROR E0580
|
#![feature(termination_trait)]
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -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
|
||||||
|
}
|
|
@ -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(())
|
||||||
|
}
|
|
@ -15,7 +15,10 @@
|
||||||
// that one cannot control the sizes of these types with the same sort
|
// that one cannot control the sizes of these types with the same sort
|
||||||
// of enum-variant manipulation tricks.
|
// of enum-variant manipulation tricks.
|
||||||
|
|
||||||
pub fn main() {
|
#![feature(start)]
|
||||||
|
|
||||||
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
let _byte: u8 = 0;
|
let _byte: u8 = 0;
|
||||||
let _word: usize = 0;
|
let _word: usize = 0;
|
||||||
let _tuple: (u8, usize)= (0, 0);
|
let _tuple: (u8, usize)= (0, 0);
|
||||||
|
@ -25,4 +28,6 @@ pub fn main() {
|
||||||
|
|
||||||
fn id(x: u8) -> u8 { x };
|
fn id(x: u8) -> u8 { x };
|
||||||
fn bye(_: u8) -> ! { loop { } }
|
fn bye(_: u8) -> ! { loop { } }
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
// monomorphized, in the MIR of the original function in which they
|
// monomorphized, in the MIR of the original function in which they
|
||||||
// occur, to have their size reported.
|
// occur, to have their size reported.
|
||||||
|
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
// In an ad-hoc attempt to avoid the injection of unwinding code
|
// In an ad-hoc attempt to avoid the injection of unwinding code
|
||||||
// (which clutters the output of `-Z print-type-sizes` with types from
|
// (which clutters the output of `-Z print-type-sizes` with types from
|
||||||
// `unwind::libunwind`):
|
// `unwind::libunwind`):
|
||||||
|
@ -66,9 +68,11 @@ pub fn f1<T:Copy>(x: T) {
|
||||||
Pair::new(FiftyBytes::new(), FiftyBytes::new());
|
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 _b: Pair<u8> = Pair::new(0, 0);
|
||||||
let _s: Pair<SevenBytes> = Pair::new(SevenBytes::new(), SevenBytes::new());
|
let _s: Pair<SevenBytes> = Pair::new(SevenBytes::new(), SevenBytes::new());
|
||||||
let _z: ZeroSized = ZeroSized;
|
let _z: ZeroSized = ZeroSized;
|
||||||
f1::<SevenBytes>(SevenBytes::new());
|
f1::<SevenBytes>(SevenBytes::new());
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
// This file illustrates that when multiple structural types occur in
|
// This file illustrates that when multiple structural types occur in
|
||||||
// a function, every one of them is included in the output.
|
// a function, every one of them is included in the output.
|
||||||
|
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
pub struct SevenBytes([u8; 7]);
|
pub struct SevenBytes([u8; 7]);
|
||||||
pub struct FiftyBytes([u8; 50]);
|
pub struct FiftyBytes([u8; 50]);
|
||||||
|
|
||||||
|
@ -22,8 +24,10 @@ pub enum Enum {
|
||||||
Large(FiftyBytes),
|
Large(FiftyBytes),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
let _e: Enum;
|
let _e: Enum;
|
||||||
let _f: FiftyBytes;
|
let _f: FiftyBytes;
|
||||||
let _s: SevenBytes;
|
let _s: SevenBytes;
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
// aligned (while on most it is 8-byte aligned) and so the resulting
|
// aligned (while on most it is 8-byte aligned) and so the resulting
|
||||||
// padding and overall computed sizes can be quite different.
|
// padding and overall computed sizes can be quite different.
|
||||||
|
|
||||||
|
#![feature(start)]
|
||||||
#![feature(nonzero)]
|
#![feature(nonzero)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
@ -76,7 +77,8 @@ pub enum Enum4<A, B, C, D> {
|
||||||
Four(D)
|
Four(D)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
let _x: MyOption<NonZero<u32>> = Default::default();
|
let _x: MyOption<NonZero<u32>> = Default::default();
|
||||||
let _y: EmbeddedDiscr = Default::default();
|
let _y: EmbeddedDiscr = Default::default();
|
||||||
let _z: MyOption<IndirectNonZero<u32>> = Default::default();
|
let _z: MyOption<IndirectNonZero<u32>> = Default::default();
|
||||||
|
@ -87,4 +89,5 @@ pub fn main() {
|
||||||
let _e: Enum4<(), char, (), ()> = Enum4::One(());
|
let _e: Enum4<(), char, (), ()> = Enum4::One(());
|
||||||
let _f: Enum4<(), (), bool, ()> = Enum4::One(());
|
let _f: Enum4<(), (), bool, ()> = Enum4::One(());
|
||||||
let _g: Enum4<(), (), (), MyOption<u8>> = Enum4::One(());
|
let _g: Enum4<(), (), (), MyOption<u8>> = Enum4::One(());
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,16 @@
|
||||||
// (even if multiple functions), it is only printed once in the
|
// (even if multiple functions), it is only printed once in the
|
||||||
// print-type-sizes output.
|
// print-type-sizes output.
|
||||||
|
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
pub struct SevenBytes([u8; 7]);
|
pub struct SevenBytes([u8; 7]);
|
||||||
|
|
||||||
pub fn f1() {
|
pub fn f1() {
|
||||||
let _s: SevenBytes = SevenBytes([0; 7]);
|
let _s: SevenBytes = SevenBytes([0; 7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
let _s: SevenBytes = SevenBytes([0; 7]);
|
let _s: SevenBytes = SevenBytes([0; 7]);
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
// padding and overall computed sizes can be quite different.
|
// padding and overall computed sizes can be quite different.
|
||||||
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
#[repr(packed)]
|
#[repr(packed)]
|
||||||
|
@ -42,7 +43,9 @@ struct Padded {
|
||||||
d: u8,
|
d: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
let _c: Packed = Default::default();
|
let _c: Packed = Default::default();
|
||||||
let _d: Padded = Default::default();
|
let _d: Padded = Default::default();
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
// aligned (while on most it is 8-byte aligned) and so the resulting
|
// aligned (while on most it is 8-byte aligned) and so the resulting
|
||||||
// padding and overall computed sizes can be quite different.
|
// padding and overall computed sizes can be quite different.
|
||||||
|
|
||||||
|
#![feature(start)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
struct S {
|
struct S {
|
||||||
|
@ -37,4 +38,7 @@ enum E2 {
|
||||||
B(S),
|
B(S),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() { }
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
// padding and overall computed sizes can be quite different.
|
// padding and overall computed sizes can be quite different.
|
||||||
#![feature(attr_literals)]
|
#![feature(attr_literals)]
|
||||||
#![feature(repr_align)]
|
#![feature(repr_align)]
|
||||||
|
#![feature(start)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
#[repr(align(16))]
|
#[repr(align(16))]
|
||||||
|
@ -39,6 +40,8 @@ struct S {
|
||||||
d: i8,
|
d: i8,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
let _s: S = Default::default();
|
let _s: S = Default::default();
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,11 @@
|
||||||
// must-compile-successfully
|
// must-compile-successfully
|
||||||
|
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
pub fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
let _x: Option<!> = None;
|
let _x: Option<!> = None;
|
||||||
let _y: Result<u32, !> = Ok(42);
|
let _y: Result<u32, !> = Ok(42);
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
// 2. For an enum, the print-type-sizes output will also include the
|
// 2. For an enum, the print-type-sizes output will also include the
|
||||||
// size of each variant.
|
// size of each variant.
|
||||||
|
|
||||||
|
#![feature(start)]
|
||||||
|
|
||||||
pub struct SevenBytes([u8; 7]);
|
pub struct SevenBytes([u8; 7]);
|
||||||
pub struct FiftyBytes([u8; 50]);
|
pub struct FiftyBytes([u8; 50]);
|
||||||
|
|
||||||
|
@ -27,6 +29,8 @@ pub enum Enum {
|
||||||
Large(FiftyBytes),
|
Large(FiftyBytes),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
#[start]
|
||||||
|
fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
let _e: Enum;
|
let _e: Enum;
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue