]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/instance.rs
move Instance to rustc and use it in the collector
[rust.git] / src / librustc / ty / instance.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use dep_graph::DepNode;
12 use hir::def_id::DefId;
13 use ty::{self, Ty, TypeFoldable, Substs};
14 use util::ppaux;
15
16 use std::borrow::Cow;
17 use std::fmt;
18 use syntax::ast;
19
20
21 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
22 pub struct Instance<'tcx> {
23     pub def: InstanceDef<'tcx>,
24     pub substs: &'tcx Substs<'tcx>,
25 }
26
27 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
28 pub enum InstanceDef<'tcx> {
29     Item(DefId),
30     // <fn() as FnTrait>::call_*
31     FnPtrShim(DefId, Ty<'tcx>),
32 }
33
34 impl<'tcx> InstanceDef<'tcx> {
35     #[inline]
36     pub fn def_id(&self) -> DefId {
37         match *self {
38             InstanceDef::Item(def_id) |
39             InstanceDef::FnPtrShim(def_id, _)
40                 => def_id
41         }
42     }
43
44     #[inline]
45     pub fn def_ty<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
46         tcx.item_type(self.def_id())
47     }
48
49     #[inline]
50     pub fn attrs<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> Cow<'tcx, [ast::Attribute]> {
51         tcx.get_attrs(self.def_id())
52     }
53
54     pub(crate) fn dep_node(&self) -> DepNode<DefId> {
55         // HACK: def-id binning, project-style; someone replace this with
56         // real on-demand.
57         let ty = match self {
58             &InstanceDef::FnPtrShim(_, ty) => Some(ty),
59             _ => None
60         }.into_iter();
61
62         DepNode::MirShim(
63             Some(self.def_id()).into_iter().chain(
64                 ty.flat_map(|t| t.walk()).flat_map(|t| match t.sty {
65                    ty::TyAdt(adt_def, _) => Some(adt_def.did),
66                    ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id),
67                    _ => None,
68                })
69             ).collect()
70         )
71     }
72 }
73
74 impl<'tcx> fmt::Display for Instance<'tcx> {
75     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76         match self.def {
77             InstanceDef::Item(def) => {
78                 ppaux::parameterized(f, self.substs, def, &[])
79             }
80             InstanceDef::FnPtrShim(def, ty) => {
81                 ppaux::parameterized(f, self.substs, def, &[])?;
82                 write!(f, " - shim({:?})", ty)
83             }
84         }
85     }
86 }
87
88 impl<'a, 'b, 'tcx> Instance<'tcx> {
89     pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
90                -> Instance<'tcx> {
91         assert!(substs.is_normalized_for_trans() && !substs.has_escaping_regions(),
92                 "substs of instance {:?} not normalized for trans: {:?}",
93                 def_id, substs);
94         Instance { def: InstanceDef::Item(def_id), substs: substs }
95     }
96
97     pub fn mono(tcx: ty::TyCtxt<'a, 'tcx, 'b>, def_id: DefId) -> Instance<'tcx> {
98         Instance::new(def_id, tcx.global_tcx().empty_substs_for_def_id(def_id))
99     }
100
101     #[inline]
102     pub fn def_id(&self) -> DefId {
103         self.def.def_id()
104     }
105 }