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