]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/instance.rs
Auto merge of #41258 - clarcharr:str_box_extras, r=Kimundi
[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::fmt;
17
18 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
19 pub struct Instance<'tcx> {
20     pub def: InstanceDef<'tcx>,
21     pub substs: &'tcx Substs<'tcx>,
22 }
23
24 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
25 pub enum InstanceDef<'tcx> {
26     Item(DefId),
27     Intrinsic(DefId),
28     // <fn() as FnTrait>::call_*
29     // def-id is FnTrait::call_*
30     FnPtrShim(DefId, Ty<'tcx>),
31     // <Trait as Trait>::fn
32     Virtual(DefId, usize),
33     // <[mut closure] as FnOnce>::call_once
34     ClosureOnceShim { call_once: DefId },
35     // drop_in_place::<T>; None for empty drop glue.
36     DropGlue(DefId, Option<Ty<'tcx>>),
37 }
38
39 impl<'tcx> InstanceDef<'tcx> {
40     #[inline]
41     pub fn def_id(&self) -> DefId {
42         match *self {
43             InstanceDef::Item(def_id) |
44             InstanceDef::FnPtrShim(def_id, _) |
45             InstanceDef::Virtual(def_id, _) |
46             InstanceDef::Intrinsic(def_id, ) |
47             InstanceDef::ClosureOnceShim { call_once: def_id }
48                 => def_id,
49             InstanceDef::DropGlue(def_id, _) => def_id
50         }
51     }
52
53     #[inline]
54     pub fn def_ty<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
55         tcx.item_type(self.def_id())
56     }
57
58     #[inline]
59     pub fn attrs<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> ty::Attributes<'tcx> {
60         tcx.get_attrs(self.def_id())
61     }
62
63     pub(crate) fn dep_node(&self) -> DepNode<DefId> {
64         // HACK: def-id binning, project-style; someone replace this with
65         // real on-demand.
66         let ty = match self {
67             &InstanceDef::FnPtrShim(_, ty) => Some(ty),
68             &InstanceDef::DropGlue(_, ty) => ty,
69             _ => None
70         }.into_iter();
71
72         DepNode::MirShim(
73             Some(self.def_id()).into_iter().chain(
74                 ty.flat_map(|t| t.walk()).flat_map(|t| match t.sty {
75                    ty::TyAdt(adt_def, _) => Some(adt_def.did),
76                    ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id),
77                    _ => None,
78                })
79             ).collect()
80         )
81     }
82 }
83
84 impl<'tcx> fmt::Display for Instance<'tcx> {
85     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86         ppaux::parameterized(f, self.substs, self.def_id(), &[])?;
87         match self.def {
88             InstanceDef::Item(_) => Ok(()),
89             InstanceDef::Intrinsic(_) => {
90                 write!(f, " - intrinsic")
91             }
92             InstanceDef::Virtual(_, num) => {
93                 write!(f, " - shim(#{})", num)
94             }
95             InstanceDef::FnPtrShim(_, ty) => {
96                 write!(f, " - shim({:?})", ty)
97             }
98             InstanceDef::ClosureOnceShim { .. } => {
99                 write!(f, " - shim")
100             }
101             InstanceDef::DropGlue(_, ty) => {
102                 write!(f, " - shim({:?})", ty)
103             }
104         }
105     }
106 }
107
108 impl<'a, 'b, 'tcx> Instance<'tcx> {
109     pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
110                -> Instance<'tcx> {
111         assert!(substs.is_normalized_for_trans() && !substs.has_escaping_regions(),
112                 "substs of instance {:?} not normalized for trans: {:?}",
113                 def_id, substs);
114         Instance { def: InstanceDef::Item(def_id), substs: substs }
115     }
116
117     pub fn mono(tcx: ty::TyCtxt<'a, 'tcx, 'b>, def_id: DefId) -> Instance<'tcx> {
118         Instance::new(def_id, tcx.global_tcx().empty_substs_for_def_id(def_id))
119     }
120
121     #[inline]
122     pub fn def_id(&self) -> DefId {
123         self.def.def_id()
124     }
125 }