1 //! This module contains the fcuntaiontliy to convert from the wacky tcx data
2 //! structures into the HAIR. The `builder` is generally ignorant of the tcx,
3 //! etc., and instead goes through the `Cx` for most of its work.
6 use crate::hair
::util
::UserAnnotatedTyHelpers
;
8 use rustc_data_structures
::indexed_vec
::Idx
;
9 use rustc
::hir
::def_id
::{DefId, LOCAL_CRATE}
;
11 use rustc
::middle
::region
;
12 use rustc
::infer
::InferCtxt
;
13 use rustc
::ty
::subst
::Subst
;
14 use rustc
::ty
::{self, Ty, TyCtxt}
;
15 use rustc
::ty
::subst
::{Kind, Substs}
;
16 use rustc
::ty
::layout
::VariantIdx
;
19 use syntax
::symbol
::Symbol
;
21 use rustc_data_structures
::sync
::Lrc
;
22 use crate::hair
::constant
::{lit_to_const, LitToConstError}
;
25 pub struct Cx
<'a
, 'gcx
: 'a
+ 'tcx
, 'tcx
: 'a
> {
26 tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
27 infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>,
29 pub root_lint_level
: ast
::NodeId
,
30 pub param_env
: ty
::ParamEnv
<'gcx
>,
32 /// Identity `Substs` for use with const-evaluation.
33 pub identity_substs
: &'gcx Substs
<'gcx
>,
35 pub region_scope_tree
: Lrc
<region
::ScopeTree
>,
36 pub tables
: &'a ty
::TypeckTables
<'gcx
>,
38 /// This is `Constness::Const` if we are compiling a `static`,
39 /// `const`, or the body of a `const fn`.
40 constness
: hir
::Constness
,
42 /// What kind of body is being compiled.
43 pub body_owner_kind
: hir
::BodyOwnerKind
,
45 /// Whether this constant/function needs overflow checks.
48 /// See field with the same name on `Mir`.
49 control_flow_destroyed
: Vec
<(Span
, String
)>,
52 impl<'a
, 'gcx
, 'tcx
> Cx
<'a
, 'gcx
, 'tcx
> {
53 pub fn new(infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>,
54 src_id
: ast
::NodeId
) -> Cx
<'a
, 'gcx
, 'tcx
> {
56 let src_def_id
= tcx
.hir().local_def_id(src_id
);
57 let body_owner_kind
= tcx
.hir().body_owner_kind(src_id
);
59 let constness
= match body_owner_kind
{
60 hir
::BodyOwnerKind
::Const
|
61 hir
::BodyOwnerKind
::Static(_
) => hir
::Constness
::Const
,
62 hir
::BodyOwnerKind
::Closure
|
63 hir
::BodyOwnerKind
::Fn
=> hir
::Constness
::NotConst
,
66 let attrs
= tcx
.hir().attrs(src_id
);
68 // Some functions always have overflow checks enabled,
69 // however, they may not get codegen'd, depending on
70 // the settings for the crate they are codegened in.
71 let mut check_overflow
= attr
::contains_name(attrs
, "rustc_inherit_overflow_checks");
73 // Respect -C overflow-checks.
74 check_overflow
|= tcx
.sess
.overflow_checks();
76 // Constants always need overflow checks.
77 check_overflow
|= constness
== hir
::Constness
::Const
;
79 let lint_level
= lint_level_for_hir_id(tcx
, src_id
);
83 root_lint_level
: lint_level
,
84 param_env
: tcx
.param_env(src_def_id
),
85 identity_substs
: Substs
::identity_for_item(tcx
.global_tcx(), src_def_id
),
86 region_scope_tree
: tcx
.region_scope_tree(src_def_id
),
87 tables
: tcx
.typeck_tables_of(src_def_id
),
91 control_flow_destroyed
: Vec
::new(),
95 pub fn control_flow_destroyed(self) -> Vec
<(Span
, String
)> {
96 self.control_flow_destroyed
100 impl<'a
, 'gcx
, 'tcx
> Cx
<'a
, 'gcx
, 'tcx
> {
101 /// Normalizes `ast` into the appropriate "mirror" type.
102 pub fn mirror
<M
: Mirror
<'tcx
>>(&mut self, ast
: M
) -> M
::Output
{
103 ast
.make_mirror(self)
106 pub fn usize_ty(&mut self) -> Ty
<'tcx
> {
110 pub fn usize_literal(&mut self, value
: u64) -> &'tcx ty
::LazyConst
<'tcx
> {
111 self.tcx
.mk_lazy_const(ty
::LazyConst
::Evaluated(ty
::Const
::from_usize(self.tcx
, value
)))
114 pub fn bool_ty(&mut self) -> Ty
<'tcx
> {
118 pub fn unit_ty(&mut self) -> Ty
<'tcx
> {
122 pub fn true_literal(&mut self) -> &'tcx ty
::LazyConst
<'tcx
> {
123 self.tcx
.mk_lazy_const(ty
::LazyConst
::Evaluated(ty
::Const
::from_bool(self.tcx
, true)))
126 pub fn false_literal(&mut self) -> &'tcx ty
::LazyConst
<'tcx
> {
127 self.tcx
.mk_lazy_const(ty
::LazyConst
::Evaluated(ty
::Const
::from_bool(self.tcx
, false)))
130 pub fn const_eval_literal(
132 lit
: &'tcx ast
::LitKind
,
136 ) -> ty
::Const
<'tcx
> {
137 trace
!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit
, ty
, sp
, neg
);
139 match lit_to_const(lit
, self.tcx
, ty
, neg
) {
141 Err(LitToConstError
::UnparseableFloat
) => {
142 // FIXME(#31407) this is only necessary because float parsing is buggy
143 self.tcx
.sess
.span_err(sp
, "could not evaluate float literal (see issue #31407)");
144 // create a dummy value and continue compiling
145 Const
::from_bits(self.tcx
, 0, self.param_env
.and(ty
))
147 Err(LitToConstError
::Reported
) => {
148 // create a dummy value and continue compiling
149 Const
::from_bits(self.tcx
, 0, self.param_env
.and(ty
))
154 pub fn pattern_from_hir(&mut self, p
: &hir
::Pat
) -> Pattern
<'tcx
> {
155 let tcx
= self.tcx
.global_tcx();
156 let p
= match tcx
.hir().get(p
.id
) {
157 Node
::Pat(p
) | Node
::Binding(p
) => p
,
158 node
=> bug
!("pattern became {:?}", node
)
160 Pattern
::from_hir(tcx
,
161 self.param_env
.and(self.identity_substs
),
166 pub fn trait_method(&mut self,
170 params
: &[Kind
<'tcx
>])
171 -> (Ty
<'tcx
>, ty
::Const
<'tcx
>) {
172 let method_name
= Symbol
::intern(method_name
);
173 let substs
= self.tcx
.mk_substs_trait(self_ty
, params
);
174 for item
in self.tcx
.associated_items(trait_def_id
) {
175 if item
.kind
== ty
::AssociatedKind
::Method
&& item
.ident
.name
== method_name
{
176 let method_ty
= self.tcx
.type_of(item
.def_id
);
177 let method_ty
= method_ty
.subst(self.tcx
, substs
);
178 return (method_ty
, ty
::Const
::zero_sized(method_ty
));
182 bug
!("found no method `{}` in `{:?}`", method_name
, trait_def_id
);
185 pub fn all_fields(&mut self, adt_def
: &ty
::AdtDef
, variant_index
: VariantIdx
) -> Vec
<Field
> {
186 (0..adt_def
.variants
[variant_index
].fields
.len())
191 pub fn needs_drop(&mut self, ty
: Ty
<'tcx
>) -> bool
{
192 let (ty
, param_env
) = self.tcx
.lift_to_global(&(ty
, self.param_env
)).unwrap_or_else(|| {
193 bug
!("MIR: Cx::needs_drop({:?}, {:?}) got \
194 type with inference types/regions",
197 ty
.needs_drop(self.tcx
.global_tcx(), param_env
)
200 fn lint_level_of(&self, node_id
: ast
::NodeId
) -> LintLevel
{
201 let hir_id
= self.tcx
.hir().definitions().node_to_hir_id(node_id
);
202 let has_lint_level
= self.tcx
.dep_graph
.with_ignore(|| {
203 self.tcx
.lint_levels(LOCAL_CRATE
).lint_level_set(hir_id
).is_some()
207 LintLevel
::Explicit(node_id
)
213 pub fn tcx(&self) -> TyCtxt
<'a
, 'gcx
, 'tcx
> {
217 pub fn tables(&self) -> &'a ty
::TypeckTables
<'gcx
> {
221 pub fn check_overflow(&self) -> bool
{
225 pub fn type_is_copy_modulo_regions(&self, ty
: Ty
<'tcx
>, span
: Span
) -> bool
{
226 self.infcx
.type_is_copy_modulo_regions(self.param_env
, ty
, span
)
230 impl UserAnnotatedTyHelpers
<'gcx
, 'tcx
> for Cx
<'_
, 'gcx
, 'tcx
> {
231 fn tcx(&self) -> TyCtxt
<'_
, 'gcx
, 'tcx
> {
235 fn tables(&self) -> &ty
::TypeckTables
<'tcx
> {
240 fn lint_level_for_hir_id(tcx
: TyCtxt
<'_
, '_
, '_
>, mut id
: ast
::NodeId
) -> ast
::NodeId
{
241 // Right now we insert a `with_ignore` node in the dep graph here to
242 // ignore the fact that `lint_levels` below depends on the entire crate.
243 // For now this'll prevent false positives of recompiling too much when
246 // Once red/green incremental compilation lands we should be able to
247 // remove this because while the crate changes often the lint level map
248 // will change rarely.
249 tcx
.dep_graph
.with_ignore(|| {
250 let sets
= tcx
.lint_levels(LOCAL_CRATE
);
252 let hir_id
= tcx
.hir().definitions().node_to_hir_id(id
);
253 if sets
.lint_level_set(hir_id
).is_some() {
256 let next
= tcx
.hir().get_parent_node(id
);
258 bug
!("lint traversal reached the root of the crate");