]>
Commit | Line | Data |
---|---|---|
3dfed10e XL |
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, | |
9fa01778 | 3 | //! etc., and instead goes through the `Cx` for most of its work. |
b039eaaf | 4 | |
17df50a5 | 5 | use crate::thir::pattern::pat_from_hir; |
3dfed10e | 6 | use crate::thir::util::UserAnnotatedTyHelpers; |
b039eaaf | 7 | |
17df50a5 | 8 | use rustc_data_structures::steal::Steal; |
5e7ed085 | 9 | use rustc_errors::ErrorGuaranteed; |
dfeec247 | 10 | use rustc_hir as hir; |
f2b60f7d | 11 | use rustc_hir::def::DefKind; |
3dfed10e | 12 | use rustc_hir::def_id::{DefId, LocalDefId}; |
f2b60f7d | 13 | use rustc_hir::lang_items::LangItem; |
c295e0f8 | 14 | use rustc_hir::HirId; |
dfeec247 | 15 | use rustc_hir::Node; |
ba9703b0 | 16 | use rustc_middle::middle::region; |
17df50a5 | 17 | use rustc_middle::thir::*; |
2b03887a | 18 | use rustc_middle::ty::{self, RvalueScopes, TyCtxt}; |
17df50a5 | 19 | use rustc_span::Span; |
e9174d1e | 20 | |
9c376795 FG |
21 | pub(crate) fn thir_body( |
22 | tcx: TyCtxt<'_>, | |
6a06907d | 23 | owner_def: ty::WithOptConstParam<LocalDefId>, |
9c376795 | 24 | ) -> Result<(&Steal<Thir<'_>>, ExprId), ErrorGuaranteed> { |
17df50a5 | 25 | let hir = tcx.hir(); |
064997fb | 26 | let body = hir.body(hir.body_owned_by(owner_def.did)); |
17df50a5 | 27 | let mut cx = Cx::new(tcx, owner_def); |
5e7ed085 FG |
28 | if let Some(reported) = cx.typeck_results.tainted_by_errors { |
29 | return Err(reported); | |
17df50a5 XL |
30 | } |
31 | let expr = cx.mirror_expr(&body.value); | |
f2b60f7d FG |
32 | |
33 | let owner_id = hir.local_def_id_to_hir_id(owner_def.did); | |
34 | if let Some(ref fn_decl) = hir.fn_decl_by_hir_id(owner_id) { | |
35 | let closure_env_param = cx.closure_env_param(owner_def.did, owner_id); | |
36 | let explicit_params = cx.explicit_params(owner_id, fn_decl, body); | |
37 | cx.thir.params = closure_env_param.into_iter().chain(explicit_params).collect(); | |
38 | ||
39 | // The resume argument may be missing, in that case we need to provide it here. | |
40 | // It will always be `()` in this case. | |
41 | if tcx.def_kind(owner_def.did) == DefKind::Generator && body.params.is_empty() { | |
42 | cx.thir.params.push(Param { | |
43 | ty: tcx.mk_unit(), | |
44 | pat: None, | |
45 | ty_span: None, | |
46 | self_kind: None, | |
47 | hir_id: None, | |
48 | }); | |
49 | } | |
50 | } | |
51 | ||
5e7ed085 | 52 | Ok((tcx.alloc_steal_thir(cx.thir), expr)) |
6a06907d | 53 | } |
3b2f2976 | 54 | |
9c376795 | 55 | pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalDefId>) -> String { |
5e7ed085 FG |
56 | match thir_body(tcx, owner_def) { |
57 | Ok((thir, _)) => format!("{:#?}", thir.steal()), | |
58 | Err(_) => "error".into(), | |
59 | } | |
94222f64 XL |
60 | } |
61 | ||
17df50a5 | 62 | struct Cx<'tcx> { |
6a06907d | 63 | tcx: TyCtxt<'tcx>, |
17df50a5 | 64 | thir: Thir<'tcx>, |
3b2f2976 | 65 | |
f2b60f7d | 66 | param_env: ty::ParamEnv<'tcx>, |
3b2f2976 | 67 | |
f2b60f7d FG |
68 | region_scope_tree: &'tcx region::ScopeTree, |
69 | typeck_results: &'tcx ty::TypeckResults<'tcx>, | |
70 | rvalue_scopes: &'tcx RvalueScopes, | |
3157f602 | 71 | |
c295e0f8 XL |
72 | /// When applying adjustments to the expression |
73 | /// with the given `HirId`, use the given `Span`, | |
74 | /// instead of the usual span. This is used to | |
75 | /// assign the span of an overall method call | |
76 | /// (e.g. `my_val.foo()`) to the adjustment expressions | |
77 | /// for the receiver. | |
78 | adjustment_span: Option<(HirId, Span)>, | |
79 | ||
487cf647 FG |
80 | /// False to indicate that adjustments should not be applied. Only used for `custom_mir` |
81 | apply_adjustments: bool, | |
82 | ||
dc9dc135 XL |
83 | /// The `DefId` of the owner of this body. |
84 | body_owner: DefId, | |
e9174d1e SL |
85 | } |
86 | ||
17df50a5 XL |
87 | impl<'tcx> Cx<'tcx> { |
88 | fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) -> Cx<'tcx> { | |
3dfed10e | 89 | let typeck_results = tcx.typeck_opt_const_arg(def); |
487cf647 FG |
90 | let did = def.did; |
91 | let hir = tcx.hir(); | |
3b2f2976 XL |
92 | Cx { |
93 | tcx, | |
17df50a5 | 94 | thir: Thir::new(), |
3dfed10e | 95 | param_env: tcx.param_env(def.did), |
3dfed10e XL |
96 | region_scope_tree: tcx.region_scope_tree(def.did), |
97 | typeck_results, | |
923072b8 | 98 | rvalue_scopes: &typeck_results.rvalue_scopes, |
487cf647 | 99 | body_owner: did.to_def_id(), |
c295e0f8 | 100 | adjustment_span: None, |
487cf647 FG |
101 | apply_adjustments: hir |
102 | .attrs(hir.local_def_id_to_hir_id(did)) | |
103 | .iter() | |
104 | .all(|attr| attr.name_or_empty() != rustc_span::sym::custom_mir), | |
3b2f2976 | 105 | } |
e9174d1e | 106 | } |
b039eaaf | 107 | |
f2b60f7d FG |
108 | #[instrument(level = "debug", skip(self))] |
109 | fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Box<Pat<'tcx>> { | |
e74abb32 | 110 | let p = match self.tcx.hir().get(p.hir_id) { |
064997fb | 111 | Node::Pat(p) => p, |
dfeec247 | 112 | node => bug!("pattern became {:?}", node), |
ea8adc8c | 113 | }; |
17df50a5 | 114 | pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p) |
ea8adc8c | 115 | } |
f2b60f7d FG |
116 | |
117 | fn closure_env_param(&self, owner_def: LocalDefId, owner_id: HirId) -> Option<Param<'tcx>> { | |
118 | match self.tcx.def_kind(owner_def) { | |
119 | DefKind::Closure => { | |
120 | let closure_ty = self.typeck_results.node_type(owner_id); | |
121 | ||
122 | let ty::Closure(closure_def_id, closure_substs) = *closure_ty.kind() else { | |
123 | bug!("closure expr does not have closure type: {:?}", closure_ty); | |
124 | }; | |
125 | ||
126 | let bound_vars = self.tcx.mk_bound_variable_kinds(std::iter::once( | |
127 | ty::BoundVariableKind::Region(ty::BrEnv), | |
128 | )); | |
129 | let br = ty::BoundRegion { | |
130 | var: ty::BoundVar::from_usize(bound_vars.len() - 1), | |
131 | kind: ty::BrEnv, | |
132 | }; | |
133 | let env_region = ty::ReLateBound(ty::INNERMOST, br); | |
134 | let closure_env_ty = | |
135 | self.tcx.closure_env_ty(closure_def_id, closure_substs, env_region).unwrap(); | |
136 | let liberated_closure_env_ty = self.tcx.erase_late_bound_regions( | |
137 | ty::Binder::bind_with_vars(closure_env_ty, bound_vars), | |
138 | ); | |
139 | let env_param = Param { | |
140 | ty: liberated_closure_env_ty, | |
141 | pat: None, | |
142 | ty_span: None, | |
143 | self_kind: None, | |
144 | hir_id: None, | |
145 | }; | |
146 | ||
147 | Some(env_param) | |
148 | } | |
149 | DefKind::Generator => { | |
150 | let gen_ty = self.typeck_results.node_type(owner_id); | |
151 | let gen_param = | |
152 | Param { ty: gen_ty, pat: None, ty_span: None, self_kind: None, hir_id: None }; | |
153 | Some(gen_param) | |
154 | } | |
155 | _ => None, | |
156 | } | |
157 | } | |
158 | ||
159 | fn explicit_params<'a>( | |
160 | &'a mut self, | |
161 | owner_id: HirId, | |
162 | fn_decl: &'tcx hir::FnDecl<'tcx>, | |
163 | body: &'tcx hir::Body<'tcx>, | |
164 | ) -> impl Iterator<Item = Param<'tcx>> + 'a { | |
165 | let fn_sig = self.typeck_results.liberated_fn_sigs()[owner_id]; | |
166 | ||
167 | body.params.iter().enumerate().map(move |(index, param)| { | |
168 | let ty_span = fn_decl | |
169 | .inputs | |
170 | .get(index) | |
171 | // Make sure that inferred closure args have no type span | |
172 | .and_then(|ty| if param.pat.span != ty.span { Some(ty.span) } else { None }); | |
173 | ||
174 | let self_kind = if index == 0 && fn_decl.implicit_self.has_implicit_self() { | |
175 | Some(fn_decl.implicit_self) | |
176 | } else { | |
177 | None | |
178 | }; | |
179 | ||
180 | // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` | |
181 | // (as it's created inside the body itself, not passed in from outside). | |
182 | let ty = if fn_decl.c_variadic && index == fn_decl.inputs.len() { | |
183 | let va_list_did = self.tcx.require_lang_item(LangItem::VaList, Some(param.span)); | |
184 | ||
185 | self.tcx | |
186 | .bound_type_of(va_list_did) | |
187 | .subst(self.tcx, &[self.tcx.lifetimes.re_erased.into()]) | |
188 | } else { | |
189 | fn_sig.inputs()[index] | |
190 | }; | |
191 | ||
192 | let pat = self.pattern_from_hir(param.pat); | |
193 | Param { pat: Some(pat), ty, ty_span, self_kind, hir_id: Some(param.hir_id) } | |
194 | }) | |
195 | } | |
e9174d1e SL |
196 | } |
197 | ||
17df50a5 | 198 | impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'tcx> { |
dc9dc135 | 199 | fn tcx(&self) -> TyCtxt<'tcx> { |
6a06907d | 200 | self.tcx |
0bf4aa26 XL |
201 | } |
202 | ||
3dfed10e | 203 | fn typeck_results(&self) -> &ty::TypeckResults<'tcx> { |
6a06907d | 204 | self.typeck_results |
0bf4aa26 XL |
205 | } |
206 | } | |
207 | ||
e9174d1e SL |
208 | mod block; |
209 | mod expr; |