]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_hir_typeck/src/lib.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / compiler / rustc_hir_typeck / src / lib.rs
CommitLineData
2b03887a
FG
1#![feature(if_let_guard)]
2#![feature(let_chains)]
3#![feature(try_blocks)]
4#![feature(never_type)]
5#![feature(min_specialization)]
6#![feature(control_flow_enum)]
7#![feature(drain_filter)]
8#![allow(rustc::potential_query_instability)]
9#![recursion_limit = "256"]
10
11#[macro_use]
12extern crate tracing;
13
14#[macro_use]
15extern crate rustc_middle;
16
17mod _match;
18mod autoderef;
19mod callee;
20// Used by clippy;
21pub mod cast;
22mod check;
23mod closure;
24mod coercion;
25mod demand;
26mod diverges;
27mod errors;
28mod expectation;
29mod expr;
30// Used by clippy;
31pub mod expr_use_visitor;
32mod fallback;
33mod fn_ctxt;
34mod gather_locals;
35mod generator_interior;
36mod inherited;
37mod intrinsicck;
38mod mem_categorization;
39mod method;
40mod op;
41mod pat;
42mod place_op;
43mod rvalue_scopes;
44mod upvar;
45mod writeback;
46
47pub use diverges::Diverges;
48pub use expectation::Expectation;
49pub use fn_ctxt::*;
50pub use inherited::{Inherited, InheritedBuilder};
51
52use crate::check::check_fn;
53use crate::coercion::DynamicCoerceMany;
54use crate::gather_locals::GatherLocalsVisitor;
55use rustc_data_structures::unord::UnordSet;
487cf647 56use rustc_errors::{struct_span_err, DiagnosticId, ErrorGuaranteed, MultiSpan};
2b03887a 57use rustc_hir as hir;
487cf647 58use rustc_hir::def::{DefKind, Res};
2b03887a
FG
59use rustc_hir::intravisit::Visitor;
60use rustc_hir::{HirIdMap, Node};
61use rustc_hir_analysis::astconv::AstConv;
62use rustc_hir_analysis::check::check_abi;
63use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
64use rustc_middle::traits;
65use rustc_middle::ty::query::Providers;
66use rustc_middle::ty::{self, Ty, TyCtxt};
67use rustc_session::config;
68use rustc_session::Session;
69use rustc_span::def_id::{DefId, LocalDefId};
70use rustc_span::Span;
71
72#[macro_export]
73macro_rules! type_error_struct {
74 ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
75 let mut err = rustc_errors::struct_span_err!($session, $span, $code, $($message)*);
76
77 if $typ.references_error() {
78 err.downgrade_to_delayed_bug();
79 }
80
81 err
82 })
83}
84
85/// The type of a local binding, including the revealed type for anon types.
86#[derive(Copy, Clone, Debug)]
87pub struct LocalTy<'tcx> {
88 decl_ty: Ty<'tcx>,
89 revealed_ty: Ty<'tcx>,
90}
91
2b03887a
FG
92/// If this `DefId` is a "primary tables entry", returns
93/// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
94///
95/// If this function returns `Some`, then `typeck_results(def_id)` will
96/// succeed; if it returns `None`, then `typeck_results(def_id)` may or
97/// may not succeed. In some cases where this function returns `None`
98/// (notably closures), `typeck_results(def_id)` would wind up
99/// redirecting to the owning function.
100fn primary_body_of(
101 tcx: TyCtxt<'_>,
102 id: hir::HirId,
103) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> {
104 match tcx.hir().get(id) {
105 Node::Item(item) => match item.kind {
106 hir::ItemKind::Const(ty, body) | hir::ItemKind::Static(ty, _, body) => {
107 Some((body, Some(ty), None))
108 }
109 hir::ItemKind::Fn(ref sig, .., body) => Some((body, None, Some(sig))),
110 _ => None,
111 },
112 Node::TraitItem(item) => match item.kind {
113 hir::TraitItemKind::Const(ty, Some(body)) => Some((body, Some(ty), None)),
114 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
115 Some((body, None, Some(sig)))
116 }
117 _ => None,
118 },
119 Node::ImplItem(item) => match item.kind {
120 hir::ImplItemKind::Const(ty, body) => Some((body, Some(ty), None)),
121 hir::ImplItemKind::Fn(ref sig, body) => Some((body, None, Some(sig))),
122 _ => None,
123 },
124 Node::AnonConst(constant) => Some((constant.body, None, None)),
125 _ => None,
126 }
127}
128
129fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
130 // Closures' typeck results come from their outermost function,
131 // as they are part of the same "inference environment".
132 let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
133 if typeck_root_def_id != def_id {
134 return tcx.has_typeck_results(typeck_root_def_id);
135 }
136
137 if let Some(def_id) = def_id.as_local() {
138 let id = tcx.hir().local_def_id_to_hir_id(def_id);
139 primary_body_of(tcx, id).is_some()
140 } else {
141 false
142 }
143}
144
145fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDefId> {
146 &*tcx.typeck(def_id).used_trait_imports
147}
148
149fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) {
150 tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id));
151}
152
153fn typeck_const_arg<'tcx>(
154 tcx: TyCtxt<'tcx>,
155 (did, param_did): (LocalDefId, DefId),
156) -> &ty::TypeckResults<'tcx> {
157 let fallback = move || tcx.type_of(param_did);
158 typeck_with_fallback(tcx, did, fallback)
159}
160
161fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
162 if let Some(param_did) = tcx.opt_const_param_of(def_id) {
163 tcx.typeck_const_arg((def_id, param_did))
164 } else {
165 let fallback = move || tcx.type_of(def_id.to_def_id());
166 typeck_with_fallback(tcx, def_id, fallback)
167 }
168}
169
170/// Used only to get `TypeckResults` for type inference during error recovery.
171/// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors.
172fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
173 let fallback = move || {
174 let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id));
175 tcx.ty_error_with_message(span, "diagnostic only typeck table used")
176 };
177 typeck_with_fallback(tcx, def_id, fallback)
178}
179
487cf647 180#[instrument(level = "debug", skip(tcx, fallback), ret)]
2b03887a
FG
181fn typeck_with_fallback<'tcx>(
182 tcx: TyCtxt<'tcx>,
183 def_id: LocalDefId,
184 fallback: impl Fn() -> Ty<'tcx> + 'tcx,
185) -> &'tcx ty::TypeckResults<'tcx> {
186 // Closures' typeck results come from their outermost function,
187 // as they are part of the same "inference environment".
188 let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
189 if typeck_root_def_id != def_id {
190 return tcx.typeck(typeck_root_def_id);
191 }
192
193 let id = tcx.hir().local_def_id_to_hir_id(def_id);
194 let span = tcx.hir().span(id);
195
196 // Figure out what primary body this item has.
197 let (body_id, body_ty, fn_sig) = primary_body_of(tcx, id).unwrap_or_else(|| {
198 span_bug!(span, "can't type-check body of {:?}", def_id);
199 });
200 let body = tcx.hir().body(body_id);
201
202 let typeck_results = Inherited::build(tcx, def_id).enter(|inh| {
203 let param_env = tcx.param_env(def_id);
487cf647
FG
204 let mut fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
205
206 if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
2b03887a 207 let fn_sig = if rustc_hir_analysis::collect::get_infer_ret_ty(&decl.output).is_some() {
9c376795 208 fcx.astconv().ty_of_fn(id, header.unsafety, header.abi, decl, None, None)
2b03887a
FG
209 } else {
210 tcx.fn_sig(def_id)
211 };
212
213 check_abi(tcx, id, span, fn_sig.abi());
214
215 // Compute the function signature from point of view of inside the fn.
216 let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
487cf647
FG
217 let fn_sig = fcx.normalize(body.value.span, fn_sig);
218
219 check_fn(&mut fcx, fn_sig, decl, def_id, body, None);
2b03887a 220 } else {
2b03887a
FG
221 let expected_type = body_ty
222 .and_then(|ty| match ty.kind {
9c376795 223 hir::TyKind::Infer => Some(fcx.astconv().ast_ty_to_ty(ty)),
2b03887a
FG
224 _ => None,
225 })
226 .unwrap_or_else(|| match tcx.hir().get(id) {
9c376795 227 Node::AnonConst(_) => match tcx.hir().get(tcx.hir().parent_id(id)) {
2b03887a
FG
228 Node::Expr(&hir::Expr {
229 kind: hir::ExprKind::ConstBlock(ref anon_const),
230 ..
231 }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
232 kind: TypeVariableOriginKind::TypeInference,
233 span,
234 }),
235 Node::Ty(&hir::Ty {
236 kind: hir::TyKind::Typeof(ref anon_const), ..
237 }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
238 kind: TypeVariableOriginKind::TypeInference,
239 span,
240 }),
241 Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
242 | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
9c376795
FG
243 let operand_ty =
244 asm.operands.iter().find_map(|(op, _op_sp)| match op {
2b03887a
FG
245 hir::InlineAsmOperand::Const { anon_const }
246 if anon_const.hir_id == id =>
247 {
248 // Inline assembly constants must be integers.
249 Some(fcx.next_int_var())
250 }
251 hir::InlineAsmOperand::SymFn { anon_const }
252 if anon_const.hir_id == id =>
253 {
254 Some(fcx.next_ty_var(TypeVariableOrigin {
255 kind: TypeVariableOriginKind::MiscVariable,
256 span,
257 }))
258 }
259 _ => None,
9c376795 260 });
2b03887a
FG
261 operand_ty.unwrap_or_else(fallback)
262 }
263 _ => fallback(),
264 },
265 _ => fallback(),
266 });
267
487cf647 268 let expected_type = fcx.normalize(body.value.span, expected_type);
2b03887a
FG
269 fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
270
271 // Gather locals in statics (because of block expressions).
272 GatherLocalsVisitor::new(&fcx).visit_body(body);
273
274 fcx.check_expr_coercable_to_type(&body.value, expected_type, None);
275
276 fcx.write_ty(id, expected_type);
2b03887a
FG
277 };
278
487cf647 279 fcx.type_inference_fallback();
2b03887a
FG
280
281 // Even though coercion casts provide type hints, we check casts after fallback for
282 // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
283 fcx.check_casts();
487cf647 284 fcx.select_obligations_where_possible(|_| {});
2b03887a
FG
285
286 // Closure and generator analysis may run after fallback
287 // because they don't constrain other type variables.
288 // Closure analysis only runs on closures. Therefore they only need to fulfill non-const predicates (as of now)
289 let prev_constness = fcx.param_env.constness();
290 fcx.param_env = fcx.param_env.without_const();
291 fcx.closure_analyze(body);
292 fcx.param_env = fcx.param_env.with_constness(prev_constness);
293 assert!(fcx.deferred_call_resolutions.borrow().is_empty());
294 // Before the generator analysis, temporary scopes shall be marked to provide more
295 // precise information on types to be captured.
296 fcx.resolve_rvalue_scopes(def_id.to_def_id());
297 fcx.resolve_generator_interiors(def_id.to_def_id());
298
299 for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
9c376795 300 let ty = fcx.normalize(span, ty);
2b03887a
FG
301 fcx.require_type_is_sized(ty, span, code);
302 }
303
304 fcx.select_all_obligations_or_error();
305
487cf647 306 if let None = fcx.infcx.tainted_by_errors() {
2b03887a
FG
307 fcx.check_transmutes();
308 }
309
310 fcx.check_asms();
311
312 fcx.infcx.skip_region_resolution();
313
314 fcx.resolve_type_vars_in_body(body)
315 });
316
317 // Consistency check our TypeckResults instance can hold all ItemLocalIds
318 // it will need to hold.
319 assert_eq!(typeck_results.hir_owner, id.owner);
320
321 typeck_results
322}
323
324/// When `check_fn` is invoked on a generator (i.e., a body that
325/// includes yield), it returns back some information about the yield
326/// points.
327struct GeneratorTypes<'tcx> {
328 /// Type of generator argument / values returned by `yield`.
329 resume_ty: Ty<'tcx>,
330
331 /// Type of value that is yielded.
332 yield_ty: Ty<'tcx>,
333
334 /// Types that are captured (see `GeneratorInterior` for more).
335 interior: Ty<'tcx>,
336
337 /// Indicates if the generator is movable or static (immovable).
338 movability: hir::Movability,
339}
340
341#[derive(Copy, Clone, Debug, PartialEq, Eq)]
342pub enum Needs {
343 MutPlace,
344 None,
345}
346
347impl Needs {
348 fn maybe_mut_place(m: hir::Mutability) -> Self {
349 match m {
350 hir::Mutability::Mut => Needs::MutPlace,
351 hir::Mutability::Not => Needs::None,
352 }
353 }
354}
355
356#[derive(Debug, Copy, Clone)]
357pub enum PlaceOp {
358 Deref,
359 Index,
360}
361
362pub struct BreakableCtxt<'tcx> {
363 may_break: bool,
364
365 // this is `null` for loops where break with a value is illegal,
366 // such as `while`, `for`, and `while let`
367 coerce: Option<DynamicCoerceMany<'tcx>>,
368}
369
370pub struct EnclosingBreakables<'tcx> {
371 stack: Vec<BreakableCtxt<'tcx>>,
372 by_id: HirIdMap<usize>,
373}
374
375impl<'tcx> EnclosingBreakables<'tcx> {
376 fn find_breakable(&mut self, target_id: hir::HirId) -> &mut BreakableCtxt<'tcx> {
377 self.opt_find_breakable(target_id).unwrap_or_else(|| {
378 bug!("could not find enclosing breakable with id {}", target_id);
379 })
380 }
381
382 fn opt_find_breakable(&mut self, target_id: hir::HirId) -> Option<&mut BreakableCtxt<'tcx>> {
383 match self.by_id.get(&target_id) {
384 Some(ix) => Some(&mut self.stack[*ix]),
385 None => None,
386 }
387 }
388}
389
487cf647
FG
390fn report_unexpected_variant_res(
391 tcx: TyCtxt<'_>,
392 res: Res,
393 qpath: &hir::QPath<'_>,
394 span: Span,
395 err_code: &str,
396 expected: &str,
397) -> ErrorGuaranteed {
398 let res_descr = match res {
399 Res::Def(DefKind::Variant, _) => "struct variant",
400 _ => res.descr(),
401 };
402 let path_str = rustc_hir_pretty::qpath_to_string(qpath);
403 let mut err = tcx.sess.struct_span_err_with_code(
2b03887a 404 span,
487cf647
FG
405 format!("expected {expected}, found {res_descr} `{path_str}`"),
406 DiagnosticId::Error(err_code.into()),
407 );
408 match res {
409 Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == "E0164" => {
410 let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html";
411 err.span_label(span, "`fn` calls are not allowed in patterns");
412 err.help(format!("for more information, visit {patterns_url}"))
413 }
414 _ => err.span_label(span, format!("not a {expected}")),
415 }
416 .emit()
2b03887a
FG
417}
418
419/// Controls whether the arguments are tupled. This is used for the call
420/// operator.
421///
422/// Tupling means that all call-side arguments are packed into a tuple and
423/// passed as a single parameter. For example, if tupling is enabled, this
424/// function:
425/// ```
426/// fn f(x: (isize, isize)) {}
427/// ```
428/// Can be called as:
429/// ```ignore UNSOLVED (can this be done in user code?)
430/// # fn f(x: (isize, isize)) {}
431/// f(1, 2);
432/// ```
433/// Instead of:
434/// ```
435/// # fn f(x: (isize, isize)) {}
436/// f((1, 2));
437/// ```
487cf647 438#[derive(Copy, Clone, Eq, PartialEq)]
2b03887a
FG
439enum TupleArgumentsFlag {
440 DontTupleArguments,
441 TupleArguments,
442}
443
444fn fatally_break_rust(sess: &Session) {
445 let handler = sess.diagnostic();
446 handler.span_bug_no_panic(
447 MultiSpan::new(),
448 "It looks like you're trying to break rust; would you like some ICE?",
449 );
450 handler.note_without_error("the compiler expectedly panicked. this is a feature.");
451 handler.note_without_error(
452 "we would appreciate a joke overview: \
453 https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
454 );
455 handler.note_without_error(&format!(
456 "rustc {} running on {}",
457 option_env!("CFG_VERSION").unwrap_or("unknown_version"),
458 config::host_triple(),
459 ));
460}
461
9c376795
FG
462fn has_expected_num_generic_args(
463 tcx: TyCtxt<'_>,
2b03887a
FG
464 trait_did: Option<DefId>,
465 expected: usize,
466) -> bool {
467 trait_did.map_or(true, |trait_did| {
468 let generics = tcx.generics_of(trait_did);
469 generics.count() == expected + if generics.has_self { 1 } else { 0 }
470 })
471}
472
473pub fn provide(providers: &mut Providers) {
474 method::provide(providers);
475 *providers = Providers {
476 typeck_item_bodies,
477 typeck_const_arg,
478 typeck,
479 diagnostic_only_typeck,
480 has_typeck_results,
481 used_trait_imports,
482 ..*providers
483 };
484}