diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 42cda6a05a1a7..616894f7ebcab 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -640,6 +640,7 @@ define_dep_nodes!( <'tcx> [] NormalizeProjectionTy(CanonicalProjectionGoal<'tcx>), [] NormalizeTyAfterErasingRegions(ParamEnvAnd<'tcx, Ty<'tcx>>), [] DropckOutlives(CanonicalTyGoal<'tcx>), + [] CollapseInterchangableInstances { instance: Instance<'tcx> }, [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) }, diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 594adfca6b3c0..cd9c9ef5dd8aa 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -833,9 +833,14 @@ for ty::TypeVariants<'gcx> TyChar | TyStr | TyError | - TyNever => { + TyNever | + TyUnusedParam => { // Nothing more to hash. } + TyLayoutOnlyParam(size, align) => { + size.hash_stable(hcx, hasher); + align.hash_stable(hcx, hasher); + } TyInt(int_ty) => { int_ty.hash_stable(hcx, hasher); } diff --git a/src/librustc/infer/canonical.rs b/src/librustc/infer/canonical.rs index 4357c9a5a776a..8866eadbddd59 100644 --- a/src/librustc/infer/canonical.rs +++ b/src/librustc/infer/canonical.rs @@ -634,7 +634,9 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> | ty::TyProjection(..) | ty::TyForeign(..) | ty::TyParam(..) - | ty::TyAnon(..) => { + | ty::TyAnon(..) + | ty::TyUnusedParam + | ty::TyLayoutOnlyParam(..) => { if t.flags.intersects(self.needs_canonical_flags) { t.super_fold_with(self) } else { diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index 6074bfd083d46..e8a1029a16937 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -200,6 +200,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { ty::TyAnon(..) => { t.super_fold_with(self) } + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) => { + bug!("Unexpected {:?} in TypeFreshener", t); + } } } } diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 31f8af1f96872..ff17d188f7064 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -480,7 +480,9 @@ fn ty_is_local_constructor(ty: Ty, in_crate: InCrate) -> bool { ty::TyClosure(..) | ty::TyGenerator(..) | ty::TyGeneratorWitness(..) | - ty::TyAnon(..) => { + ty::TyAnon(..) | + ty::TyUnusedParam | + ty::TyLayoutOnlyParam(_, _) => { bug!("ty_is_local invoked on unexpected type: {:?}", ty) } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index d2bde14732bbc..ff34a100b83ca 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -263,7 +263,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::TyGenerator(..) => Some(18), ty::TyForeign(..) => Some(19), ty::TyGeneratorWitness(..) => Some(20), - ty::TyInfer(..) | ty::TyError => None + ty::TyInfer(..) | ty::TyError => None, + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) => { + bug!("unexpected {:?} in fuzzy_match_tys", t); + } } } diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index af1d2c77c28a8..54c2f01a66ad0 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -261,5 +261,9 @@ fn trivial_dropck_outlives<'cx, 'tcx>(tcx: TyCtxt<'cx, '_, 'tcx>, ty: Ty<'tcx>) | ty::TyAnon(..) | ty::TyInfer(_) | ty::TyGenerator(..) => false, + + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) => { + bug!("Unexpected {:?} in trivial_dropck_outlives", ty) + } } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 93ae101eb1426..d8dd2e40c5505 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2037,7 +2037,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { )) } - ty::TyProjection(_) | ty::TyParam(_) | ty::TyAnon(..) => None, + ty::TyProjection(_) | ty::TyParam(_) | ty::TyUnusedParam | + ty::TyLayoutOnlyParam(_, _) | ty::TyAnon(..) => None, ty::TyInfer(ty::TyVar(_)) => Ambiguous, ty::TyInfer(ty::CanonicalTy(_)) | @@ -2114,6 +2115,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty); } + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) => { + bug!("Unexpected {:?} in copy_clone_conditions", self_ty); + } } } @@ -2150,6 +2154,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::TyForeign(..) | ty::TyProjection(..) | ty::TyInfer(ty::CanonicalTy(_)) | + ty::TyUnusedParam | + ty::TyLayoutOnlyParam(_, _) | ty::TyInfer(ty::TyVar(_)) | ty::TyInfer(ty::FreshTy(_)) | ty::TyInfer(ty::FreshIntTy(_)) | diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index fdda2286da03b..f1574df66dfa7 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1780,6 +1780,7 @@ macro_rules! sty_debug_print { region_infer: 0, ty_infer: 0, both_infer: 0, }; $(let mut $variant = total;)* + let mut TyUnusedParam = total; for &Interned(t) in tcx.interners.type_.borrow().iter() { @@ -1787,6 +1788,7 @@ macro_rules! sty_debug_print { ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) | ty::TyFloat(..) | ty::TyStr | ty::TyNever => continue, ty::TyError => /* unimportant */ continue, + ty::TyUnusedParam => &mut TyUnusedParam, $(ty::$variant(..) => &mut $variant,)* }; let region = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER); @@ -1827,7 +1829,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { self, TyAdt, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, TyGenerator, TyGeneratorWitness, TyDynamic, TyClosure, TyTuple, - TyParam, TyInfer, TyProjection, TyAnon, TyForeign); + TyParam, TyLayoutOnlyParam, TyInfer, TyProjection, TyAnon, TyForeign); println!("Substs interner: #{}", self.interners.substs.borrow().len()); println!("Region interner: #{}", self.interners.region.borrow().len()); diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index eb3924186472c..cc104de6cb454 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -232,6 +232,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { "type parameter".to_string() } } + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) => "unused type parameter".to_string(), ty::TyAnon(..) => "anonymized type".to_string(), ty::TyError => "type error".to_string(), } diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 31b3ca44700e9..90117b7e41bba 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -121,7 +121,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::TyForeign(def_id) => { Some(ForeignSimplifiedType(def_id)) } - ty::TyInfer(_) | ty::TyError => None, + ty::TyInfer(_) | ty::TyError | ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) => None, } } diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 086fc66c70f9d..2404f969b2181 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -190,6 +190,9 @@ impl FlagComputation { &ty::TyFnPtr(f) => { self.add_fn_sig(f); } + &ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) => { + bug!("Unexpected {:?} in FlagComputation::for_sty", st); + } } } diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 1f23b0a27e33d..e40de8f3cc51b 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -373,6 +373,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option { ty::TyProjection(_) | ty::TyParam(_) | ty::TyAnon(..) | + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) | ty::TyInfer(_) | ty::TyError | ty::TyGeneratorWitness(..) | diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 5f9c305d92f04..bc02b607c4697 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -234,7 +234,7 @@ pub enum Endian { } /// Size of a type in bytes. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct Size { raw: u64 } @@ -1712,7 +1712,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { ty::TyParam(_) => { return Err(LayoutError::Unknown(ty)); } - ty::TyGeneratorWitness(..) | ty::TyInfer(_) | ty::TyError => { + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) | ty::TyGeneratorWitness(..) | + ty::TyInfer(_) | ty::TyError => { bug!("LayoutDetails::compute: unexpected type `{}`", ty) } }) @@ -2287,8 +2288,8 @@ impl<'a, 'tcx> TyLayout<'tcx> { } } - ty::TyProjection(_) | ty::TyAnon(..) | ty::TyParam(_) | - ty::TyInfer(_) | ty::TyError => { + ty::TyProjection(_) | ty::TyAnon(..) | ty::TyParam(_) | ty::TyUnusedParam | + ty::TyLayoutOnlyParam(_, _) | ty::TyInfer(_) | ty::TyError => { bug!("TyLayout::field_type: unexpected type `{}`", self.ty) } }) diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index bb9467305e335..7be145001bc99 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -639,6 +639,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::typeck_tables_of<'tcx> { } } +impl<'tcx> QueryDescription<'tcx> for queries::collapse_interchangable_instances<'tcx> { + fn describe(_tcx: TyCtxt, instance: ty::Instance<'tcx>) -> String { + format!("collapse interchangable instance {:?}", instance) + } +} + impl<'tcx> QueryDescription<'tcx> for queries::optimized_mir<'tcx> { #[inline] fn cache_on_disk(def_id: Self::Key) -> bool { diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 2bfb687032923..35307571d3f10 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -430,6 +430,9 @@ define_maps! { <'tcx> [] fn wasm_custom_sections: WasmCustomSections(CrateNum) -> Lrc>, [] fn wasm_import_module_map: WasmImportModuleMap(CrateNum) -> Lrc>, + + [] fn collapse_interchangable_instances: + collapse_interchangable_instances_dep_node(ty::Instance<'tcx>) -> ty::Instance<'tcx>, } ////////////////////////////////////////////////////////////////////// @@ -592,3 +595,11 @@ fn instance_def_size_estimate_dep_node<'tcx>(instance_def: ty::InstanceDef<'tcx> instance_def } } + +fn collapse_interchangable_instances_dep_node<'tcx>( + instance: ty::Instance<'tcx> +) -> DepConstructor<'tcx> { + DepConstructor::CollapseInterchangableInstances { + instance, + } +} diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 50a19526ba8c4..9ffceabf5759d 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -777,6 +777,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::DropckOutlives | DepKind::SubstituteNormalizeAndTestPredicates | DepKind::InstanceDefSizeEstimate | + DepKind::CollapseInterchangableInstances | // This one should never occur in this context DepKind::Null => { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 72ba199eb2412..97521f3e595f5 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -43,11 +43,13 @@ use std::cell::RefCell; use std::cmp; use std::fmt; use std::hash::{Hash, Hasher}; +use std::iter; use std::ops::Deref; use rustc_data_structures::sync::Lrc; use std::slice; use std::vec::IntoIter; use std::mem; +use syntax::abi::Abi; use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId}; use syntax::attr; use syntax::ext::hygiene::{Mark, SyntaxContext}; @@ -2067,7 +2069,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } - TyInfer(..) => { + TyUnusedParam | ty::TyLayoutOnlyParam(_, _) | TyInfer(..) => { bug!("unexpected type `{:?}` in sized_constraint_for_ty", ty) } @@ -2811,3 +2813,48 @@ impl fmt::Debug for SymbolName { fmt::Display::fmt(&self.name, fmt) } } + +pub fn ty_fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + ty: Ty<'tcx>) + -> ty::PolyFnSig<'tcx> +{ + match ty.sty { + ty::TyFnDef(..) | + // Shims currently have type TyFnPtr. Not sure this should remain. + ty::TyFnPtr(_) => ty.fn_sig(tcx), + ty::TyClosure(def_id, substs) => { + let sig = substs.closure_sig(def_id, tcx); + + let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); + sig.map_bound(|sig| tcx.mk_fn_sig( + iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), + sig.output(), + sig.variadic, + sig.unsafety, + sig.abi + )) + } + ty::TyGenerator(def_id, substs, _) => { + let sig = substs.generator_poly_sig(def_id, tcx); + + let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv); + let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); + + sig.map_bound(|sig| { + let state_did = tcx.lang_items().gen_state().unwrap(); + let state_adt_ref = tcx.adt_def(state_did); + let state_substs = tcx.mk_substs([sig.yield_ty.into(), + sig.return_ty.into()].iter()); + let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); + + tcx.mk_fn_sig(iter::once(env_ty), + ret_ty, + false, + hir::Unsafety::Normal, + Abi::Rust + ) + }) + } + _ => bug!("unexpected type {:?} to ty_fn_sig", ty) + } +} diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index ff99a4b7ff638..a7ce0a512054c 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -167,6 +167,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.compute_components(subty, out); } } + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) => { + bug!("Unexpected TyUnusedParam in compute_components"); + } } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 8cf662ccaea92..13e9b9144584e 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -865,7 +865,8 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyAnon(did, substs) => ty::TyAnon(did, substs.fold_with(folder)), ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) | - ty::TyParam(..) | ty::TyNever | ty::TyForeign(..) => return self + ty::TyParam(..) | ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) | + ty::TyNever | ty::TyForeign(..) => return self }; if self.sty == sty { @@ -900,7 +901,8 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyAnon(_, ref substs) => substs.visit_with(visitor), ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) | - ty::TyParam(..) | ty::TyNever | ty::TyForeign(..) => false, + ty::TyParam(..) | ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) | + ty::TyNever | ty::TyForeign(..) => false, } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index ed04d41ba1457..3fe0c0ba2481f 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -18,6 +18,7 @@ use rustc_data_structures::indexed_vec::Idx; use ty::subst::{Substs, Subst, Kind, UnpackedKind}; use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable}; use ty::{Slice, TyS}; +use ty::layout::{Size, Align}; use util::captures::Captures; use std::iter; @@ -164,6 +165,12 @@ pub enum TypeVariants<'tcx> { /// A type parameter; for example, `T` in `fn f(x: T) {} TyParam(ParamTy), + /// Substitution for a unused type parameter; see rustc_mir::monomorphize::deduplicate_instances + TyUnusedParam, + + /// Substitution for a type parameter whose size and layout is the onlything that matters + TyLayoutOnlyParam(Size, Align), + /// A type variable used during type-checking. TyInfer(InferTy), @@ -1633,6 +1640,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { TyTuple(..) | TyForeign(..) | TyParam(_) | + TyUnusedParam | ty::TyLayoutOnlyParam(_, _) | TyInfer(_) | TyError => { vec![] diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index afe977d10baac..582380f3cb556 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -733,6 +733,9 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W> TyStr | TySlice(_) => {} + // This can be generated by collapse_interchangable_instances + TyUnusedParam | ty::TyLayoutOnlyParam(_, _) => self.hash(""), + TyError | TyInfer(_) => bug!("TypeIdHasher: unexpected type {}", ty) } @@ -1122,6 +1125,10 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def.variants.iter().any( |variant| variant.fields.iter().any( |field| needs_drop(field.ty(tcx, substs)))), + + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) => { + bug!("Unexpected type {:?} in needs_drop_raw", ty); + } } } diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 46c048e839b4b..022bcf790b1f2 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -82,8 +82,8 @@ pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> AccIntoIter> { fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { match parent_ty.sty { ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | - ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyNever | ty::TyError | - ty::TyForeign(..) => { + ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyUnusedParam | + ty::TyLayoutOnlyParam(_, _) | ty::TyNever | ty::TyError | ty::TyForeign(..) => { } ty::TyArray(ty, len) => { push_const(stack, len); diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index f05d56c9d8371..2211d485d0918 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -261,6 +261,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { ty::TyGeneratorWitness(..) | ty::TyNever | ty::TyParam(_) | + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) | ty::TyForeign(..) => { // WfScalar, WfParameter, etc } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index d27cda4040e56..c2d9292db9a23 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -16,7 +16,7 @@ use ty::subst::{self, Subst}; use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use ty::{TyBool, TyChar, TyAdt}; use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr}; -use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple}; +use ty::{TyParam, TyUnusedParam, TyRawPtr, TyRef, TyNever, TyTuple}; use ty::{TyClosure, TyGenerator, TyGeneratorWitness, TyForeign, TyProjection, TyAnon}; use ty::{TyDynamic, TyInt, TyUint, TyInfer}; use ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -1044,6 +1044,7 @@ define_print! { TyInfer(infer_ty) => write!(f, "{}", infer_ty), TyError => write!(f, "[type error]"), TyParam(ref param_ty) => write!(f, "{}", param_ty), + TyUnusedParam | ty::TyLayoutOnlyParam(_, _) => write!(f, "[unused type param]"), TyAdt(def, substs) => cx.parameterized(f, substs, def.did, &[]), TyDynamic(data, r) => { data.print(f, cx)?; diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 445fe0cc40197..30cea94493440 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -705,6 +705,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::TyForeign(..) => FfiSafe, ty::TyParam(..) | + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) | ty::TyInfer(..) | ty::TyError | ty::TyClosure(..) | @@ -712,7 +713,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::TyGeneratorWitness(..) | ty::TyProjection(..) | ty::TyAnon(..) | - ty::TyFnDef(..) => bug!("Unexpected type in foreign function"), + ty::TyFnDef(..) => bug!("Unexpected type `{:?}` in foreign function", ty), } } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 7af3a397666e8..ae5202fe630fd 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -31,6 +31,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![cfg_attr(stage0, feature(inclusive_range_syntax))] #![feature(macro_vis_matcher)] #![cfg_attr(stage0, feature(match_default_bindings))] +#![feature(macro_lifetime_matcher)] #![feature(exhaustive_patterns)] #![feature(range_contains)] #![feature(rustc_diagnostic_macros)] @@ -82,6 +83,8 @@ pub fn provide(providers: &mut Providers) { transform::provide(providers); providers.const_eval = interpret::const_eval_provider; providers.check_match = hair::pattern::check_match; + providers.collapse_interchangable_instances = + monomorphize::deduplicate_instances::collapse_interchangable_instances; } __build_diagnostic_array! { librustc_mir, DIAGNOSTICS } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 446ef6bd32876..028ca3cd2d443 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -315,6 +315,8 @@ pub fn collect_crate_mono_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, &mut inlining_map); } + //tcx.sess.warn(&format!("{:#?}", visited)); + (visited, inlining_map) } @@ -374,6 +376,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Sanity check whether this ended up being collected accidentally debug_assert!(should_monomorphize_locally(tcx, &instance)); + let instance = tcx.collapse_interchangable_instances(instance); let ty = instance.ty(tcx); visit_drop_use(tcx, ty, true, &mut neighbors); @@ -397,6 +400,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, MonoItem::Fn(instance) => { // Sanity check whether this ended up being collected accidentally debug_assert!(should_monomorphize_locally(tcx, &instance)); + let instance = tcx.collapse_interchangable_instances(instance); // Keep track of the monomorphization recursion depth recursion_depth_reset = Some(check_recursion_limit(tcx, @@ -692,6 +696,8 @@ fn visit_instance_use<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return } + let instance = tcx.collapse_interchangable_instances(instance); + match instance.def { ty::InstanceDef::Intrinsic(def_id) => { if !is_direct_call { @@ -883,6 +889,7 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::ParamEnv::reveal_all(), def_id, substs).unwrap()) + .map(|instance|tcx.collapse_interchangable_instances(instance)) .filter(|&instance| should_monomorphize_locally(tcx, &instance)) .map(|instance| create_fn_mono_item(instance)); output.extend(methods); diff --git a/src/librustc_mir/monomorphize/deduplicate_instances.rs b/src/librustc_mir/monomorphize/deduplicate_instances.rs new file mode 100644 index 0000000000000..929b3e952b4fb --- /dev/null +++ b/src/librustc_mir/monomorphize/deduplicate_instances.rs @@ -0,0 +1,232 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc_data_structures::indexed_vec::IndexVec; +use rustc::ty::{self, TyCtxt, Ty, TypeVariants, ParamTy, TypeFoldable, Instance, ParamEnv}; +use rustc::ty::fold::TypeFolder; +use rustc::ty::subst::{Kind, UnpackedKind}; +use rustc::ty::layout::{LayoutCx, LayoutOf}; +use rustc::middle::const_val::ConstVal; +use rustc::mir::{Mir, Rvalue, Location}; +use rustc::mir::visit::{Visitor, TyContext}; + +/// Replace substs which aren't used by the function with TyError, +/// so that it doesn't end up in the binary multiple times +/// For example in the code +/// +/// ```rust +/// fn foo() { } // here, T is clearly unused =) +/// +/// fn main() { +/// foo::(); +/// foo::(); +/// } +/// ``` +/// +/// `foo::` and `foo::` are collapsed to `foo::<{some dummy}>`, +/// because codegen for `foo` doesn't depend on the Subst for T. +pub(crate) fn collapse_interchangable_instances<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mut instance: Instance<'tcx> +) -> Instance<'tcx> { + info!("replace_unused_substs_with_ty_error({:?})", instance); + + if instance.substs.is_noop() || !tcx.is_mir_available(instance.def_id()) { + return instance; + } + match instance.ty(tcx).sty { + ty::TyFnDef(def_id, _) => { + if tcx.lang_items().items().iter().find(|l|**l == Some(def_id)).is_some() { + return instance; // Lang items dont work otherwise + } + } + _ => return instance, // Closures dont work otherwise + } + + let used_substs = used_substs_for_instance(tcx, instance); + instance.substs = tcx.intern_substs(&instance.substs.into_iter().enumerate().map(|(i, subst)| { + if let UnpackedKind::Type(ty) = subst.unpack() { + let ty = match used_substs.parameters[ParamIdx(i as u32)] { + ParamUsage::Unused => { + if false /*param.name.as_str().starts_with("<")*/ { + ty.into() + } else { + /*#[allow(unused_mut)] + let mut mir = Vec::new(); + ::util::write_mir_pretty(tcx, Some(instance.def_id()), &mut mir).unwrap(); + let mut generics = Some(tcx.generics_of(instance.def_id())); + let mut pretty_generics = String::new(); + loop { + if let Some(ref gen) = generics { + for ty in &gen.types { + pretty_generics.push_str(&format!( + "{}:{} at {:?}, ", + ty.index, + ty.name, + tcx.def_span(ty.def_id) + )); + } + } else { + break; + } + generics = generics.and_then(|gen|gen.parent) + .map(|def_id|tcx.generics_of(def_id)); + } + tcx.sess.warn(&format!( + "Unused subst {} for {:?}<{}>\n with mir: {}", + i, + instance, + pretty_generics, + String::from_utf8_lossy(&mir) + ));*/ + tcx.mk_ty(ty::TyNever) + } + } + ParamUsage::LayoutUsed => { + let layout_cx = LayoutCx { + tcx, + param_env: ParamEnv::reveal_all(), + }; + let layout = layout_cx.layout_of(ty).unwrap(); + let (size, align) = layout.size_and_align(); + tcx.mk_ty(TypeVariants::TyLayoutOnlyParam(size, align)) + } + ParamUsage::Used => ty.into(), + }; + Kind::from(ty) + } else { + (*subst).clone() + } + }).collect::>()); + info!("replace_unused_substs_with_ty_error(_) -> {:?}", instance); + instance +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +struct ParamIdx(u32); + +impl ::rustc_data_structures::indexed_vec::Idx for ParamIdx { + fn new(idx: usize) -> Self { + assert!(idx < ::std::u32::MAX as usize); + ParamIdx(idx as u32) + } + + fn index(self) -> usize { + self.0 as usize + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +enum ParamUsage { + Unused = 0, + #[allow(dead_code)] + LayoutUsed = 1, + Used = 2, +} + +impl_stable_hash_for! { enum self::ParamUsage { Unused, LayoutUsed, Used} } + +#[derive(Debug, Default, Clone)] +pub struct ParamsUsage { + parameters: IndexVec, +} + +impl_stable_hash_for! { struct ParamsUsage { parameters } } + +impl ParamsUsage { + fn new(len: usize) -> ParamsUsage { + ParamsUsage { + parameters: IndexVec::from_elem_n(ParamUsage::Unused, len), + } + } +} + +struct SubstsVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a>( + TyCtxt<'a, 'gcx, 'tcx>, + &'tcx Mir<'tcx>, + ParamsUsage, +); + +impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Visitor<'tcx> for SubstsVisitor<'a, 'gcx, 'tcx> { + fn visit_mir(&mut self, mir: &Mir<'tcx>) { + for promoted in &mir.promoted { + self.visit_mir(promoted); + } + self.super_mir(mir); + } + + fn visit_ty(&mut self, ty: &Ty<'tcx>, _: TyContext) { + self.fold_ty(ty); + } + + fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _location: Location) { + if let ConstVal::Unevaluated(_def_id, substs) = constant.val { + for subst in substs { + if let UnpackedKind::Type(ty) = subst.unpack() { + ty.fold_with(self); + } + } + } + } + + fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { + let tcx = self.0; + match *rvalue { + Rvalue::Cast(_kind, ref op, ty) => { + self.fold_ty(op.ty(&self.1.local_decls, tcx)); + self.fold_ty(ty); + } + _ => {} + } + self.super_rvalue(rvalue, location); + } +} + +impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> TypeFolder<'gcx, 'tcx> for SubstsVisitor<'a, 'gcx, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { + self.0 + } + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + if !ty.needs_subst() { + return ty; + } + match ty.sty { + ty::TyParam(param) => { + self.2.parameters[ParamIdx(param.idx)] = ParamUsage::Used; + } + _ => {} + } + ty.super_fold_with(self) + } +} + +fn used_substs_for_instance<'a, 'tcx: 'a>( + tcx: TyCtxt<'a ,'tcx, 'tcx>, + instance: Instance<'tcx>, +) -> ParamsUsage { + let mir = tcx.instance_mir(instance.def); + let generics = tcx.generics_of(instance.def_id()); + let sig = ::rustc::ty::ty_fn_sig(tcx, instance.ty(tcx)); + let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); + let mut substs_visitor = SubstsVisitor(tcx, mir, ParamsUsage::new(instance.substs.len())); + //substs_visitor.visit_mir(mir); + mir.fold_with(&mut substs_visitor); + for ty in sig.inputs().iter() { + ty.fold_with(&mut substs_visitor); + } + for ty_param_def in &generics.types { + if ParamTy::for_def(ty_param_def).is_self() { + // The self parameter is important for trait selection + (substs_visitor.2).parameters[ParamIdx(ty_param_def.index)] = ParamUsage::Used; + } + } + sig.output().fold_with(&mut substs_visitor); + substs_visitor.2 +} diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index c2f4359c0082b..889afc8d153a3 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -387,6 +387,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { ty::TyInfer(_) | ty::TyProjection(..) | ty::TyParam(_) | + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) | ty::TyGeneratorWitness(_) | ty::TyAnon(..) => { bug!("DefPathBasedNames: Trying to create type name for \ diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs index 5c38735d92034..2ca0e52ea2f1d 100644 --- a/src/librustc_mir/monomorphize/mod.rs +++ b/src/librustc_mir/monomorphize/mod.rs @@ -21,6 +21,7 @@ pub use self::item::{MonoItem, MonoItemExt}; pub mod collector; pub mod item; pub mod partitioning; +pub mod deduplicate_instances; #[inline(never)] // give this a place in the profiler pub fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_items: I) diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 4509cace794d4..2165adedaa6cb 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -517,7 +517,11 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>( mir: &Mir, w: &mut dyn Write, ) -> io::Result<()> { - write_mir_sig(tcx, src, mir, w)?; + if tcx.hir.as_local_node_id(src.def_id).is_some() { + write_mir_sig(tcx, src, mir, w)?; + } else { + write!(w, "fn () ")?; + } writeln!(w, "{{")?; // construct a scope tree and write it out diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 1fe2f87128abd..80eedd7f4c2ec 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -238,6 +238,10 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>( // be fully resolved. Err(NoSolution) } + + ty::TyUnusedParam | ty::TyLayoutOnlyParam(..) => { + bug!("Unexpected {:?} in dtorck_constraint_for_ty", ty); + } }; debug!("dtorck_constraint_for_ty({:?}) = {:?}", ty, result); diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 19ae1fa0478ea..d0aa9cff84fc0 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -650,7 +650,7 @@ impl<'a, 'tcx> FnType<'tcx> { pub fn of_instance(cx: &CodegenCx<'a, 'tcx>, instance: &ty::Instance<'tcx>) -> Self { let fn_ty = instance.ty(cx.tcx); - let sig = ty_fn_sig(cx, fn_ty); + let sig = ty_fn_sig(cx.tcx, fn_ty); let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); FnType::new(cx, sig, &[]) } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 3ab33c4134697..320050b42860b 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -464,7 +464,7 @@ pub fn trans_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tc info!("trans_instance({})", instance); let fn_ty = instance.ty(cx.tcx); - let sig = common::ty_fn_sig(cx, fn_ty); + let sig = common::ty_fn_sig(cx.tcx, fn_ty); let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); let lldecl = match cx.instances.borrow().get(&instance) { diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 1dcf349e23bd8..b5654ba6fdb0a 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -43,6 +43,10 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, debug!("get_fn(instance={:?})", instance); + let instance = tcx.collapse_interchangable_instances(instance); + + info!("get_fn(collapsed_instance={:?})", instance); + assert!(!instance.substs.needs_infer()); assert!(!instance.substs.has_escaping_regions()); assert!(!instance.substs.has_param_types()); @@ -56,7 +60,7 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym); // Create a fn pointer with the substituted signature. - let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig(cx, fn_ty)); + let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig(cx.tcx, fn_ty)); let llptrty = cx.layout_of(fn_ptr_ty).llvm_type(cx); let llfn = if let Some(llfn) = declare::get_declared_value(cx, &sym) { diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index e83e73c8ae757..46946ace25dbd 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -30,13 +30,12 @@ use rustc::ty::layout::{HasDataLayout, LayoutOf}; use rustc::hir; use libc::{c_uint, c_char}; -use std::iter; -use syntax::abi::Abi; use syntax::symbol::InternedString; use syntax_pos::{Span, DUMMY_SP}; pub use context::CodegenCx; +pub use rustc::ty::ty_fn_sig; pub fn type_needs_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool { ty.needs_drop(tcx, ty::ParamEnv::reveal_all()) @@ -399,51 +398,3 @@ pub fn shift_mask_val<'a, 'tcx>( _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind), } } - -pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - ty: Ty<'tcx>) - -> ty::PolyFnSig<'tcx> -{ - match ty.sty { - ty::TyFnDef(..) | - // Shims currently have type TyFnPtr. Not sure this should remain. - ty::TyFnPtr(_) => ty.fn_sig(cx.tcx), - ty::TyClosure(def_id, substs) => { - let tcx = cx.tcx; - let sig = substs.closure_sig(def_id, tcx); - - let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); - sig.map_bound(|sig| tcx.mk_fn_sig( - iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), - sig.output(), - sig.variadic, - sig.unsafety, - sig.abi - )) - } - ty::TyGenerator(def_id, substs, _) => { - let tcx = cx.tcx; - let sig = substs.generator_poly_sig(def_id, cx.tcx); - - let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv); - let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); - - sig.map_bound(|sig| { - let state_did = tcx.lang_items().gen_state().unwrap(); - let state_adt_ref = tcx.adt_def(state_did); - let state_substs = tcx.mk_substs([sig.yield_ty.into(), - sig.return_ty.into()].iter()); - let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); - - tcx.mk_fn_sig(iter::once(env_ty), - ret_ty, - false, - hir::Unsafety::Normal, - Abi::Rust - ) - }) - } - _ => bug!("unexpected type {:?} to ty_fn_sig", ty) - } -} - diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index f3d95cf794bab..897418c63f906 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -1567,6 +1567,8 @@ fn create_struct_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, unique_type_id: UniqueTypeId, containing_scope: DIScope) -> DICompositeType { + // FIXME: ignore unused generic subsitutions + //cx.tcx.sess.warn(&format!("create_struct_stub({:?})", struct_type)); let (struct_size, struct_align) = cx.size_and_align_of(struct_type); let name = CString::new(struct_type_name).unwrap(); diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 7664c88679e0e..eea84f6d25dea 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -30,7 +30,8 @@ use abi::Abi; use common::CodegenCx; use builder::Builder; use monomorphize::Instance; -use rustc::ty::{self, ParamEnv, Ty}; +use rustc::ty::{self, TyCtxt, ParamEnv, Ty, TypeFoldable}; +use rustc::ty::fold::TypeFolder; use rustc::mir; use rustc::session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet}; @@ -201,12 +202,30 @@ pub fn finalize(cx: &CodegenCx) { /// for debug info creation. The function may also return another variant of the /// FunctionDebugContext enum which indicates why no debuginfo should be created /// for the function. -pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, +pub fn create_function_debug_context<'a, 'tcx>(cx: &'a CodegenCx<'a, 'tcx>, instance: Instance<'tcx>, sig: ty::FnSig<'tcx>, llfn: ValueRef, - mir: &mir::Mir) -> FunctionDebugContext { - if cx.sess().opts.debuginfo == NoDebugInfo { + mir: &'a mir::Mir<'tcx>) -> FunctionDebugContext { + struct UnusedParamVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a>(TyCtxt<'a, 'gcx, 'tcx>, bool); + impl<'a, 'gcx: 'tcx, 'tcx: 'a> TypeFolder<'gcx, 'tcx> for UnusedParamVisitor<'a, 'gcx, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { + self.0 + } + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + match ty.sty { + ty::TyUnusedParam => { + self.1 = true; + } + _ => {} + } + ty.super_fold_with(self) + } + } + let mut has_unused_param_visitor = UnusedParamVisitor(cx.tcx, false); + mir.fold_with(&mut has_unused_param_visitor); + + if cx.sess().opts.debuginfo == NoDebugInfo || has_unused_param_visitor.1 { return FunctionDebugContext::DebugInfoDisabled; } diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 96ed4e8847115..3bc6faf253628 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -171,6 +171,9 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ty::TyGenerator(..) => { output.push_str("generator"); } + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) => { + output.push_str("[unused type param]"); + } ty::TyError | ty::TyInfer(_) | ty::TyProjection(..) | diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs index c2010feb1b638..7c111ef513a64 100644 --- a/src/librustc_trans/declare.rs +++ b/src/librustc_trans/declare.rs @@ -126,7 +126,7 @@ pub fn declare_cfn(cx: &CodegenCx, name: &str, fn_type: Type) -> ValueRef { pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str, fn_type: Ty<'tcx>) -> ValueRef { debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, fn_type); - let sig = common::ty_fn_sig(cx, fn_type); + let sig = common::ty_fn_sig(cx.tcx, fn_type); let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); debug!("declare_rust_fn (after region erasure) sig={:?}", sig); diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 93bc89f0914f5..15fbf8fc69fe9 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -280,7 +280,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let (drop_fn, fn_ty) = match ty.sty { ty::TyDynamic(..) => { let fn_ty = drop_fn.ty(bx.cx.tcx); - let sig = common::ty_fn_sig(bx.cx, fn_ty); + let sig = common::ty_fn_sig(bx.cx.tcx, fn_ty); let sig = bx.tcx().normalize_erasing_late_bound_regions( ty::ParamEnv::reveal_all(), &sig, diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 06d94e8d15569..d39798ed4d4b2 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -69,6 +69,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { } } MonoItem::Fn(instance) => { + //cx.tcx.sess.warn(&format!("trans_instance({:?})", instance)); base::trans_instance(&cx, instance); } } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index e4bad8349ea2b..64f262ce7958b 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -137,6 +137,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span, &format!("`{:?}` should be sized but is not?", t)); return Err(ErrorReported); } + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) => { + bug!("Unexpected {:?} in FnCtxt::pointer_kind", t); + } }) } } diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index a24e501aba950..ae5429f50dcf0 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -334,6 +334,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // types, where we use TyError as the Self type } + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) | ty::TyGeneratorWitness(..) | ty::TyInfer(..) => { bug!("unexpected type encountered in \ diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3a79c14f4ec2a..a10f468c9ae23 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2836,6 +2836,7 @@ impl<'tcx> Clean for Ty<'tcx> { ty::TyClosure(..) | ty::TyGenerator(..) => Tuple(vec![]), // FIXME(pcwalton) + ty::TyUnusedParam | ty::TyLayoutOnlyParam(_, _) => panic!("TyUnusedParam"), ty::TyGeneratorWitness(..) => panic!("TyGeneratorWitness"), ty::TyInfer(..) => panic!("TyInfer"), ty::TyError => panic!("TyError"), diff --git a/src/test/codegen-units/item-collection/static-init.rs b/src/test/codegen-units/item-collection/static-init.rs index 5ff7c3480b126..87260d8b89f26 100644 --- a/src/test/codegen-units/item-collection/static-init.rs +++ b/src/test/codegen-units/item-collection/static-init.rs @@ -17,7 +17,7 @@ pub static FN : fn() = foo::; pub fn foo() { } -//~ TRANS_ITEM fn static_init::foo[0] +//~ TRANS_ITEM fn static_init::foo[0] //~ TRANS_ITEM static static_init::FN[0] //~ TRANS_ITEM fn static_init::start[0] diff --git a/src/test/run-make-fulldeps/libtest-json/Makefile b/src/test/run-make-fulldeps/libtest-json/Makefile index ec91ddfb9f917..9a216c4a9b7eb 100644 --- a/src/test/run-make-fulldeps/libtest-json/Makefile +++ b/src/test/run-make-fulldeps/libtest-json/Makefile @@ -6,7 +6,8 @@ OUTPUT_FILE := $(TMPDIR)/libtest-json-output.json all: $(RUSTC) --test f.rs - $(call RUN,f) -Z unstable-options --test-threads=1 --format=json > $(OUTPUT_FILE) || true + RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json \ + > $(OUTPUT_FILE) || true cat $(OUTPUT_FILE) | "$(PYTHON)" validate_json.py