]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
New upstream version 1.62.1+dfsg1
[rustc.git] / compiler / rustc_typeck / src / check / fn_ctxt / mod.rs
CommitLineData
29967ef6
XL
1mod _impl;
2mod checks;
3mod suggestions;
4
5pub use _impl::*;
29967ef6
XL
6pub use suggestions::*;
7
8use crate::astconv::AstConv;
9use crate::check::coercion::DynamicCoerceMany;
10use crate::check::{Diverges, EnclosingBreakables, Inherited, UnsafetyState};
11
12use rustc_hir as hir;
13use rustc_hir::def_id::DefId;
14use rustc_infer::infer;
15use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
5e7ed085 16use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
29967ef6
XL
17use rustc_middle::ty::fold::TypeFoldable;
18use rustc_middle::ty::subst::GenericArgKind;
19use rustc_middle::ty::{self, Const, Ty, TyCtxt};
20use rustc_session::Session;
6a06907d 21use rustc_span::symbol::Ident;
29967ef6
XL
22use rustc_span::{self, Span};
23use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
24
25use std::cell::{Cell, RefCell};
26use std::ops::Deref;
27
28pub struct FnCtxt<'a, 'tcx> {
29 pub(super) body_id: hir::HirId,
30
31 /// The parameter environment used for proving trait obligations
32 /// in this function. This can change when we descend into
33 /// closures (as they bring new things into scope), hence it is
34 /// not part of `Inherited` (as of the time of this writing,
35 /// closures do not yet change the environment, but they will
36 /// eventually).
37 pub(super) param_env: ty::ParamEnv<'tcx>,
38
39 /// Number of errors that had been reported when we started
40 /// checking this function. On exit, if we find that *more* errors
41 /// have been reported, we will skip regionck and other work that
42 /// expects the types within the function to be consistent.
43 // FIXME(matthewjasper) This should not exist, and it's not correct
44 // if type checking is run in parallel.
45 err_count_on_creation: usize,
46
47 /// If `Some`, this stores coercion information for returned
48 /// expressions. If `None`, this is in a context where return is
49 /// inappropriate, such as a const expression.
50 ///
51 /// This is a `RefCell<DynamicCoerceMany>`, which means that we
52 /// can track all the return expressions and then use them to
53 /// compute a useful coercion from the set, similar to a match
54 /// expression or other branching context. You can use methods
55 /// like `expected_ty` to access the declared return type (if
56 /// any).
57 pub(super) ret_coercion: Option<RefCell<DynamicCoerceMany<'tcx>>>,
58
29967ef6
XL
59 pub(super) ret_type_span: Option<Span>,
60
61 /// Used exclusively to reduce cost of advanced evaluation used for
62 /// more helpful diagnostics.
63 pub(super) in_tail_expr: bool,
64
65 /// First span of a return site that we find. Used in error messages.
5869c6ff 66 pub(super) ret_coercion_span: Cell<Option<Span>>,
29967ef6
XL
67
68 pub(super) resume_yield_tys: Option<(Ty<'tcx>, Ty<'tcx>)>,
69
5869c6ff 70 pub(super) ps: Cell<UnsafetyState>,
29967ef6
XL
71
72 /// Whether the last checked node generates a divergence (e.g.,
73 /// `return` will set this to `Always`). In general, when entering
74 /// an expression or other node in the tree, the initial value
75 /// indicates whether prior parts of the containing expression may
76 /// have diverged. It is then typically set to `Maybe` (and the
77 /// old value remembered) for processing the subparts of the
78 /// current expression. As each subpart is processed, they may set
79 /// the flag to `Always`, etc. Finally, at the end, we take the
80 /// result and "union" it with the original value, so that when we
81 /// return the flag indicates if any subpart of the parent
82 /// expression (up to and including this part) has diverged. So,
83 /// if you read it after evaluating a subexpression `X`, the value
84 /// you get indicates whether any subexpression that was
85 /// evaluating up to and including `X` diverged.
86 ///
87 /// We currently use this flag only for diagnostic purposes:
88 ///
89 /// - To warn about unreachable code: if, after processing a
90 /// sub-expression but before we have applied the effects of the
91 /// current node, we see that the flag is set to `Always`, we
92 /// can issue a warning. This corresponds to something like
93 /// `foo(return)`; we warn on the `foo()` expression. (We then
94 /// update the flag to `WarnedAlways` to suppress duplicate
95 /// reports.) Similarly, if we traverse to a fresh statement (or
94222f64 96 /// tail expression) from an `Always` setting, we will issue a
29967ef6
XL
97 /// warning. This corresponds to something like `{return;
98 /// foo();}` or `{return; 22}`, where we would warn on the
99 /// `foo()` or `22`.
100 ///
101 /// An expression represents dead code if, after checking it,
102 /// the diverges flag is set to something other than `Maybe`.
103 pub(super) diverges: Cell<Diverges>,
104
105 /// Whether any child nodes have any type errors.
106 pub(super) has_errors: Cell<bool>,
107
108 pub(super) enclosing_breakables: RefCell<EnclosingBreakables<'tcx>>,
109
110 pub(super) inh: &'a Inherited<'a, 'tcx>,
94222f64
XL
111
112 /// True if the function or closure's return type is known before
113 /// entering the function/closure, i.e. if the return type is
114 /// either given explicitly or inferred from, say, an `Fn*` trait
115 /// bound. Used for diagnostic purposes only.
116 pub(super) return_type_pre_known: bool,
29967ef6
XL
117}
118
119impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
120 pub fn new(
121 inh: &'a Inherited<'a, 'tcx>,
122 param_env: ty::ParamEnv<'tcx>,
123 body_id: hir::HirId,
124 ) -> FnCtxt<'a, 'tcx> {
125 FnCtxt {
126 body_id,
127 param_env,
128 err_count_on_creation: inh.tcx.sess.err_count(),
129 ret_coercion: None,
29967ef6
XL
130 ret_type_span: None,
131 in_tail_expr: false,
5869c6ff 132 ret_coercion_span: Cell::new(None),
29967ef6 133 resume_yield_tys: None,
5869c6ff 134 ps: Cell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)),
29967ef6
XL
135 diverges: Cell::new(Diverges::Maybe),
136 has_errors: Cell::new(false),
137 enclosing_breakables: RefCell::new(EnclosingBreakables {
138 stack: Vec::new(),
139 by_id: Default::default(),
140 }),
141 inh,
94222f64 142 return_type_pre_known: true,
29967ef6
XL
143 }
144 }
145
146 pub fn cause(&self, span: Span, code: ObligationCauseCode<'tcx>) -> ObligationCause<'tcx> {
147 ObligationCause::new(span, self.body_id, code)
148 }
149
150 pub fn misc(&self, span: Span) -> ObligationCause<'tcx> {
151 self.cause(span, ObligationCauseCode::MiscObligation)
152 }
153
154 pub fn sess(&self) -> &Session {
155 &self.tcx.sess
156 }
157
158 pub fn errors_reported_since_creation(&self) -> bool {
159 self.tcx.sess.err_count() > self.err_count_on_creation
160 }
161}
162
163impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> {
164 type Target = Inherited<'a, 'tcx>;
165 fn deref(&self) -> &Self::Target {
166 &self.inh
167 }
168}
169
170impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
171 fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
172 self.tcx
173 }
174
175 fn item_def_id(&self) -> Option<DefId> {
176 None
177 }
178
6a06907d
XL
179 fn get_type_parameter_bounds(
180 &self,
181 _: Span,
182 def_id: DefId,
183 _: Ident,
184 ) -> ty::GenericPredicates<'tcx> {
29967ef6 185 let tcx = self.tcx;
04454e1e 186 let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local());
29967ef6
XL
187 let generics = tcx.generics_of(item_def_id);
188 let index = generics.param_def_id_to_index[&def_id];
189 ty::GenericPredicates {
190 parent: None,
191 predicates: tcx.arena.alloc_from_iter(
192 self.param_env.caller_bounds().iter().filter_map(|predicate| {
5869c6ff 193 match predicate.kind().skip_binder() {
94222f64 194 ty::PredicateKind::Trait(data) if data.self_ty().is_param(index) => {
29967ef6
XL
195 // HACK(eddyb) should get the original `Span`.
196 let span = tcx.def_span(def_id);
197 Some((predicate, span))
198 }
199 _ => None,
200 }
201 }),
202 ),
203 }
204 }
205
206 fn re_infer(&self, def: Option<&ty::GenericParamDef>, span: Span) -> Option<ty::Region<'tcx>> {
207 let v = match def {
208 Some(def) => infer::EarlyBoundRegion(span, def.name),
209 None => infer::MiscVariable(span),
210 };
211 Some(self.next_region_var(v))
212 }
213
214 fn allow_ty_infer(&self) -> bool {
215 true
216 }
217
218 fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
219 if let Some(param) = param {
220 if let GenericArgKind::Type(ty) = self.var_for_def(span, param).unpack() {
221 return ty;
222 }
223 unreachable!()
224 } else {
225 self.next_ty_var(TypeVariableOrigin {
226 kind: TypeVariableOriginKind::TypeInference,
227 span,
228 })
229 }
230 }
231
232 fn ct_infer(
233 &self,
234 ty: Ty<'tcx>,
235 param: Option<&ty::GenericParamDef>,
236 span: Span,
5099ac24 237 ) -> Const<'tcx> {
29967ef6
XL
238 if let Some(param) = param {
239 if let GenericArgKind::Const(ct) = self.var_for_def(span, param).unpack() {
240 return ct;
241 }
242 unreachable!()
243 } else {
244 self.next_const_var(
245 ty,
246 ConstVariableOrigin { kind: ConstVariableOriginKind::ConstInference, span },
247 )
248 }
249 }
250
251 fn projected_ty_from_poly_trait_ref(
252 &self,
253 span: Span,
254 item_def_id: DefId,
255 item_segment: &hir::PathSegment<'_>,
256 poly_trait_ref: ty::PolyTraitRef<'tcx>,
257 ) -> Ty<'tcx> {
258 let (trait_ref, _) = self.replace_bound_vars_with_fresh_vars(
259 span,
260 infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id),
fc512014 261 poly_trait_ref,
29967ef6
XL
262 );
263
264 let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item(
265 self,
266 self.tcx,
267 span,
268 item_def_id,
269 item_segment,
270 trait_ref.substs,
271 );
272
273 self.tcx().mk_projection(item_def_id, item_substs)
274 }
275
276 fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
277 if ty.has_escaping_bound_vars() {
278 ty // FIXME: normalization and escaping regions
279 } else {
5099ac24 280 self.normalize_associated_types_in(span, ty)
29967ef6
XL
281 }
282 }
283
284 fn set_tainted_by_errors(&self) {
285 self.infcx.set_tainted_by_errors()
286 }
287
288 fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, _span: Span) {
289 self.write_ty(hir_id, ty)
290 }
291}