1 //! This module contains the functionality to convert from the wacky tcx data
2 //! structures into the THIR. The `builder` is generally ignorant of the tcx,
3 //! etc., and instead goes through the `Cx` for most of its work.
5 use crate::thir
::util
::UserAnnotatedTyHelpers
;
10 use rustc_hir
::def_id
::{DefId, LocalDefId}
;
12 use rustc_index
::vec
::Idx
;
13 use rustc_infer
::infer
::InferCtxt
;
14 use rustc_middle
::middle
::region
;
15 use rustc_middle
::mir
::interpret
::{LitToConstError, LitToConstInput}
;
16 use rustc_middle
::ty
::subst
::Subst
;
17 use rustc_middle
::ty
::subst
::{GenericArg, InternalSubsts}
;
18 use rustc_middle
::ty
::{self, Ty, TyCtxt}
;
19 use rustc_span
::symbol
::{sym, Symbol}
;
20 use rustc_target
::abi
::VariantIdx
;
21 use rustc_trait_selection
::infer
::InferCtxtExt
;
24 crate struct Cx
<'a
, 'tcx
> {
26 infcx
: &'a InferCtxt
<'a
, 'tcx
>,
28 crate root_lint_level
: hir
::HirId
,
29 crate param_env
: ty
::ParamEnv
<'tcx
>,
31 /// Identity `InternalSubsts` for use with const-evaluation.
32 crate identity_substs
: &'tcx InternalSubsts
<'tcx
>,
34 crate region_scope_tree
: &'tcx region
::ScopeTree
,
35 crate typeck_results
: &'a ty
::TypeckResults
<'tcx
>,
37 /// This is `Constness::Const` if we are compiling a `static`,
38 /// `const`, or the body of a `const fn`.
39 constness
: hir
::Constness
,
41 /// The `DefId` of the owner of this body.
44 /// What kind of body is being compiled.
45 crate body_owner_kind
: hir
::BodyOwnerKind
,
47 /// Whether this constant/function needs overflow checks.
51 impl<'a
, 'tcx
> Cx
<'a
, 'tcx
> {
53 infcx
: &'a InferCtxt
<'a
, 'tcx
>,
54 def
: ty
::WithOptConstParam
<LocalDefId
>,
58 let typeck_results
= tcx
.typeck_opt_const_arg(def
);
59 let body_owner_kind
= tcx
.hir().body_owner_kind(src_id
);
61 let constness
= match body_owner_kind
{
62 hir
::BodyOwnerKind
::Const
| hir
::BodyOwnerKind
::Static(_
) => hir
::Constness
::Const
,
63 hir
::BodyOwnerKind
::Closure
| 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
= tcx
.sess
.contains_name(attrs
, sym
::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
;
82 root_lint_level
: src_id
,
83 param_env
: tcx
.param_env(def
.did
),
84 identity_substs
: InternalSubsts
::identity_for_item(tcx
, def
.did
.to_def_id()),
85 region_scope_tree
: tcx
.region_scope_tree(def
.did
),
88 body_owner
: def
.did
.to_def_id(),
95 impl<'a
, 'tcx
> Cx
<'a
, 'tcx
> {
96 /// Normalizes `ast` into the appropriate "mirror" type.
97 crate fn mirror
<M
: Mirror
<'tcx
>>(&mut self, ast
: M
) -> M
::Output
{
101 crate fn usize_ty(&mut self) -> Ty
<'tcx
> {
105 crate fn usize_literal(&mut self, value
: u64) -> &'tcx ty
::Const
<'tcx
> {
106 ty
::Const
::from_usize(self.tcx
, value
)
109 crate fn bool_ty(&mut self) -> Ty
<'tcx
> {
113 crate fn unit_ty(&mut self) -> Ty
<'tcx
> {
117 crate fn true_literal(&mut self) -> &'tcx ty
::Const
<'tcx
> {
118 ty
::Const
::from_bool(self.tcx
, true)
121 crate fn false_literal(&mut self) -> &'tcx ty
::Const
<'tcx
> {
122 ty
::Const
::from_bool(self.tcx
, false)
125 crate fn const_eval_literal(
127 lit
: &'tcx ast
::LitKind
,
131 ) -> &'tcx ty
::Const
<'tcx
> {
132 trace
!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit
, ty
, sp
, neg
);
134 match self.tcx
.at(sp
).lit_to_const(LitToConstInput { lit, ty, neg }
) {
136 Err(LitToConstError
::UnparseableFloat
) => {
137 // FIXME(#31407) this is only necessary because float parsing is buggy
138 self.tcx
.sess
.span_err(sp
, "could not evaluate float literal (see issue #31407)");
139 // create a dummy value and continue compiling
140 Const
::from_bits(self.tcx
, 0, self.param_env
.and(ty
))
142 Err(LitToConstError
::Reported
) => {
143 // create a dummy value and continue compiling
144 Const
::from_bits(self.tcx
, 0, self.param_env
.and(ty
))
146 Err(LitToConstError
::TypeError
) => bug
!("const_eval_literal: had type error"),
150 crate fn pattern_from_hir(&mut self, p
: &hir
::Pat
<'_
>) -> Pat
<'tcx
> {
151 let p
= match self.tcx
.hir().get(p
.hir_id
) {
152 Node
::Pat(p
) | Node
::Binding(p
) => p
,
153 node
=> bug
!("pattern became {:?}", node
),
155 Pat
::from_hir(self.tcx
, self.param_env
, self.typeck_results(), p
)
158 crate fn trait_method(
163 params
: &[GenericArg
<'tcx
>],
164 ) -> &'tcx ty
::Const
<'tcx
> {
165 let substs
= self.tcx
.mk_substs_trait(self_ty
, params
);
167 // The unhygienic comparison here is acceptable because this is only
168 // used on known traits.
171 .associated_items(trait_def_id
)
172 .filter_by_name_unhygienic(method_name
)
173 .find(|item
| item
.kind
== ty
::AssocKind
::Fn
)
174 .expect("trait method not found");
176 let method_ty
= self.tcx
.type_of(item
.def_id
);
177 let method_ty
= method_ty
.subst(self.tcx
, substs
);
178 ty
::Const
::zero_sized(self.tcx
, method_ty
)
181 crate fn all_fields(&mut self, adt_def
: &ty
::AdtDef
, variant_index
: VariantIdx
) -> Vec
<Field
> {
182 (0..adt_def
.variants
[variant_index
].fields
.len()).map(Field
::new
).collect()
185 crate fn needs_drop(&mut self, ty
: Ty
<'tcx
>) -> bool
{
186 ty
.needs_drop(self.tcx
, self.param_env
)
189 crate fn tcx(&self) -> TyCtxt
<'tcx
> {
193 crate fn typeck_results(&self) -> &'a ty
::TypeckResults
<'tcx
> {
197 crate fn check_overflow(&self) -> bool
{
201 crate fn type_is_copy_modulo_regions(&self, ty
: Ty
<'tcx
>, span
: Span
) -> bool
{
202 self.infcx
.type_is_copy_modulo_regions(self.param_env
, ty
, span
)
206 impl<'tcx
> UserAnnotatedTyHelpers
<'tcx
> for Cx
<'_
, 'tcx
> {
207 fn tcx(&self) -> TyCtxt
<'tcx
> {
211 fn typeck_results(&self) -> &ty
::TypeckResults
<'tcx
> {
212 self.typeck_results()