Skip to content

Commit 149aa05

Browse files
committed
Move collapse_interchangable_instances to src/librustc_mir
1 parent bc81145 commit 149aa05

File tree

5 files changed

+116
-114
lines changed

5 files changed

+116
-114
lines changed

src/librustc/ty/instance.rs

Lines changed: 1 addition & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use rustc_data_structures::indexed_vec::IndexVec;
12-
1311
use hir::def_id::DefId;
14-
use ty::{self, TyCtxt, Ty, TypeFoldable, Substs, ParamTy};
12+
use ty::{self, TyCtxt, Ty, TypeFoldable, Substs};
1513
use ty::subst::Kind;
16-
use ty::fold::TypeFolder;
17-
use mir::visit::{Visitor, TyContext};
1814
use traits;
1915
use syntax::abi::Abi;
2016
use util::ppaux;
@@ -247,114 +243,6 @@ impl<'a, 'b, 'tcx> Instance<'tcx> {
247243
_ => Instance::new(def_id, substs.substs)
248244
}
249245
}
250-
251-
/// Replace substs which arent used by the function with TyError,
252-
/// so that it doesnt end up in the binary multiple times
253-
pub(in ty) fn _collapse_interchangable_instances(mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Instance<'tcx> {
254-
use ty::subst::Kind;
255-
info!("replace_unused_substs_with_ty_error({:?})", self);
256-
257-
if self.substs.is_noop() || !tcx.is_mir_available(self.def_id()) {
258-
return self;
259-
}
260-
match self.ty(tcx).sty {
261-
ty::TyFnDef(def_id, _) => {
262-
//let attrs = tcx.item_attrs(def_id);
263-
if tcx.lang_items().items().iter().find(|l|**l == Some(def_id)).is_some() {
264-
return self; // Lang items dont work otherwise
265-
}
266-
}
267-
_ => return self, // Closures dont work otherwise
268-
}
269-
270-
let used_substs = used_substs_for_instance(tcx, self);
271-
self.substs = tcx._intern_substs(&self.substs.into_iter().enumerate().map(|(i, subst)| {
272-
if let Some(ty) = subst.as_type() {
273-
let ty = if used_substs.substs.iter().find(|p|p.idx == i as u32).is_some() {
274-
ty.into()
275-
} else if let ty::TyParam(ref _param) = ty.sty { // Dont replace <closure_kind> and other internal params
276-
if false /*param.name.as_str().starts_with("<")*/ {
277-
ty.into()
278-
} else {
279-
tcx.mk_ty(ty::TyNever)
280-
}
281-
} else {
282-
tcx.mk_ty(ty::TyNever) // Can't use TyError as it gives some ICE in rustc_trans::callee::get_fn
283-
};
284-
Kind::from(ty)
285-
} else {
286-
(*subst).clone()
287-
}
288-
}).collect::<Vec<_>>());
289-
info!("replace_unused_substs_with_ty_error(_) -> {:?}", self);
290-
self
291-
}
292-
}
293-
294-
#[derive(Debug, Default, Clone)]
295-
pub struct UsedSubsts {
296-
pub substs: Vec<ParamTy>,
297-
pub promoted: IndexVec<::mir::Promoted, UsedSubsts>,
298-
}
299-
300-
impl_stable_hash_for! { struct UsedSubsts { substs, promoted } }
301-
302-
fn used_substs_for_instance<'a, 'tcx: 'a>(tcx: TyCtxt<'a ,'tcx, 'tcx>, instance: Instance<'tcx>) -> UsedSubsts {
303-
struct SubstsVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a>(TyCtxt<'a, 'gcx, 'tcx>, UsedSubsts);
304-
305-
impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Visitor<'tcx> for SubstsVisitor<'a, 'gcx, 'tcx> {
306-
fn visit_ty(&mut self, ty: &Ty<'tcx>, _: TyContext) {
307-
self.fold_ty(ty);
308-
}
309-
}
310-
311-
impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> TypeFolder<'gcx, 'tcx> for SubstsVisitor<'a, 'gcx, 'tcx> {
312-
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
313-
self.0
314-
}
315-
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
316-
if !ty.needs_subst() {
317-
return ty;
318-
}
319-
match ty.sty {
320-
ty::TyParam(param) => {
321-
self.1.substs.push(param);
322-
ty
323-
}
324-
ty::TyFnDef(_, substs) => {
325-
for subst in substs {
326-
if let Some(ty) = subst.as_type() {
327-
ty.fold_with(self);
328-
}
329-
}
330-
ty.super_fold_with(self)
331-
}
332-
ty::TyClosure(_, closure_substs) => {
333-
for subst in closure_substs.substs {
334-
if let Some(ty) = subst.as_type() {
335-
ty.fold_with(self);
336-
}
337-
}
338-
ty.super_fold_with(self)
339-
}
340-
_ => ty.super_fold_with(self)
341-
}
342-
}
343-
}
344-
345-
let mir = tcx.instance_mir(instance.def);
346-
let sig = ::ty::ty_fn_sig(tcx, instance.ty(tcx));
347-
let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
348-
let mut substs_visitor = SubstsVisitor(tcx, UsedSubsts::default());
349-
substs_visitor.visit_mir(mir);
350-
for ty in sig.inputs().iter() {
351-
ty.fold_with(&mut substs_visitor);
352-
}
353-
sig.output().fold_with(&mut substs_visitor);
354-
let mut used_substs = substs_visitor.1;
355-
used_substs.substs.sort_by_key(|s|s.idx);
356-
used_substs.substs.dedup_by_key(|s|s.idx);
357-
used_substs
358246
}
359247

360248
fn resolve_associated_item<'a, 'tcx>(

src/librustc/ty/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2761,7 +2761,6 @@ pub fn provide(providers: &mut ty::maps::Providers) {
27612761
crate_hash,
27622762
trait_impls_of: trait_def::trait_impls_of_provider,
27632763
instance_def_size_estimate,
2764-
collapse_interchangable_instances: |tcx, instance| instance._collapse_interchangable_instances(tcx),
27652764
..*providers
27662765
};
27672766
}

src/librustc_mir/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ pub fn provide(providers: &mut Providers) {
7474
transform::provide(providers);
7575
providers.const_eval = interpret::const_eval_provider;
7676
providers.check_match = hair::pattern::check_match;
77+
providers.collapse_interchangable_instances = monomorphize::deduplicate_instances::collapse_interchangable_instances;
7778
}
7879

7980
__build_diagnostic_array! { librustc_mir, DIAGNOSTICS }
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
use rustc_data_structures::indexed_vec::IndexVec;
2+
use rustc::ty::{self, TyCtxt, Ty, TypeFoldable, Instance, ParamTy};
3+
use rustc::ty::fold::TypeFolder;
4+
use rustc::ty::subst::Kind;
5+
use rustc::mir::Promoted;
6+
use rustc::mir::visit::{Visitor, TyContext};
7+
8+
/// Replace substs which arent used by the function with TyError,
9+
/// so that it doesnt end up in the binary multiple times
10+
pub(crate) fn collapse_interchangable_instances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mut inst: Instance<'tcx>) -> Instance<'tcx> {
11+
info!("replace_unused_substs_with_ty_error({:?})", inst);
12+
13+
if inst.substs.is_noop() || !tcx.is_mir_available(inst.def_id()) {
14+
return inst;
15+
}
16+
match inst.ty(tcx).sty {
17+
ty::TyFnDef(def_id, _) => {
18+
//let attrs = tcx.item_attrs(def_id);
19+
if tcx.lang_items().items().iter().find(|l|**l == Some(def_id)).is_some() {
20+
return inst; // Lang items dont work otherwise
21+
}
22+
}
23+
_ => return inst, // Closures dont work otherwise
24+
}
25+
26+
let used_substs = used_substs_for_instance(tcx, inst);
27+
inst.substs = tcx._intern_substs(&inst.substs.into_iter().enumerate().map(|(i, subst)| {
28+
if let Some(ty) = subst.as_type() {
29+
let ty = if used_substs.substs.iter().find(|p|p.idx == i as u32).is_some() {
30+
ty.into()
31+
} else if let ty::TyParam(ref _param) = ty.sty { // Dont replace <closure_kind> and other internal params
32+
if false /*param.name.as_str().starts_with("<")*/ {
33+
ty.into()
34+
} else {
35+
tcx.mk_ty(ty::TyNever)
36+
}
37+
} else {
38+
tcx.mk_ty(ty::TyNever) // Can't use TyError as it gives some ICE in rustc_trans::callee::get_fn
39+
};
40+
Kind::from(ty)
41+
} else {
42+
(*subst).clone()
43+
}
44+
}).collect::<Vec<_>>());
45+
info!("replace_unused_substs_with_ty_error(_) -> {:?}", inst);
46+
inst
47+
}
48+
49+
#[derive(Debug, Default, Clone)]
50+
pub struct UsedSubsts {
51+
pub substs: Vec<ParamTy>,
52+
pub promoted: IndexVec<Promoted, UsedSubsts>,
53+
}
54+
55+
impl_stable_hash_for! { struct UsedSubsts { substs, promoted } }
56+
57+
fn used_substs_for_instance<'a, 'tcx: 'a>(tcx: TyCtxt<'a ,'tcx, 'tcx>, instance: Instance<'tcx>) -> UsedSubsts {
58+
struct SubstsVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a>(TyCtxt<'a, 'gcx, 'tcx>, UsedSubsts);
59+
60+
impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> Visitor<'tcx> for SubstsVisitor<'a, 'gcx, 'tcx> {
61+
fn visit_ty(&mut self, ty: &Ty<'tcx>, _: TyContext) {
62+
self.fold_ty(ty);
63+
}
64+
}
65+
66+
impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> TypeFolder<'gcx, 'tcx> for SubstsVisitor<'a, 'gcx, 'tcx> {
67+
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
68+
self.0
69+
}
70+
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
71+
if !ty.needs_subst() {
72+
return ty;
73+
}
74+
match ty.sty {
75+
ty::TyParam(param) => {
76+
self.1.substs.push(param);
77+
ty
78+
}
79+
ty::TyFnDef(_, substs) => {
80+
for subst in substs {
81+
if let Some(ty) = subst.as_type() {
82+
ty.fold_with(self);
83+
}
84+
}
85+
ty.super_fold_with(self)
86+
}
87+
ty::TyClosure(_, closure_substs) => {
88+
for subst in closure_substs.substs {
89+
if let Some(ty) = subst.as_type() {
90+
ty.fold_with(self);
91+
}
92+
}
93+
ty.super_fold_with(self)
94+
}
95+
_ => ty.super_fold_with(self)
96+
}
97+
}
98+
}
99+
100+
let mir = tcx.instance_mir(instance.def);
101+
let sig = ::rustc::ty::ty_fn_sig(tcx, instance.ty(tcx));
102+
let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
103+
let mut substs_visitor = SubstsVisitor(tcx, UsedSubsts::default());
104+
substs_visitor.visit_mir(mir);
105+
for ty in sig.inputs().iter() {
106+
ty.fold_with(&mut substs_visitor);
107+
}
108+
sig.output().fold_with(&mut substs_visitor);
109+
let mut used_substs = substs_visitor.1;
110+
used_substs.substs.sort_by_key(|s|s.idx);
111+
used_substs.substs.dedup_by_key(|s|s.idx);
112+
used_substs
113+
}

src/librustc_mir/monomorphize/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub use self::item::{MonoItem, MonoItemExt};
2121
pub mod collector;
2222
pub mod item;
2323
pub mod partitioning;
24+
pub mod deduplicate_instances;
2425

2526
#[inline(never)] // give this a place in the profiler
2627
pub fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_items: I)

0 commit comments

Comments
 (0)