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