Implement the translation item collector.

The purpose of the translation item collector is to find all monomorphic instances of functions, methods and statics that need to be translated into LLVM IR in order to compile the current crate.
So far these instances have been discovered lazily during the trans path. For incremental compilation we want to know the set of these instances in advance, and that is what the trans::collect module provides.
In the future, incremental and regular translation will be driven by the collector implemented here.
This commit is contained in:
Michael Woerister 2015-11-02 14:46:39 +01:00
parent b279c5b068
commit 862911df9a
46 changed files with 3296 additions and 61 deletions

1
configure vendored
View File

@ -1409,6 +1409,7 @@ do
make_dir $h/test/debuginfo-gdb
make_dir $h/test/debuginfo-lldb
make_dir $h/test/codegen
make_dir $h/test/codegen-units
make_dir $h/test/rustdoc
done

View File

@ -310,6 +310,7 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
check-stage$(1)-T-$(2)-H-$(3)-debuginfo-gdb-exec \
check-stage$(1)-T-$(2)-H-$(3)-debuginfo-lldb-exec \
check-stage$(1)-T-$(2)-H-$(3)-codegen-exec \
check-stage$(1)-T-$(2)-H-$(3)-codegen-units-exec \
check-stage$(1)-T-$(2)-H-$(3)-doc-exec \
check-stage$(1)-T-$(2)-H-$(3)-pretty-exec
@ -473,6 +474,7 @@ DEBUGINFO_GDB_RS := $(wildcard $(S)src/test/debuginfo/*.rs)
DEBUGINFO_LLDB_RS := $(wildcard $(S)src/test/debuginfo/*.rs)
CODEGEN_RS := $(wildcard $(S)src/test/codegen/*.rs)
CODEGEN_CC := $(wildcard $(S)src/test/codegen/*.cc)
CODEGEN_UNITS_RS := $(wildcard $(S)src/test/codegen-units/*.rs)
RUSTDOCCK_RS := $(wildcard $(S)src/test/rustdoc/*.rs)
RPASS_TESTS := $(RPASS_RS)
@ -488,6 +490,7 @@ PRETTY_TESTS := $(PRETTY_RS)
DEBUGINFO_GDB_TESTS := $(DEBUGINFO_GDB_RS)
DEBUGINFO_LLDB_TESTS := $(DEBUGINFO_LLDB_RS)
CODEGEN_TESTS := $(CODEGEN_RS) $(CODEGEN_CC)
CODEGEN_UNITS_TESTS := $(CODEGEN_UNITS_RS)
RUSTDOCCK_TESTS := $(RUSTDOCCK_RS)
CTEST_SRC_BASE_rpass = run-pass
@ -550,6 +553,11 @@ CTEST_BUILD_BASE_codegen = codegen
CTEST_MODE_codegen = codegen
CTEST_RUNTOOL_codegen = $(CTEST_RUNTOOL)
CTEST_SRC_BASE_codegen-units = codegen-units
CTEST_BUILD_BASE_codegen-units = codegen-units
CTEST_MODE_codegen-units = codegen-units
CTEST_RUNTOOL_codegen-units = $(CTEST_RUNTOOL)
CTEST_SRC_BASE_rustdocck = rustdoc
CTEST_BUILD_BASE_rustdocck = rustdoc
CTEST_MODE_rustdocck = rustdoc
@ -673,6 +681,7 @@ CTEST_DEPS_debuginfo-lldb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_LLDB_TESTS) \
$(S)src/etc/lldb_batchmode.py \
$(S)src/etc/lldb_rust_formatters.py
CTEST_DEPS_codegen_$(1)-T-$(2)-H-$(3) = $$(CODEGEN_TESTS)
CTEST_DEPS_codegen-units_$(1)-T-$(2)-H-$(3) = $$(CODEGEN_UNITS_TESTS)
CTEST_DEPS_rustdocck_$(1)-T-$(2)-H-$(3) = $$(RUSTDOCCK_TESTS) \
$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
$(S)src/etc/htmldocck.py
@ -739,7 +748,7 @@ endif
endef
CTEST_NAMES = rpass rpass-valgrind rpass-full rfail-full cfail-full rfail cfail pfail \
bench debuginfo-gdb debuginfo-lldb codegen rustdocck
bench debuginfo-gdb debuginfo-lldb codegen codegen-units rustdocck
$(foreach host,$(CFG_HOST), \
$(eval $(foreach target,$(CFG_TARGET), \
@ -917,6 +926,7 @@ TEST_GROUPS = \
debuginfo-gdb \
debuginfo-lldb \
codegen \
codegen-units \
doc \
$(foreach docname,$(DOC_NAMES),doc-$(docname)) \
pretty \

View File

@ -25,6 +25,7 @@ pub enum Mode {
DebugInfoLldb,
Codegen,
Rustdoc,
CodegenUnits
}
impl FromStr for Mode {
@ -41,6 +42,7 @@ impl FromStr for Mode {
"debuginfo-gdb" => Ok(DebugInfoGdb),
"codegen" => Ok(Codegen),
"rustdoc" => Ok(Rustdoc),
"codegen-units" => Ok(CodegenUnits),
_ => Err(()),
}
}
@ -59,6 +61,7 @@ impl fmt::Display for Mode {
DebugInfoLldb => "debuginfo-lldb",
Codegen => "codegen",
Rustdoc => "rustdoc",
CodegenUnits => "codegen-units",
}, f)
}
}

View File

@ -10,7 +10,7 @@
use common::Config;
use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind};
use common::{Codegen, DebugInfoLldb, DebugInfoGdb, Rustdoc};
use common::{Codegen, DebugInfoLldb, DebugInfoGdb, Rustdoc, CodegenUnits};
use errors;
use header::TestProps;
use header;
@ -18,6 +18,7 @@ use procsrv;
use util::logv;
use std::env;
use std::collections::HashSet;
use std::fmt;
use std::fs::{self, File};
use std::io::BufReader;
@ -56,6 +57,7 @@ pub fn run(config: Config, testfile: &Path) {
DebugInfoLldb => run_debuginfo_lldb_test(&config, &props, &testfile),
Codegen => run_codegen_test(&config, &props, &testfile),
Rustdoc => run_rustdoc_test(&config, &props, &testfile),
CodegenUnits => run_codegen_units_test(&config, &props, &testfile),
}
}
@ -1747,3 +1749,44 @@ fn run_rustdoc_test(config: &Config, props: &TestProps, testfile: &Path) {
fatal_proc_rec("htmldocck failed!", &res);
}
}
fn run_codegen_units_test(config: &Config, props: &TestProps, testfile: &Path) {
let proc_res = compile_test(config, props, testfile);
if !proc_res.status.success() {
fatal_proc_rec("compilation failed!", &proc_res);
}
check_no_compiler_crash(&proc_res);
let prefix = "TRANS_ITEM ";
let actual: HashSet<String> = proc_res
.stdout
.lines()
.filter(|line| line.starts_with(prefix))
.map(|s| (&s[prefix.len()..]).to_string())
.collect();
let expected: HashSet<String> = errors::load_errors(testfile)
.iter()
.map(|e| e.msg.trim().to_string())
.collect();
if actual != expected {
let mut missing: Vec<_> = expected.difference(&actual).collect();
missing.sort();
let mut too_much: Vec<_> = actual.difference(&expected).collect();
too_much.sort();
println!("Expected and actual sets of codegen-items differ.\n\
These items should have been contained but were not:\n\n\
{}\n\n\
These items were contained but should not have been:\n\n\
{}\n\n",
missing.iter().fold("".to_string(), |s1, s2| s1 + "\n" + s2),
too_much.iter().fold("".to_string(), |s1, s2| s1 + "\n" + s2));
panic!();
}
}

View File

@ -196,33 +196,33 @@ impl DefPathData {
PositionalField |
Field(hir::StructFieldKind::UnnamedField(_)) => {
InternedString::new("<field>")
InternedString::new("{{field}}")
}
// note that this does not show up in user printouts
CrateRoot => {
InternedString::new("<root>")
InternedString::new("{{root}}")
}
// note that this does not show up in user printouts
InlinedRoot(_) => {
InternedString::new("<inlined-root>")
InternedString::new("{{inlined-root}}")
}
Misc => {
InternedString::new("?")
InternedString::new("{{?}}")
}
ClosureExpr => {
InternedString::new("<closure>")
InternedString::new("{{closure}}")
}
StructCtor => {
InternedString::new("<constructor>")
InternedString::new("{{constructor}}")
}
Initializer => {
InternedString::new("<initializer>")
InternedString::new("{{initializer}}")
}
}
}

View File

@ -223,6 +223,8 @@ pub trait CrateStore<'tcx> : Any {
-> FoundAst<'tcx>;
fn maybe_get_item_mir(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
-> Option<Mir<'tcx>>;
fn is_item_mir_available(&self, def: DefId) -> bool;
// This is basically a 1-based range of ints, which is a little
// silly - I may fix that.
fn crates(&self) -> Vec<ast::CrateNum>;
@ -397,6 +399,9 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
-> FoundAst<'tcx> { unimplemented!() }
fn maybe_get_item_mir(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
-> Option<Mir<'tcx>> { unimplemented!() }
fn is_item_mir_available(&self, def: DefId) -> bool {
unimplemented!()
}
// This is basically a 1-based range of ints, which is a little
// silly - I may fix that.

View File

@ -563,7 +563,7 @@ impl<'tcx> ctxt<'tcx> {
const_qualif_map: RefCell::new(NodeMap()),
custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
cast_kinds: RefCell::new(NodeMap()),
fragment_infos: RefCell::new(DefIdMap()),
fragment_infos: RefCell::new(DefIdMap())
}, f)
}
}

View File

@ -13,7 +13,7 @@ use middle::def_id::DefId;
use middle::ty;
use std::marker::PhantomData;
use std::rc::Rc;
use syntax::attr;
use syntax::{attr, ast};
macro_rules! dep_map_ty {
($ty_name:ident : $node_name:ident ($key:ty) -> $value:ty) => {
@ -42,3 +42,4 @@ dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Rc<Vec<DefId>> }
dep_map_ty! { ImplItems: ImplItems(DefId) -> Vec<ty::ImplOrTraitItemId> }
dep_map_ty! { TraitItems: TraitItems(DefId) -> Rc<Vec<ty::ImplOrTraitItem<'tcx>>> }
dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc<Vec<attr::ReprAttr>> }
dep_map_ty! { InlinedClosures: Hir(DefId) -> ast::NodeId }

View File

@ -721,7 +721,7 @@ pub enum Rvalue<'tcx> {
InlineAsm(InlineAsm),
}
#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum CastKind {
Misc,

View File

@ -643,6 +643,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"keep the AST after lowering it to HIR"),
show_span: Option<String> = (None, parse_opt_string,
"show spans for compiler debugging (expr|pat|ty)"),
print_trans_items: Option<String> = (None, parse_opt_string,
"print the result of the translation item collection pass"),
}
pub fn default_lib_output() -> CrateType {

View File

@ -177,6 +177,7 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
}
_ => { }
}
Ok(ii)
}
}

View File

@ -445,6 +445,11 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
decoder::maybe_get_item_mir(&*cdata, tcx, def.index)
}
fn is_item_mir_available(&self, def: DefId) -> bool {
let cdata = self.get_crate_data(def.krate);
decoder::is_item_mir_available(&*cdata, def.index)
}
fn crates(&self) -> Vec<ast::CrateNum>
{
let mut result = vec![];

View File

@ -830,6 +830,14 @@ pub fn maybe_get_item_ast<'tcx>(cdata: Cmd,
}
}
pub fn is_item_mir_available<'tcx>(cdata: Cmd, id: DefIndex) -> bool {
if let Some(item_doc) = cdata.get_item(id) {
return reader::maybe_get_doc(item_doc, tag_mir as usize).is_some();
}
false
}
pub fn maybe_get_item_mir<'tcx>(cdata: Cmd,
tcx: &ty::ctxt<'tcx>,
id: DefIndex)
@ -849,6 +857,8 @@ pub fn maybe_get_item_mir<'tcx>(cdata: Cmd,
})
}).unwrap();
assert!(decoder.position() == mir_doc.end);
let mut def_id_and_span_translator = MirDefIdAndSpanTranslator {
crate_metadata: cdata,
codemap: tcx.sess.codemap(),

View File

@ -41,8 +41,10 @@ use middle::infer;
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
use middle::weak_lang_items;
use middle::pat_util::simple_name;
use middle::subst::Substs;
use middle::subst::{self, Substs};
use middle::traits;
use middle::ty::{self, Ty, TypeFoldable};
use middle::ty::adjustment::CustomCoerceUnsized;
use rustc::dep_graph::DepNode;
use rustc::front::map as hir_map;
use rustc::util::common::time;
@ -59,10 +61,11 @@ use trans::callee;
use trans::cleanup::{self, CleanupMethods, DropHint};
use trans::closure;
use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_int, C_uint, C_integral};
use trans::collector::{self, TransItem, TransItemState, TransItemCollectionMode};
use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef};
use trans::common::{CrateContext, DropFlagHintsMap, Field, FunctionContext};
use trans::common::{Result, NodeIdAndSpan, VariantInfo};
use trans::common::{node_id_type, return_type_is_void};
use trans::common::{node_id_type, return_type_is_void, fulfill_obligation};
use trans::common::{type_is_immediate, type_is_zero_size, val_ty};
use trans::common;
use trans::consts;
@ -98,7 +101,7 @@ use std::collections::{HashMap, HashSet};
use std::str;
use std::{i8, i16, i32, i64};
use syntax::abi::{Rust, RustCall, RustIntrinsic, PlatformIntrinsic, Abi};
use syntax::codemap::Span;
use syntax::codemap::{Span, DUMMY_SP};
use syntax::parse::token::InternedString;
use syntax::attr::AttrMetaMethods;
use syntax::attr;
@ -736,6 +739,29 @@ pub fn coerce_unsized_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
}
pub fn custom_coerce_unsize_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
source_ty: Ty<'tcx>,
target_ty: Ty<'tcx>)
-> CustomCoerceUnsized {
let trait_substs = Substs::erased(subst::VecPerParamSpace::new(vec![target_ty],
vec![source_ty],
Vec::new()));
let trait_ref = ty::Binder(ty::TraitRef {
def_id: ccx.tcx().lang_items.coerce_unsized_trait().unwrap(),
substs: ccx.tcx().mk_substs(trait_substs)
});
match fulfill_obligation(ccx, DUMMY_SP, trait_ref) {
traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
ccx.tcx().custom_coerce_unsized_kind(impl_def_id)
}
vtable => {
ccx.sess().bug(&format!("invalid CoerceUnsized vtable: {:?}",
vtable));
}
}
}
pub fn cast_shift_expr_rhs(cx: Block, op: hir::BinOp_, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
cast_shift_rhs(op, lhs, rhs, |a, b| Trunc(cx, a, b), |a, b| ZExt(cx, a, b))
}
@ -1965,6 +1991,8 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
closure_env: closure::ClosureEnv<'b>) {
ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1);
record_translation_item_as_generated(ccx, fn_ast_id, param_substs);
let _icx = push_ctxt("trans_closure");
attributes::emit_uwtable(llfndecl, true);
@ -2078,6 +2106,24 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
// Insert the mandatory first few basic blocks before lltop.
finish_fn(&fcx, bcx, output_type, ret_debug_loc);
fn record_translation_item_as_generated<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
node_id: ast::NodeId,
param_substs: &'tcx Substs<'tcx>) {
let def_id = match ccx.tcx().node_id_to_type(node_id).sty {
ty::TyClosure(def_id, _) => def_id,
_ => ccx.external_srcs()
.borrow()
.get(&node_id)
.map(|did| *did)
.unwrap_or_else(|| ccx.tcx().map.local_def_id(node_id)),
};
ccx.record_translation_item_as_generated(TransItem::Fn{
def_id: def_id,
substs: ccx.tcx().mk_substs(ccx.tcx().erase_regions(param_substs)),
});
}
}
/// Creates an LLVM function corresponding to a source language function.
@ -3161,6 +3207,8 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>,
// First, verify intrinsics.
intrinsic::check_intrinsics(&ccx);
collect_translation_items(&ccx);
// Next, translate all items. See `TransModVisitor` for
// details on why we walk in this particular way.
{
@ -3168,6 +3216,8 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>,
intravisit::walk_mod(&mut TransItemsWithinModVisitor { ccx: &ccx }, &krate.module);
krate.visit_all_items(&mut TransModVisitor { ccx: &ccx });
}
collector::print_collection_results(&ccx);
}
for ccx in shared_ccx.iter() {
@ -3339,3 +3389,48 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TransItemsWithinModVisitor<'a, 'tcx> {
}
}
}
fn collect_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>) {
let time_passes = ccx.sess().time_passes();
let collection_mode = match ccx.sess().opts.debugging_opts.print_trans_items {
Some(ref s) => {
let mode_string = s.to_lowercase();
let mode_string = mode_string.trim();
if mode_string == "eager" {
TransItemCollectionMode::Eager
} else {
if mode_string != "lazy" {
let message = format!("Unknown codegen-item collection mode '{}'. \
Falling back to 'lazy' mode.",
mode_string);
ccx.sess().warn(&message);
}
TransItemCollectionMode::Lazy
}
}
None => TransItemCollectionMode::Lazy
};
let items = time(time_passes, "translation item collection", || {
collector::collect_crate_translation_items(&ccx, collection_mode)
});
if ccx.sess().opts.debugging_opts.print_trans_items.is_some() {
let mut item_keys: Vec<_> = items.iter()
.map(|i| i.to_string(ccx))
.collect();
item_keys.sort();
for item in item_keys {
println!("TRANS_ITEM {}", item);
}
let mut ccx_map = ccx.translation_items().borrow_mut();
for cgi in items {
ccx_map.insert(cgi, TransItemState::PredictedButNotGenerated);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,7 @@ use middle::def::Def;
use middle::def_id::DefId;
use trans::{adt, closure, debuginfo, expr, inline, machine};
use trans::base::{self, push_ctxt};
use trans::collector::TransItem;
use trans::common::{self, type_is_sized, ExprOrMethodCall, node_id_substs, C_nil, const_get_elt};
use trans::common::{CrateContext, C_integral, C_floating, C_bool, C_str_slice, C_bytes, val_ty};
use trans::common::{C_struct, C_undef, const_to_opt_int, const_to_opt_uint, VariantInfo, C_uint};
@ -1016,6 +1017,9 @@ pub fn trans_static(ccx: &CrateContext,
id: ast::NodeId,
attrs: &[ast::Attribute])
-> Result<ValueRef, ConstEvalErr> {
ccx.record_translation_item_as_generated(TransItem::Static(id));
unsafe {
let _icx = push_ctxt("trans_static");
let g = base::get_item_val(ccx, id);

View File

@ -24,6 +24,7 @@ use trans::debuginfo;
use trans::declare;
use trans::glue::DropGlueKind;
use trans::monomorphize::MonoId;
use trans::collector::{TransItem, TransItemState};
use trans::type_::{Type, TypeNames};
use middle::subst::Substs;
use middle::ty::{self, Ty};
@ -77,6 +78,8 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
available_drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, String>>,
use_dll_storage_attrs: bool,
translation_items: RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>>,
}
/// The local portion of a `CrateContext`. There is one `LocalCrateContext`
@ -245,7 +248,6 @@ impl<'a, 'tcx> Iterator for CrateContextMaybeIterator<'a, 'tcx> {
}
}
unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
let llcx = llvm::LLVMContextCreate();
let mod_name = CString::new(mod_name).unwrap();
@ -354,6 +356,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
check_drop_flag_for_sanity: check_drop_flag_for_sanity,
available_drop_glues: RefCell::new(FnvHashMap()),
use_dll_storage_attrs: use_dll_storage_attrs,
translation_items: RefCell::new(FnvHashMap()),
};
for i in 0..local_count {
@ -829,6 +832,24 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
pub fn mir_map(&self) -> &'b MirMap<'tcx> {
self.shared.mir_map
}
pub fn translation_items(&self) -> &RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>> {
&self.shared.translation_items
}
pub fn record_translation_item_as_generated(&self, cgi: TransItem<'tcx>) {
if self.sess().opts.debugging_opts.print_trans_items.is_none() {
return;
}
let mut codegen_items = self.translation_items().borrow_mut();
if codegen_items.contains_key(&cgi) {
codegen_items.insert(cgi, TransItemState::PredictedAndGenerated);
} else {
codegen_items.insert(cgi, TransItemState::NotPredictedButGenerated);
}
}
}
pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>);

View File

@ -55,9 +55,7 @@ use back::abi;
use llvm::{self, ValueRef, TypeKind};
use middle::const_qualif::ConstQualif;
use middle::def::Def;
use middle::lang_items::CoerceUnsizedTraitLangItem;
use middle::subst::{Substs, VecPerParamSpace};
use middle::traits;
use middle::subst::Substs;
use trans::{_match, adt, asm, base, callee, closure, consts, controlflow};
use trans::base::*;
use trans::build::*;
@ -500,24 +498,7 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let source = unpack_datum!(bcx, source.to_ref_datum(bcx));
assert!(target.kind.is_by_ref());
let trait_substs = Substs::erased(VecPerParamSpace::new(vec![target.ty],
vec![source.ty],
Vec::new()));
let trait_ref = ty::Binder(ty::TraitRef {
def_id: langcall(bcx, Some(span), "coercion",
CoerceUnsizedTraitLangItem),
substs: bcx.tcx().mk_substs(trait_substs)
});
let kind = match fulfill_obligation(bcx.ccx(), span, trait_ref) {
traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
bcx.tcx().custom_coerce_unsized_kind(impl_def_id)
}
vtable => {
bcx.sess().span_bug(span, &format!("invalid CoerceUnsized vtable: {:?}",
vtable));
}
};
let kind = custom_coerce_unsize_info(bcx.ccx(), source.ty, target.ty);
let repr_source = adt::represent_type(bcx.ccx(), source.ty);
let src_fields = match &*repr_source {

View File

@ -28,6 +28,7 @@ use trans::build::*;
use trans::callee;
use trans::cleanup;
use trans::cleanup::CleanupMethods;
use trans::collector::TransItem;
use trans::common::*;
use trans::debuginfo::DebugLoc;
use trans::declare;
@ -88,7 +89,7 @@ pub fn trans_exchange_free_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
}
fn type_needs_drop<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
pub fn type_needs_drop<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
tcx.type_needs_drop_given_env(ty, &tcx.empty_parameter_environment())
}
@ -496,6 +497,11 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in
fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueKind<'tcx>)
-> Block<'blk, 'tcx> {
let t = g.ty();
bcx.ccx()
.record_translation_item_as_generated(TransItem::DropGlue(bcx.tcx()
.erase_regions(&t)));
let skip_dtor = match g { DropGlueKind::Ty(_) => false, DropGlueKind::TyContents(_) => true };
// NB: v0 is an *alias* of type t here, not a direct value.
let _icx = push_ctxt("make_drop_glue");

View File

@ -495,7 +495,23 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
impl_def_id: id,
substs,
nested: _ }) => {
emit_vtable_methods(ccx, id, substs, param_substs).into_iter()
let nullptr = C_null(Type::nil(ccx).ptr_to());
get_vtable_methods(ccx, id, substs)
.into_iter()
.map(|opt_mth| {
match opt_mth {
Some(mth) => {
trans_fn_ref_with_substs(ccx,
mth.method.def_id,
ExprId(0),
param_substs,
mth.substs).val
}
None => nullptr
}
})
.collect::<Vec<_>>()
.into_iter()
}
traits::VtableClosure(
traits::VtableClosureData {
@ -549,18 +565,14 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
vtable
}
fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
impl_id: DefId,
substs: subst::Substs<'tcx>,
param_substs: &'tcx subst::Substs<'tcx>)
-> Vec<ValueRef>
pub fn get_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
impl_id: DefId,
substs: subst::Substs<'tcx>)
-> Vec<Option<ty::util::ImplMethod<'tcx>>>
{
let tcx = ccx.tcx();
debug!("emit_vtable_methods(impl_id={:?}, substs={:?}, param_substs={:?})",
impl_id,
substs,
param_substs);
debug!("get_vtable_methods(impl_id={:?}, substs={:?}", impl_id, substs);
let trt_id = match tcx.impl_trait_ref(impl_id) {
Some(t_id) => t_id.def_id,
@ -570,7 +582,6 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
tcx.populate_implementations_for_trait_if_necessary(trt_id);
let nullptr = C_null(Type::nil(ccx).ptr_to());
let trait_item_def_ids = tcx.trait_item_def_ids(trt_id);
trait_item_def_ids
.iter()
@ -587,7 +598,7 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
// method could never be called from this object, just supply
// null.
.map(|trait_method_def_id| {
debug!("emit_vtable_methods: trait_method_def_id={:?}",
debug!("get_vtable_methods: trait_method_def_id={:?}",
trait_method_def_id);
let trait_method_type = match tcx.impl_or_trait_item(trait_method_def_id) {
@ -598,18 +609,18 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
// Some methods cannot be called on an object; skip those.
if !traits::is_vtable_safe_method(tcx, trt_id, &trait_method_type) {
debug!("emit_vtable_methods: not vtable safe");
return nullptr;
debug!("get_vtable_methods: not vtable safe");
return None;
}
debug!("emit_vtable_methods: trait_method_type={:?}",
debug!("get_vtable_methods: trait_method_type={:?}",
trait_method_type);
// The substitutions we have are on the impl, so we grab
// the method type from the impl to substitute into.
let mth = tcx.get_impl_method(impl_id, substs.clone(), name);
debug!("emit_vtable_methods: mth={:?}", mth);
debug!("get_vtable_methods: mth={:?}", mth);
// If this is a default method, it's possible that it
// relies on where clauses that do not hold for this
@ -619,16 +630,12 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
if mth.is_provided {
let predicates = mth.method.predicates.predicates.subst(tcx, &mth.substs);
if !normalize_and_test_predicates(ccx, predicates.into_vec()) {
debug!("emit_vtable_methods: predicates do not hold");
return nullptr;
debug!("get_vtable_methods: predicates do not hold");
return None;
}
}
trans_fn_ref_with_substs(ccx,
mth.method.def_id,
ExprId(0),
param_substs,
mth.substs).val
Some(mth)
})
.collect()
}

View File

@ -58,6 +58,7 @@ mod _match;
mod meth;
mod mir;
mod monomorphize;
mod collector;
mod tvec;
mod type_;
mod type_of;

View File

@ -0,0 +1,34 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_type = "lib"]
pub trait Trait : Sized {
fn without_self() -> u32;
fn without_self_default() -> u32 { 0 }
fn with_default_impl(self) -> Self { self }
fn with_default_impl_generic<T>(self, x: T) -> (Self, T) { (self, x) }
fn without_default_impl(x: u32) -> (Self, u32);
fn without_default_impl_generic<T>(x: T) -> (Self, T);
}
impl Trait for char {
fn without_self() -> u32 { 2 }
fn without_default_impl(x: u32) -> (Self, u32) { ('c', x) }
fn without_default_impl_generic<T>(x: T) -> (Self, T) { ('c', x) }
}
impl Trait for u32 {
fn without_self() -> u32 { 1 }
fn without_default_impl(x: u32) -> (Self, u32) { (0, x) }
fn without_default_impl_generic<T>(x: T) -> (Self, T) { (0, x) }
}

View File

@ -0,0 +1,33 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_type = "lib"]
#[inline]
pub fn inlined_fn(x: i32, y: i32) -> i32 {
let closure = |a, b| { a + b };
closure(x, y)
}
pub fn inlined_fn_generic<T>(x: i32, y: i32, z: T) -> (i32, T) {
let closure = |a, b| { a + b };
(closure(x, y), z)
}
pub fn non_inlined_fn(x: i32, y: i32) -> i32 {
let closure = |a, b| { a + b };
closure(x, y)
}

View File

@ -0,0 +1,36 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_type = "lib"]
struct Struct(u32);
pub fn foo<T>(x: T) -> (T, u32, i8) {
let (x, Struct(y)) = bar(x);
(x, y, 2)
}
fn bar<T>(x: T) -> (T, Struct) {
let _ = not_exported_and_not_generic(0);
(x, Struct(1))
}
// These should not contribute to the codegen items of other crates.
#[inline(never)]
pub fn exported_but_not_generic(x: i32) -> i64 {
x as i64
}
#[inline(never)]
fn not_exported_and_not_generic(x: u32) -> u64 {
x as u64
}

View File

@ -0,0 +1,35 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
// aux-build:cgu_extern_closures.rs
extern crate cgu_extern_closures;
//~ TRANS_ITEM fn cross_crate_closures::main[0]
fn main() {
//~ TRANS_ITEM fn cgu_extern_closures[0]::inlined_fn[0]
//~ TRANS_ITEM fn cgu_extern_closures[0]::inlined_fn[0]::{{closure}}[0]
let _ = cgu_extern_closures::inlined_fn(1, 2);
//~ TRANS_ITEM fn cgu_extern_closures[0]::inlined_fn_generic[0]<i32>
//~ TRANS_ITEM fn cgu_extern_closures[0]::inlined_fn_generic[0]::{{closure}}[0]<i32>
let _ = cgu_extern_closures::inlined_fn_generic(3, 4, 5i32);
// Nothing should be generated for this call, we just link to the instance instance
// in the extern crate.
let _ = cgu_extern_closures::non_inlined_fn(6, 7);
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,34 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
// 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 cgu_generic_function[0]::bar[0]<u32>
//~ TRANS_ITEM fn cgu_generic_function[0]::foo[0]<u32>
let _ = cgu_generic_function::foo(1u32);
//~ TRANS_ITEM fn cgu_generic_function[0]::bar[0]<u64>
//~ TRANS_ITEM fn cgu_generic_function[0]::foo[0]<u64>
let _ = cgu_generic_function::foo(2u64);
// This should not introduce a codegen item
let _ = cgu_generic_function::exported_but_not_generic(3);
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,60 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
// 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()
{
// 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);
let _: (char, u32) = Trait::without_default_impl(0);
// Currently, no object code is generated for trait methods with default
// implemenations, unless they are actually called from somewhere. Therefore
// we cannot import the implementations and have to create our own inline.
//~ TRANS_ITEM fn cgu_export_trait_method[0]::Trait[0]::with_default_impl[0]<u32>
let _ = Trait::with_default_impl(0u32);
//~ TRANS_ITEM fn cgu_export_trait_method[0]::Trait[0]::with_default_impl[0]<char>
let _ = Trait::with_default_impl('c');
//~ TRANS_ITEM fn cgu_export_trait_method[0]::Trait[0]::with_default_impl_generic[0]<u32, &str>
let _ = Trait::with_default_impl_generic(0u32, "abc");
//~ TRANS_ITEM fn cgu_export_trait_method[0]::Trait[0]::with_default_impl_generic[0]<u32, bool>
let _ = Trait::with_default_impl_generic(0u32, false);
//~ TRANS_ITEM fn cgu_export_trait_method[0]::Trait[0]::with_default_impl_generic[0]<char, i16>
let _ = Trait::with_default_impl_generic('x', 1i16);
//~ TRANS_ITEM fn cgu_export_trait_method[0]::Trait[0]::with_default_impl_generic[0]<char, i32>
let _ = Trait::with_default_impl_generic('y', 0i32);
//~ TRANS_ITEM fn cgu_export_trait_method[0]::u32.Trait[0]::without_default_impl_generic[0]<char>
let _: (u32, char) = Trait::without_default_impl_generic('c');
//~ TRANS_ITEM fn cgu_export_trait_method[0]::u32.Trait[0]::without_default_impl_generic[0]<bool>
let _: (u32, bool) = Trait::without_default_impl_generic(false);
//~ TRANS_ITEM fn cgu_export_trait_method[0]::char.Trait[0]::without_default_impl_generic[0]<char>
let _: (char, char) = Trait::without_default_impl_generic('c');
//~ TRANS_ITEM fn cgu_export_trait_method[0]::char.Trait[0]::without_default_impl_generic[0]<bool>
let _: (char, bool) = Trait::without_default_impl_generic(false);
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,46 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
fn take_fn_once<T1, T2, F: FnOnce(T1, T2)>(f: F, x: T1, y: T2) {
(f)(x, y)
}
fn function<T1, T2>(_: T1, _: T2) {}
fn take_fn_pointer<T1, T2>(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::take_fn_once[0]<u32, &str, fn(u32, &str)>
//~ TRANS_ITEM fn function_as_argument::function[0]<u32, &str>
take_fn_once(function, 0u32, "abc");
//~ TRANS_ITEM fn function_as_argument::take_fn_once[0]<char, f64, fn(char, f64)>
//~ TRANS_ITEM fn function_as_argument::function[0]<char, f64>
take_fn_once(function, 'c', 0f64);
//~ TRANS_ITEM fn function_as_argument::take_fn_pointer[0]<i32, ()>
//~ TRANS_ITEM fn function_as_argument::function[0]<i32, ()>
take_fn_pointer(function, 0i32, ());
//~ TRANS_ITEM fn function_as_argument::take_fn_pointer[0]<f32, i64>
//~ TRANS_ITEM fn function_as_argument::function[0]<f32, i64>
take_fn_pointer(function, 0f32, 0i64);
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,98 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
struct StructWithDrop<T1, T2> {
x: T1,
y: T2,
}
impl<T1, T2> Drop for StructWithDrop<T1, T2> {
fn drop(&mut self) {}
}
struct StructNoDrop<T1, T2> {
x: T1,
y: T2,
}
enum EnumWithDrop<T1, T2> {
A(T1),
B(T2)
}
impl<T1, T2> Drop for EnumWithDrop<T1, T2> {
fn drop(&mut self) {}
}
enum EnumNoDrop<T1, T2> {
A(T1),
B(T2)
}
struct NonGenericNoDrop(i32);
struct NonGenericWithDrop(i32);
//~ TRANS_ITEM drop-glue generic_drop_glue::NonGenericWithDrop[0]
impl Drop for NonGenericWithDrop {
fn drop(&mut self) {}
//~ TRANS_ITEM fn generic_drop_glue::NonGenericWithDrop.Drop[0]::drop[0]
}
//~ TRANS_ITEM fn generic_drop_glue::main[0]
fn main() {
//~ TRANS_ITEM drop-glue generic_drop_glue::StructWithDrop[0]<i8, char>
//~ TRANS_ITEM fn generic_drop_glue::StructWithDrop<T1, T2>.Drop[0]::drop[0]<i8, char>
let _ = StructWithDrop { x: 0i8, y: 'a' }.x;
//~ TRANS_ITEM drop-glue generic_drop_glue::StructWithDrop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>
//~ TRANS_ITEM fn generic_drop_glue::StructWithDrop<T1, T2>.Drop[0]::drop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>
let _ = StructWithDrop { x: "&str", y: NonGenericNoDrop(0) }.y;
// Should produce no drop glue
let _ = StructNoDrop { x: 'a', y: 0u32 }.x;
// This is supposed to generate drop-glue because it contains a field that
// needs to be dropped.
//~ TRANS_ITEM drop-glue generic_drop_glue::StructNoDrop[0]<generic_drop_glue::NonGenericWithDrop[0], f64>
let _ = StructNoDrop { x: NonGenericWithDrop(0), y: 0f64 }.y;
//~ TRANS_ITEM drop-glue generic_drop_glue::EnumWithDrop[0]<i32, i64>
//~ TRANS_ITEM fn generic_drop_glue::EnumWithDrop<T1, T2>.Drop[0]::drop[0]<i32, i64>
let _ = match EnumWithDrop::A::<i32, i64>(0) {
EnumWithDrop::A(x) => x,
EnumWithDrop::B(x) => x as i32
};
//~ TRANS_ITEM drop-glue generic_drop_glue::EnumWithDrop[0]<f64, f32>
//~ TRANS_ITEM fn generic_drop_glue::EnumWithDrop<T1, T2>.Drop[0]::drop[0]<f64, f32>
let _ = match EnumWithDrop::B::<f64, f32>(1.0) {
EnumWithDrop::A(x) => x,
EnumWithDrop::B(x) => x as f64
};
let _ = match EnumNoDrop::A::<i32, i64>(0) {
EnumNoDrop::A(x) => x,
EnumNoDrop::B(x) => x as i32
};
let _ = match EnumNoDrop::B::<f64, f32>(1.0) {
EnumNoDrop::A(x) => x,
EnumNoDrop::B(x) => x as f64
};
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,64 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
fn foo1<T1>(a: T1) -> (T1, u32) {
(a, 1)
}
fn foo2<T1, T2>(a: T1, b: T2) -> (T1, T2) {
(a, b)
}
fn foo3<T1, T2, T3>(a: T1, b: T2, c: T3) -> (T1, T2, T3) {
(a, b, c)
}
// This function should be instantiated even if no used
//~ TRANS_ITEM fn generic_functions::lifetime_only[0]
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::foo1[0]<i32>
let _ = foo1(2i32);
//~ TRANS_ITEM fn generic_functions::foo1[0]<i64>
let _ = foo1(2i64);
//~ TRANS_ITEM fn generic_functions::foo1[0]<&str>
let _ = foo1("abc");
//~ TRANS_ITEM fn generic_functions::foo1[0]<char>
let _ = foo1('v');
//~ TRANS_ITEM fn generic_functions::foo2[0]<i32, i32>
let _ = foo2(2i32, 2i32);
//~ TRANS_ITEM fn generic_functions::foo2[0]<i64, &str>
let _ = foo2(2i64, "abc");
//~ TRANS_ITEM fn generic_functions::foo2[0]<&str, usize>
let _ = foo2("a", 2usize);
//~ TRANS_ITEM fn generic_functions::foo2[0]<char, ()>
let _ = foo2('v', ());
//~ TRANS_ITEM fn generic_functions::foo3[0]<i32, i32, i32>
let _ = foo3(2i32, 2i32, 2i32);
//~ TRANS_ITEM fn generic_functions::foo3[0]<i64, &str, char>
let _ = foo3(2i64, "abc", 'c');
//~ TRANS_ITEM fn generic_functions::foo3[0]<i16, &str, usize>
let _ = foo3(0i16, "a", 2usize);
//~ TRANS_ITEM fn generic_functions::foo3[0]<char, (), ()>
let _ = foo3('v', (), ());
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,81 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
struct Struct<T> {
x: T,
f: fn(x: T) -> T,
}
fn id<T>(x: T) -> T { x }
impl<T> Struct<T> {
fn new(x: T) -> Struct<T> {
Struct {
x: x,
f: id
}
}
fn get<T2>(self, x: T2) -> (T, T2) {
(self.x, x)
}
}
pub struct LifeTimeOnly<'a> {
_a: &'a u32
}
impl<'a> LifeTimeOnly<'a> {
//~ TRANS_ITEM fn generic_impl::LifeTimeOnly<'a>[0]::foo[0]
pub fn foo(&self) {}
//~ TRANS_ITEM fn generic_impl::LifeTimeOnly<'a>[0]::bar[0]
pub fn bar(&'a self) {}
//~ TRANS_ITEM fn generic_impl::LifeTimeOnly<'a>[0]::baz[0]
pub fn baz<'b>(&'b self) {}
pub fn non_instantiated<T>(&self) {}
}
//~ TRANS_ITEM fn generic_impl::main[0]
fn main() {
//~ TRANS_ITEM fn generic_impl::Struct<T>[0]::new[0]<i32>
//~ TRANS_ITEM fn generic_impl::id[0]<i32>
//~ TRANS_ITEM fn generic_impl::Struct<T>[0]::get[0]<i32, i16>
let _ = Struct::new(0i32).get(0i16);
//~ TRANS_ITEM fn generic_impl::Struct<T>[0]::new[0]<i64>
//~ TRANS_ITEM fn generic_impl::id[0]<i64>
//~ TRANS_ITEM fn generic_impl::Struct<T>[0]::get[0]<i64, i16>
let _ = Struct::new(0i64).get(0i16);
//~ TRANS_ITEM fn generic_impl::Struct<T>[0]::new[0]<char>
//~ TRANS_ITEM fn generic_impl::id[0]<char>
//~ TRANS_ITEM fn generic_impl::Struct<T>[0]::get[0]<char, i16>
let _ = Struct::new('c').get(0i16);
//~ TRANS_ITEM fn generic_impl::Struct<T>[0]::new[0]<&str>
//~ TRANS_ITEM fn generic_impl::id[0]<&str>
//~ TRANS_ITEM fn generic_impl::Struct<T>[0]::get[0]<generic_impl::Struct[0]<&str>, i16>
let _ = Struct::new(Struct::new("str")).get(0i16);
//~ TRANS_ITEM fn generic_impl::Struct<T>[0]::new[0]<generic_impl::Struct[0]<&str>>
//~ TRANS_ITEM fn generic_impl::id[0]<generic_impl::Struct[0]<&str>>
let _ = (Struct::new(Struct::new("str")).f)(Struct::new("str"));
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,36 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
trait SomeTrait {
fn foo(&self);
}
// This function is never instantiated but the contained impl must still be
// discovered.
pub fn generic_function<T>(x: T) -> (T, i32) {
impl SomeTrait for i64 {
//~ TRANS_ITEM fn impl_in_non_instantiated_generic::generic_function[0]::i64.SomeTrait[0]::foo[0]
fn foo(&self) {}
}
(x, 0)
}
//~ TRANS_ITEM fn impl_in_non_instantiated_generic::main[0]
fn main() {
0i64.foo();
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,42 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
trait Trait {
fn foo(&self) -> u32;
fn bar(&self);
}
struct Struct<T> {
_a: T
}
impl<T> Trait for Struct<T> {
fn foo(&self) -> u32 { 0 }
fn bar(&self) {}
}
//~ TRANS_ITEM fn instantiation_through_vtable::main[0]
fn main() {
let s1 = Struct { _a: 0u32 };
//~ TRANS_ITEM fn instantiation_through_vtable::Struct<T>.Trait[0]::foo[0]<u32>
//~ TRANS_ITEM fn instantiation_through_vtable::Struct<T>.Trait[0]::bar[0]<u32>
let _ = &s1 as &Trait;
let s1 = Struct { _a: 0u64 };
//~ TRANS_ITEM fn instantiation_through_vtable::Struct<T>.Trait[0]::foo[0]<u64>
//~ TRANS_ITEM fn instantiation_through_vtable::Struct<T>.Trait[0]::bar[0]<u64>
let _ = &s1 as &Trait;
}

View File

@ -0,0 +1,44 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
fn generic_fn<T>(a: T) -> (T, i32) {
//~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]::nested_fn[0]
fn nested_fn(a: i32) -> i32 {
a + 1
}
let x = {
//~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]::nested_fn[1]
fn nested_fn(a: i32) -> i32 {
a + 2
}
1 + nested_fn(1)
};
return (a, x + nested_fn(0));
}
//~ TRANS_ITEM fn items_within_generic_items::main[0]
fn main() {
//~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<i64>
let _ = generic_fn(0i64);
//~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<u16>
let _ = generic_fn(0u16);
//~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<i8>
let _ = generic_fn(0i8);
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,63 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
//~ TRANS_ITEM fn non_generic_closures::temporary[0]
fn temporary() {
//~ TRANS_ITEM fn non_generic_closures::temporary[0]::{{closure}}[0]
(|a: u32| {
let _ = a;
})(4);
}
//~ TRANS_ITEM fn non_generic_closures::assigned_to_variable_but_not_executed[0]
fn assigned_to_variable_but_not_executed() {
//~ TRANS_ITEM fn non_generic_closures::assigned_to_variable_but_not_executed[0]::{{closure}}[0]
let _x = |a: i16| {
let _ = a + 1;
};
}
//~ TRANS_ITEM fn non_generic_closures::assigned_to_variable_executed_directly[0]
fn assigned_to_variable_executed_indirectly() {
//~ TRANS_ITEM fn non_generic_closures::assigned_to_variable_executed_directly[0]::{{closure}}[0]
let f = |a: i32| {
let _ = a + 2;
};
run_closure(&f);
}
//~ TRANS_ITEM fn non_generic_closures::assigned_to_variable_executed_indirectly[0]
fn assigned_to_variable_executed_directly() {
//~ TRANS_ITEM fn non_generic_closures::assigned_to_variable_executed_indirectly[0]::{{closure}}[0]
let f = |a: i64| {
let _ = a + 3;
};
f(4);
}
//~ TRANS_ITEM fn non_generic_closures::main[0]
fn main() {
temporary();
assigned_to_variable_but_not_executed();
assigned_to_variable_executed_directly();
assigned_to_variable_executed_indirectly();
}
//~ TRANS_ITEM fn non_generic_closures::run_closure[0]
fn run_closure(f: &Fn(i32)) {
f(3);
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,56 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
//~ TRANS_ITEM drop-glue non_generic_drop_glue::StructWithDrop[0]
struct StructWithDrop {
x: i32
}
impl Drop for StructWithDrop {
//~ TRANS_ITEM fn non_generic_drop_glue::StructWithDrop.Drop[0]::drop[0]
fn drop(&mut self) {}
}
struct StructNoDrop {
x: i32
}
//~ TRANS_ITEM drop-glue non_generic_drop_glue::EnumWithDrop[0]
enum EnumWithDrop {
A(i32)
}
impl Drop for EnumWithDrop {
//~ TRANS_ITEM fn non_generic_drop_glue::EnumWithDrop.Drop[0]::drop[0]
fn drop(&mut self) {}
}
enum EnumNoDrop {
A(i32)
}
//~ TRANS_ITEM fn non_generic_drop_glue::main[0]
fn main() {
let _ = StructWithDrop { x: 0 }.x;
let _ = StructNoDrop { x: 0 }.x;
let _ = match EnumWithDrop::A(0) {
EnumWithDrop::A(x) => x
};
let _ = match EnumNoDrop::A(0) {
EnumNoDrop::A(x) => x
};
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,81 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
//~ TRANS_ITEM fn non_generic_functions::foo[0]
fn foo() {
{
//~ TRANS_ITEM fn non_generic_functions::foo[0]::foo[0]
fn foo() {}
foo();
}
{
//~ TRANS_ITEM fn non_generic_functions::foo[0]::foo[1]
fn foo() {}
foo();
}
}
//~ TRANS_ITEM fn non_generic_functions::bar[0]
fn bar() {
//~ TRANS_ITEM fn non_generic_functions::bar[0]::baz[0]
fn baz() {}
baz();
}
struct Struct { _x: i32 }
impl Struct {
//~ TRANS_ITEM fn non_generic_functions::Struct[0]::foo[0]
fn foo() {
{
//~ TRANS_ITEM fn non_generic_functions::Struct[0]::foo[0]::foo[0]
fn foo() {}
foo();
}
{
//~ TRANS_ITEM fn non_generic_functions::Struct[0]::foo[0]::foo[1]
fn foo() {}
foo();
}
}
//~ TRANS_ITEM fn non_generic_functions::Struct[0]::bar[0]
fn bar(&self) {
{
//~ TRANS_ITEM fn non_generic_functions::Struct[0]::bar[0]::foo[0]
fn foo() {}
foo();
}
{
//~ TRANS_ITEM fn non_generic_functions::Struct[0]::bar[0]::foo[1]
fn foo() {}
foo();
}
}
}
//~ TRANS_ITEM fn non_generic_functions::main[0]
fn main() {
foo();
bar();
Struct::foo();
let x = Struct { _x: 0 };
x.bar();
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,72 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
#![crate_type="lib"]
use std::ops::{Index, IndexMut, Add, Deref};
pub struct Indexable {
data: [u8; 3]
}
impl Index<usize> for Indexable {
type Output = u8;
//~ TRANS_ITEM fn overloaded_operators::Indexable.Index<usize>[0]::index[0]
fn index(&self, index: usize) -> &Self::Output {
if index >= 3 {
&self.data[0]
} else {
&self.data[index]
}
}
}
impl IndexMut<usize> for Indexable {
//~ TRANS_ITEM fn overloaded_operators::Indexable.IndexMut<usize>[0]::index_mut[0]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
if index >= 3 {
&mut self.data[0]
} else {
&mut self.data[index]
}
}
}
//~ TRANS_ITEM fn overloaded_operators::Equatable.::std::cmp::PartialEq[0]::eq[0]
//~ TRANS_ITEM fn overloaded_operators::Equatable.::std::cmp::PartialEq[0]::ne[0]
#[derive(PartialEq)]
pub struct Equatable(u32);
impl Add<u32> for Equatable {
type Output = u32;
//~ TRANS_ITEM fn overloaded_operators::Equatable.Add<u32>[0]::add[0]
fn add(self, rhs: u32) -> u32 {
self.0 + rhs
}
}
impl Deref for Equatable {
type Target = u32;
//~ TRANS_ITEM fn overloaded_operators::Equatable.Deref[0]::deref[0]
fn deref(&self) -> &Self::Target {
&self.0
}
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,64 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
static STATIC1: i64 = {
const STATIC1_CONST1: i64 = 2;
1 + CONST1 as i64 + STATIC1_CONST1
};
const CONST1: i64 = {
const CONST1_1: i64 = {
const CONST1_1_1: i64 = 2;
CONST1_1_1 + 1
};
1 + CONST1_1 as i64
};
fn foo() {
let _ = {
const CONST2: i64 = 0;
static STATIC2: i64 = CONST2;
let x = {
const CONST2: i64 = 1;
static STATIC2: i64 = CONST2;
STATIC2
};
x + STATIC2
};
let _ = {
const CONST2: i64 = 0;
static STATIC2: i64 = CONST2;
STATIC2
};
}
fn main() {
foo();
let _ = STATIC1;
}
//~ TRANS_ITEM static statics_and_consts::STATIC1[0]
//~ TRANS_ITEM fn statics_and_consts::foo[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[2]
//~ TRANS_ITEM fn statics_and_consts::main[0]
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,82 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
pub trait SomeTrait {
fn foo(&self);
fn bar<T>(&self, x: T);
}
impl SomeTrait for i64 {
//~ TRANS_ITEM fn trait_implementations::i64.SomeTrait[0]::foo[0]
fn foo(&self) {}
fn bar<T>(&self, _: T) {}
}
impl SomeTrait for i32 {
//~ TRANS_ITEM fn trait_implementations::i32.SomeTrait[0]::foo[0]
fn foo(&self) {}
fn bar<T>(&self, _: T) {}
}
pub trait SomeGenericTrait<T> {
fn foo(&self, x: T);
fn bar<T2>(&self, x: T, y: T2);
}
// Concrete impl of generic trait
impl SomeGenericTrait<u32> for f64 {
//~ TRANS_ITEM fn trait_implementations::f64.SomeGenericTrait<u32>[0]::foo[0]
fn foo(&self, _: u32) {}
fn bar<T2>(&self, _: u32, _: T2) {}
}
// Generic impl of generic trait
impl<T> SomeGenericTrait<T> for f32 {
fn foo(&self, _: T) {}
fn bar<T2>(&self, _: T, _: T2) {}
}
//~ TRANS_ITEM fn trait_implementations::main[0]
fn main() {
//~ TRANS_ITEM fn trait_implementations::i32.SomeTrait[0]::bar[0]<char>
0i32.bar('x');
//~ TRANS_ITEM fn trait_implementations::f64.SomeGenericTrait<u32>[0]::bar[0]<&str>
0f64.bar(0u32, "&str");
//~ TRANS_ITEM fn trait_implementations::f64.SomeGenericTrait<u32>[0]::bar[0]<()>
0f64.bar(0u32, ());
//~ TRANS_ITEM fn trait_implementations::f32.SomeGenericTrait<T>[0]::foo[0]<char>
0f32.foo('x');
//~ TRANS_ITEM fn trait_implementations::f32.SomeGenericTrait<T>[0]::foo[0]<i64>
0f32.foo(-1i64);
//~ TRANS_ITEM fn trait_implementations::f32.SomeGenericTrait<T>[0]::bar[0]<u32, ()>
0f32.bar(0u32, ());
//~ TRANS_ITEM fn trait_implementations::f32.SomeGenericTrait<T>[0]::bar[0]<&str, &str>
0f32.bar("&str", "&str");
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,62 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
trait Trait : Sized {
fn foo(self) -> Self { self }
}
impl Trait for u32 {
fn foo(self) -> u32 { self }
}
impl Trait for char {
}
fn take_foo_once<T, F: FnOnce(T) -> T>(f: F, arg: T) -> T {
(f)(arg)
}
fn take_foo<T, F: Fn(T) -> T>(f: F, arg: T) -> T {
(f)(arg)
}
fn take_foo_mut<T, F: FnMut(T) -> 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::take_foo_once[0]<u32, fn(u32) -> u32>
//~ TRANS_ITEM fn trait_method_as_argument::u32.Trait[0]::foo[0]
take_foo_once(Trait::foo, 0u32);
//~ TRANS_ITEM fn trait_method_as_argument::take_foo_once[0]<char, fn(char) -> char>
//~ TRANS_ITEM fn trait_method_as_argument::Trait[0]::foo[0]<char>
take_foo_once(Trait::foo, 'c');
//~ TRANS_ITEM fn trait_method_as_argument::take_foo[0]<u32, fn(u32) -> u32>
take_foo(Trait::foo, 0u32);
//~ TRANS_ITEM fn trait_method_as_argument::take_foo[0]<char, fn(char) -> char>
take_foo(Trait::foo, 'c');
//~ TRANS_ITEM fn trait_method_as_argument::take_foo_mut[0]<u32, fn(u32) -> u32>
take_foo_mut(Trait::foo, 0u32);
//~ TRANS_ITEM fn trait_method_as_argument::take_foo_mut[0]<char, fn(char) -> char>
take_foo_mut(Trait::foo, 'c');
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,70 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
trait SomeTrait {
fn foo(&self) { }
fn bar<T>(&self, x: T) -> T { x }
}
impl SomeTrait for i8 {
// take the default implementations
// For the non-generic foo(), we should generate a codegen-item even if it
// is not called anywhere
//~ TRANS_ITEM fn trait_method_default_impl::SomeTrait[0]::foo[0]<i8>
}
trait SomeGenericTrait<T1> {
fn foo(&self) { }
fn bar<T2>(&self, x: T1, y: T2) {}
}
// Non-generic impl of generic trait
impl SomeGenericTrait<u64> for i32 {
// take the default implementations
// For the non-generic foo(), we should generate a codegen-item even if it
// is not called anywhere
//~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::foo[0]<u64, i32>
}
// Non-generic impl of generic trait
impl<T1> SomeGenericTrait<T1> for u32 {
// take the default implementations
// 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::SomeTrait[0]::bar[0]<i8, char>
let _ = 1i8.bar('c');
//~ TRANS_ITEM fn trait_method_default_impl::SomeTrait[0]::bar[0]<i8, &str>
let _ = 2i8.bar("&str");
//~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<u64, i32, char>
0i32.bar(0u64, 'c');
//~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<u64, i32, &str>
0i32.bar(0u64, "&str");
//~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<i8, u32, &[char; 1]>
0u32.bar(0i8, &['c']);
//~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<i16, u32, ()>
0u32.bar(0i16, ());
}
//~ TRANS_ITEM drop-glue i8

View File

@ -0,0 +1,55 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
//~ TRANS_ITEM drop-glue transitive_drop_glue::Root[0]
struct Root(Intermediate);
//~ TRANS_ITEM drop-glue transitive_drop_glue::Intermediate[0]
struct Intermediate(Leaf);
//~ TRANS_ITEM drop-glue transitive_drop_glue::Leaf[0]
struct Leaf;
impl Drop for Leaf {
//~ TRANS_ITEM fn transitive_drop_glue::Leaf.Drop[0]::drop[0]
fn drop(&mut self) {}
}
//~ TRANS_ITEM drop-glue transitive_drop_glue::Root[0]
struct RootGen<T>(IntermediateGen<T>);
//~ TRANS_ITEM drop-glue transitive_drop_glue::Root[0]
struct IntermediateGen<T>(LeafGen<T>);
//~ TRANS_ITEM drop-glue transitive_drop_glue::Root[0]
struct LeafGen<T>(T);
impl<T> Drop for LeafGen<T> {
fn drop(&mut self) {}
}
//~ TRANS_ITEM fn transitive_drop_glue::main[0]
fn main() {
let _ = Root(Intermediate(Leaf));
//~ TRANS_ITEM drop-glue transitive_drop_glue::RootGen[0]<u32>
//~ TRANS_ITEM drop-glue transitive_drop_glue::IntermediateGen[0]<u32>
//~ TRANS_ITEM drop-glue transitive_drop_glue::LeafGen[0]<u32>
//~ TRANS_ITEM fn transitive_drop_glue::LeafGen<T>.Drop[0]::drop[0]<u32>
let _ = RootGen(IntermediateGen(LeafGen(0u32)));
//~ TRANS_ITEM drop-glue transitive_drop_glue::RootGen[0]<i16>
//~ TRANS_ITEM drop-glue transitive_drop_glue::IntermediateGen[0]<i16>
//~ TRANS_ITEM drop-glue transitive_drop_glue::LeafGen[0]<i16>
//~ TRANS_ITEM fn transitive_drop_glue::LeafGen<T>.Drop[0]::drop[0]<i16>
let _ = RootGen(IntermediateGen(LeafGen(0i16)));
}

View File

@ -0,0 +1,32 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
//~ TRANS_ITEM drop-glue tuple_drop_glue::Dropped[0]
struct Dropped;
impl Drop for Dropped {
//~ TRANS_ITEM fn tuple_drop_glue::Dropped.Drop[0]::drop[0]
fn drop(&mut self) {}
}
//~ TRANS_ITEM fn tuple_drop_glue::main[0]
fn main() {
//~ TRANS_ITEM drop-glue (u32, tuple_drop_glue::Dropped[0])
let x = (0u32, Dropped);
//~ TRANS_ITEM drop-glue (i16, (tuple_drop_glue::Dropped[0], bool))
//~ TRANS_ITEM drop-glue (tuple_drop_glue::Dropped[0], bool)
let x = (0i16, (Dropped, true));
}

View File

@ -0,0 +1,80 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![deny(dead_code)]
#![feature(coerce_unsized)]
#![feature(unsize)]
use std::marker::Unsize;
use std::ops::CoerceUnsized;
trait Trait {
fn foo(&self);
}
// Simple Case
impl Trait for bool {
fn foo(&self) {}
}
impl Trait for char {
fn foo(&self) {}
}
// Struct Field Case
struct Struct<T: ?Sized> {
_a: u32,
_b: i32,
_c: T
}
impl Trait for f64 {
fn foo(&self) {}
}
// Custom Coercion Case
impl Trait for u32 {
fn foo(&self) {}
}
#[derive(Clone, Copy)]
struct Wrapper<T: ?Sized>(*const T);
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
//~ TRANS_ITEM fn unsizing::main[0]
fn main()
{
// simple case
let bool_sized = &true;
//~ TRANS_ITEM fn unsizing::bool.Trait[0]::foo[0]
let _bool_unsized = bool_sized as &Trait;
let char_sized = &true;
//~ TRANS_ITEM fn unsizing::char.Trait[0]::foo[0]
let _char_unsized = char_sized as &Trait;
// struct field
let struct_sized = &Struct {
_a: 1,
_b: 2,
_c: 3.0f64
};
//~ TRANS_ITEM fn unsizing::f64.Trait[0]::foo[0]
let _struct_unsized = struct_sized as &Struct<Trait>;
// custom coercion
let wrapper_sized = Wrapper(&0u32);
//~ TRANS_ITEM fn unsizing::u32.Trait[0]::foo[0]
let _wrapper_sized = wrapper_sized as Wrapper<Trait>;
}

View File

@ -0,0 +1,89 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
// compile-flags:-Zprint-trans-items=eager
#![crate_type="lib"]
#![deny(dead_code)]
// This test asserts that no codegen items are generated for generic items that
// are never instantiated in the local crate.
pub trait Trait {
fn foo() {}
fn bar(&self) {}
}
pub fn foo<T: Copy>(x: T) -> (T, T) {
(x, x)
}
pub struct Struct<T> {
x: T
}
impl<T> Struct<T> {
pub fn foo(self) -> T {
self.x
}
pub fn bar() {}
}
pub enum Enum<T> {
A(T),
B { x: T }
}
impl<T> Enum<T> {
pub fn foo(self) -> T {
match self {
Enum::A(x) => x,
Enum::B { x } => x,
}
}
pub fn bar() {}
}
pub struct TupleStruct<T>(T);
impl<T> TupleStruct<T> {
pub fn foo(self) -> T {
self.0
}
pub fn bar() {}
}
pub type Pair<T> = (T, T);
pub struct NonGeneric {
x: i32
}
impl NonGeneric {
pub fn foo(self) -> i32 {
self.x
}
pub fn generic_foo<T>(&self, x: T) -> (T, i32) {
(x, self.x)
}
pub fn generic_bar<T: Copy>(x: T) -> (T, T) {
(x, x)
}
}
// Only the non-generic methods should be instantiated:
//~ TRANS_ITEM fn unused_traits_and_generics::NonGeneric[0]::foo[0]
//~ TRANS_ITEM drop-glue i8