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.
5 use crate::hair
::util
::UserAnnotatedTyHelpers
;
11 use rustc_hir
::def_id
::DefId
;
13 use rustc_index
::vec
::Idx
;
14 use rustc_infer
::infer
::InferCtxt
;
15 use rustc_middle
::middle
::region
;
16 use rustc_middle
::mir
::interpret
::{LitToConstError, LitToConstInput}
;
17 use rustc_middle
::ty
::subst
::Subst
;
18 use rustc_middle
::ty
::subst
::{GenericArg, InternalSubsts}
;
19 use rustc_middle
::ty
::{self, Ty, TyCtxt}
;
20 use rustc_span
::symbol
::{sym, Symbol}
;
21 use rustc_target
::abi
::VariantIdx
;
22 use rustc_trait_selection
::infer
::InferCtxtExt
;
25 crate struct Cx
<'a
, 'tcx
> {
27 infcx
: &'a InferCtxt
<'a
, 'tcx
>,
29 crate root_lint_level
: hir
::HirId
,
30 crate param_env
: ty
::ParamEnv
<'tcx
>,
32 /// Identity `InternalSubsts` for use with const-evaluation.
33 crate identity_substs
: &'tcx InternalSubsts
<'tcx
>,
35 crate region_scope_tree
: &'tcx region
::ScopeTree
,
36 crate tables
: &'a ty
::TypeckTables
<'tcx
>,
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 /// The `DefId` of the owner of this body.
45 /// What kind of body is being compiled.
46 crate body_owner_kind
: hir
::BodyOwnerKind
,
48 /// Whether this constant/function needs overflow checks.
51 /// See field with the same name on `mir::Body`.
52 control_flow_destroyed
: Vec
<(Span
, String
)>,
55 impl<'a
, 'tcx
> Cx
<'a
, 'tcx
> {
56 crate fn new(infcx
: &'a InferCtxt
<'a
, 'tcx
>, src_id
: hir
::HirId
) -> Cx
<'a
, 'tcx
> {
58 let src_def_id
= tcx
.hir().local_def_id(src_id
);
59 let tables
= tcx
.typeck_tables_of(src_def_id
);
60 let body_owner_kind
= tcx
.hir().body_owner_kind(src_id
);
62 let constness
= match body_owner_kind
{
63 hir
::BodyOwnerKind
::Const
| hir
::BodyOwnerKind
::Static(_
) => hir
::Constness
::Const
,
64 hir
::BodyOwnerKind
::Closure
| hir
::BodyOwnerKind
::Fn
=> hir
::Constness
::NotConst
,
67 let attrs
= tcx
.hir().attrs(src_id
);
69 // Some functions always have overflow checks enabled,
70 // however, they may not get codegen'd, depending on
71 // the settings for the crate they are codegened in.
72 let mut check_overflow
= attr
::contains_name(attrs
, sym
::rustc_inherit_overflow_checks
);
74 // Respect -C overflow-checks.
75 check_overflow
|= tcx
.sess
.overflow_checks();
77 // Constants always need overflow checks.
78 check_overflow
|= constness
== hir
::Constness
::Const
;
83 root_lint_level
: src_id
,
84 param_env
: tcx
.param_env(src_def_id
),
85 identity_substs
: InternalSubsts
::identity_for_item(tcx
, src_def_id
.to_def_id()),
86 region_scope_tree
: tcx
.region_scope_tree(src_def_id
),
89 body_owner
: src_def_id
.to_def_id(),
92 control_flow_destroyed
: Vec
::new(),
96 crate fn control_flow_destroyed(self) -> Vec
<(Span
, String
)> {
97 self.control_flow_destroyed
101 impl<'a
, 'tcx
> Cx
<'a
, 'tcx
> {
102 /// Normalizes `ast` into the appropriate "mirror" type.
103 crate fn mirror
<M
: Mirror
<'tcx
>>(&mut self, ast
: M
) -> M
::Output
{
104 ast
.make_mirror(self)
107 crate fn usize_ty(&mut self) -> Ty
<'tcx
> {
111 crate fn usize_literal(&mut self, value
: u64) -> &'tcx ty
::Const
<'tcx
> {
112 ty
::Const
::from_usize(self.tcx
, value
)
115 crate fn bool_ty(&mut self) -> Ty
<'tcx
> {
119 crate fn unit_ty(&mut self) -> Ty
<'tcx
> {
123 crate fn true_literal(&mut self) -> &'tcx ty
::Const
<'tcx
> {
124 ty
::Const
::from_bool(self.tcx
, true)
127 crate fn false_literal(&mut self) -> &'tcx ty
::Const
<'tcx
> {
128 ty
::Const
::from_bool(self.tcx
, false)
131 crate fn const_eval_literal(
133 lit
: &'tcx ast
::LitKind
,
137 ) -> &'tcx ty
::Const
<'tcx
> {
138 trace
!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit
, ty
, sp
, neg
);
140 match self.tcx
.at(sp
).lit_to_const(LitToConstInput { lit, ty, neg }
) {
142 Err(LitToConstError
::UnparseableFloat
) => {
143 // FIXME(#31407) this is only necessary because float parsing is buggy
144 self.tcx
.sess
.span_err(sp
, "could not evaluate float literal (see issue #31407)");
145 // create a dummy value and continue compiling
146 Const
::from_bits(self.tcx
, 0, self.param_env
.and(ty
))
148 Err(LitToConstError
::Reported
) => {
149 // create a dummy value and continue compiling
150 Const
::from_bits(self.tcx
, 0, self.param_env
.and(ty
))
152 Err(LitToConstError
::TypeError
) => bug
!("const_eval_literal: had type error"),
156 crate fn pattern_from_hir(&mut self, p
: &hir
::Pat
<'_
>) -> Pat
<'tcx
> {
157 let p
= match self.tcx
.hir().get(p
.hir_id
) {
158 Node
::Pat(p
) | Node
::Binding(p
) => p
,
159 node
=> bug
!("pattern became {:?}", node
),
161 Pat
::from_hir(self.tcx
, self.param_env
, self.tables(), p
)
164 crate fn trait_method(
169 params
: &[GenericArg
<'tcx
>],
170 ) -> &'tcx ty
::Const
<'tcx
> {
171 let substs
= self.tcx
.mk_substs_trait(self_ty
, params
);
173 // The unhygienic comparison here is acceptable because this is only
174 // used on known traits.
177 .associated_items(trait_def_id
)
178 .filter_by_name_unhygienic(method_name
)
179 .find(|item
| item
.kind
== ty
::AssocKind
::Fn
)
180 .expect("trait method not found");
182 let method_ty
= self.tcx
.type_of(item
.def_id
);
183 let method_ty
= method_ty
.subst(self.tcx
, substs
);
184 ty
::Const
::zero_sized(self.tcx
, method_ty
)
187 crate fn all_fields(&mut self, adt_def
: &ty
::AdtDef
, variant_index
: VariantIdx
) -> Vec
<Field
> {
188 (0..adt_def
.variants
[variant_index
].fields
.len()).map(Field
::new
).collect()
191 crate fn needs_drop(&mut self, ty
: Ty
<'tcx
>) -> bool
{
192 ty
.needs_drop(self.tcx
, self.param_env
)
195 crate fn tcx(&self) -> TyCtxt
<'tcx
> {
199 crate fn tables(&self) -> &'a ty
::TypeckTables
<'tcx
> {
203 crate fn check_overflow(&self) -> bool
{
207 crate fn type_is_copy_modulo_regions(&self, ty
: Ty
<'tcx
>, span
: Span
) -> bool
{
208 self.infcx
.type_is_copy_modulo_regions(self.param_env
, ty
, span
)
212 impl<'tcx
> UserAnnotatedTyHelpers
<'tcx
> for Cx
<'_
, 'tcx
> {
213 fn tcx(&self) -> TyCtxt
<'tcx
> {
217 fn tables(&self) -> &ty
::TypeckTables
<'tcx
> {