1#![allow(rustc::diagnostic_outside_of_impl)]
3#![allow(rustc::untranslatable_diagnostic)]
4#![feature(assert_matches)]
5#![feature(box_patterns)]
6#![feature(if_let_guard)]
7#![feature(iter_intersperse)]
8#![feature(iter_order_by)]
9#![feature(never_type)]
10#![feature(trim_prefix_suffix)]
11mod _match;
14mod autoderef;
15mod callee;
16pub mod cast;
18mod check;
19mod closure;
20mod coercion;
21mod demand;
22mod diverges;
23mod errors;
24mod expectation;
25mod expr;
26mod inline_asm;
27pub mod expr_use_visitor;
29mod fallback;
30mod fn_ctxt;
31mod gather_locals;
32mod intrinsicck;
33mod loops;
34mod method;
35mod naked_functions;
36mod op;
37mod opaque_types;
38mod pat;
39mod place_op;
40mod rvalue_scopes;
41mod typeck_root_ctxt;
42mod upvar;
43mod writeback;
44
45pub use coercion::can_coerce;
46use fn_ctxt::FnCtxt;
47use rustc_data_structures::unord::UnordSet;
48use rustc_errors::codes::*;
49use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
50use rustc_hir as hir;
51use rustc_hir::def::{DefKind, Res};
52use rustc_hir::{HirId, HirIdMap, Node};
53use rustc_hir_analysis::check::{check_abi, check_custom_abi};
54use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
55use rustc_infer::traits::{ObligationCauseCode, ObligationInspector, WellFormedLoc};
56use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
57use rustc_middle::query::Providers;
58use rustc_middle::ty::{self, Ty, TyCtxt};
59use rustc_middle::{bug, span_bug};
60use rustc_session::config;
61use rustc_span::Span;
62use rustc_span::def_id::LocalDefId;
63use tracing::{debug, instrument};
64use typeck_root_ctxt::TypeckRootCtxt;
65
66use crate::check::check_fn;
67use crate::coercion::DynamicCoerceMany;
68use crate::diverges::Diverges;
69use crate::expectation::Expectation;
70use crate::fn_ctxt::LoweredTy;
71use crate::gather_locals::GatherLocalsVisitor;
72
73rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
74
75#[macro_export]
76macro_rules! type_error_struct {
77 ($dcx:expr, $span:expr, $typ:expr, $code:expr, $($message:tt)*) => ({
78 let mut err = rustc_errors::struct_span_code_err!($dcx, $span, $code, $($message)*);
79
80 if $typ.references_error() {
81 err.downgrade_to_delayed_bug();
82 }
83
84 err
85 })
86}
87
88fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDefId> {
89 &tcx.typeck(def_id).used_trait_imports
90}
91
92fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> {
93 typeck_with_inspect(tcx, def_id, None)
94}
95
96pub fn inspect_typeck<'tcx>(
101 tcx: TyCtxt<'tcx>,
102 def_id: LocalDefId,
103 inspect: ObligationInspector<'tcx>,
104) -> &'tcx ty::TypeckResults<'tcx> {
105 typeck_with_inspect(tcx, def_id, Some(inspect))
106}
107
108#[instrument(level = "debug", skip(tcx, inspector), ret)]
109fn typeck_with_inspect<'tcx>(
110 tcx: TyCtxt<'tcx>,
111 def_id: LocalDefId,
112 inspector: Option<ObligationInspector<'tcx>>,
113) -> &'tcx ty::TypeckResults<'tcx> {
114 let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
117 if typeck_root_def_id != def_id {
118 return tcx.typeck(typeck_root_def_id);
119 }
120
121 let id = tcx.local_def_id_to_hir_id(def_id);
122 let node = tcx.hir_node(id);
123 let span = tcx.def_span(def_id);
124
125 let body_id = node.body_id().unwrap_or_else(|| {
127 span_bug!(span, "can't type-check body of {:?}", def_id);
128 });
129 let body = tcx.hir_body(body_id);
130
131 let param_env = tcx.param_env(def_id);
132
133 let root_ctxt = TypeckRootCtxt::new(tcx, def_id);
134 if let Some(inspector) = inspector {
135 root_ctxt.infcx.attach_obligation_inspector(inspector);
136 }
137 let mut fcx = FnCtxt::new(&root_ctxt, param_env, def_id);
138
139 if let hir::Node::Item(hir::Item { kind: hir::ItemKind::GlobalAsm { .. }, .. }) = node {
140 let ty = fcx.check_expr(body.value);
143 fcx.write_ty(id, ty);
144 } else if let Some(hir::FnSig { header, decl, span: fn_sig_span }) = node.fn_sig() {
145 let fn_sig = if decl.output.is_suggestable_infer_ty().is_some() {
146 fcx.lowerer().lower_fn_ty(id, header.safety(), header.abi, decl, None, None)
151 } else {
152 tcx.fn_sig(def_id).instantiate_identity()
153 };
154
155 check_abi(tcx, id, span, fn_sig.abi());
156 check_custom_abi(tcx, def_id, fn_sig.skip_binder(), *fn_sig_span);
157
158 loops::check(tcx, def_id, body);
159
160 let mut fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
162
163 let arg_span =
169 |idx| decl.inputs.get(idx).map_or(decl.output.span(), |arg: &hir::Ty<'_>| arg.span);
170
171 fn_sig.inputs_and_output = tcx.mk_type_list_from_iter(
172 fn_sig
173 .inputs_and_output
174 .iter()
175 .enumerate()
176 .map(|(idx, ty)| fcx.normalize(arg_span(idx), ty)),
177 );
178
179 if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NAKED) {
180 naked_functions::typeck_naked_fn(tcx, def_id, body);
181 }
182
183 check_fn(&mut fcx, fn_sig, None, decl, def_id, body, tcx.features().unsized_fn_params());
184 } else {
185 let expected_type = if let Some(infer_ty) = infer_type_if_missing(&fcx, node) {
186 infer_ty
187 } else if let Some(ty) = node.ty()
188 && ty.is_suggestable_infer_ty()
189 {
190 fcx.lowerer().lower_ty(ty)
195 } else {
196 tcx.type_of(def_id).instantiate_identity()
197 };
198
199 loops::check(tcx, def_id, body);
200
201 let expected_type = fcx.normalize(body.value.span, expected_type);
202
203 let wf_code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(def_id)));
204 fcx.register_wf_obligation(expected_type.into(), body.value.span, wf_code);
205
206 fcx.check_expr_coercible_to_type(body.value, expected_type, None);
207
208 fcx.write_ty(id, expected_type);
209 };
210
211 fcx.check_repeat_exprs();
222
223 if fcx.next_trait_solver() {
226 fcx.try_handle_opaque_type_uses_next();
227 }
228
229 fcx.type_inference_fallback();
230
231 fcx.check_casts();
234 fcx.select_obligations_where_possible(|_| {});
235
236 fcx.closure_analyze(body);
239 assert!(fcx.deferred_call_resolutions.borrow().is_empty());
240 fcx.resolve_rvalue_scopes(def_id.to_def_id());
243
244 for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
245 let ty = fcx.normalize(span, ty);
246 fcx.require_type_is_sized(ty, span, code);
247 }
248
249 fcx.select_obligations_where_possible(|_| {});
250
251 debug!(pending_obligations = ?fcx.fulfillment_cx.borrow().pending_obligations());
252
253 if fcx.next_trait_solver() {
256 fcx.handle_opaque_type_uses_next();
257 }
258
259 fcx.drain_stalled_coroutine_obligations();
262 if fcx.infcx.tainted_by_errors().is_none() {
263 fcx.report_ambiguity_errors();
264 }
265
266 fcx.check_asms();
267
268 let typeck_results = fcx.resolve_type_vars_in_body(body);
269
270 fcx.detect_opaque_types_added_during_writeback();
271
272 assert_eq!(typeck_results.hir_owner, id.owner);
275
276 typeck_results
277}
278
279fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Option<Ty<'tcx>> {
280 let tcx = fcx.tcx;
281 let def_id = fcx.body_id;
282 let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer(()), span, .. }) = node.ty()
283 {
284 if let Some(item) = tcx.opt_associated_item(def_id.into())
285 && let ty::AssocKind::Const { .. } = item.kind
286 && let ty::AssocContainer::TraitImpl(Ok(trait_item_def_id)) = item.container
287 {
288 let impl_def_id = item.container_id(tcx);
289 let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate_identity();
290 let args = ty::GenericArgs::identity_for_item(tcx, def_id).rebase_onto(
291 tcx,
292 impl_def_id,
293 impl_trait_ref.args,
294 );
295 tcx.check_args_compatible(trait_item_def_id, args)
296 .then(|| tcx.type_of(trait_item_def_id).instantiate(tcx, args))
297 } else {
298 Some(fcx.next_ty_var(span))
299 }
300 } else if let Node::AnonConst(_) = node {
301 let id = tcx.local_def_id_to_hir_id(def_id);
302 match tcx.parent_hir_node(id) {
303 Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(anon_const), span, .. })
304 if anon_const.hir_id == id =>
305 {
306 Some(fcx.next_ty_var(span))
307 }
308 Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. })
309 | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm { asm, .. }, span, .. }) => {
310 asm.operands.iter().find_map(|(op, _op_sp)| match op {
311 hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == id => {
312 Some(fcx.next_ty_var(span))
313 }
314 _ => None,
315 })
316 }
317 _ => None,
318 }
319 } else {
320 None
321 };
322 expected_type
323}
324
325#[derive(Debug, PartialEq, Copy, Clone)]
329struct CoroutineTypes<'tcx> {
330 resume_ty: Ty<'tcx>,
332
333 yield_ty: Ty<'tcx>,
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 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: 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: 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
386fn report_unexpected_variant_res(
387 tcx: TyCtxt<'_>,
388 res: Res,
389 expr: Option<&hir::Expr<'_>>,
390 qpath: &hir::QPath<'_>,
391 span: Span,
392 err_code: ErrCode,
393 expected: &str,
394) -> ErrorGuaranteed {
395 let res_descr = match res {
396 Res::Def(DefKind::Variant, _) => "struct variant",
397 _ => res.descr(),
398 };
399 let path_str = rustc_hir_pretty::qpath_to_string(&tcx, qpath);
400 let mut err = tcx
401 .dcx()
402 .struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`"))
403 .with_code(err_code);
404 match res {
405 Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == E0164 => {
406 let patterns_url = "https://doc.rust-lang.org/book/ch19-00-patterns.html";
407 err.with_span_label(span, "`fn` calls are not allowed in patterns")
408 .with_help(format!("for more information, visit {patterns_url}"))
409 }
410 Res::Def(DefKind::Variant, _) if let Some(expr) = expr => {
411 err.span_label(span, format!("not a {expected}"));
412 let variant = tcx.expect_variant_res(res);
413 let sugg = if variant.fields.is_empty() {
414 " {}".to_string()
415 } else {
416 format!(
417 " {{ {} }}",
418 variant
419 .fields
420 .iter()
421 .map(|f| format!("{}: /* value */", f.name))
422 .collect::<Vec<_>>()
423 .join(", ")
424 )
425 };
426 let descr = "you might have meant to create a new value of the struct";
427 let mut suggestion = vec![];
428 match tcx.parent_hir_node(expr.hir_id) {
429 hir::Node::Expr(hir::Expr {
430 kind: hir::ExprKind::Call(..),
431 span: call_span,
432 ..
433 }) => {
434 suggestion.push((span.shrink_to_hi().with_hi(call_span.hi()), sugg));
435 }
436 hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(..), hir_id, .. }) => {
437 suggestion.push((expr.span.shrink_to_lo(), "(".to_string()));
438 if let hir::Node::Expr(parent) = tcx.parent_hir_node(*hir_id)
439 && let hir::ExprKind::If(condition, block, None) = parent.kind
440 && condition.hir_id == *hir_id
441 && let hir::ExprKind::Block(block, _) = block.kind
442 && block.stmts.is_empty()
443 && let Some(expr) = block.expr
444 && let hir::ExprKind::Path(..) = expr.kind
445 {
446 suggestion.push((block.span.shrink_to_hi(), ")".to_string()));
451 } else {
452 suggestion.push((span.shrink_to_hi().with_hi(expr.span.hi()), sugg));
453 }
454 }
455 _ => {
456 suggestion.push((span.shrink_to_hi(), sugg));
457 }
458 }
459
460 err.multipart_suggestion_verbose(descr, suggestion, Applicability::HasPlaceholders);
461 err
462 }
463 Res::Def(DefKind::Variant, _) if expr.is_none() => {
464 err.span_label(span, format!("not a {expected}"));
465
466 let fields = &tcx.expect_variant_res(res).fields.raw;
467 let span = qpath.span().shrink_to_hi().to(span.shrink_to_hi());
468 let (msg, sugg) = if fields.is_empty() {
469 ("use the struct variant pattern syntax".to_string(), " {}".to_string())
470 } else {
471 let msg = format!(
472 "the struct variant's field{s} {are} being ignored",
473 s = pluralize!(fields.len()),
474 are = pluralize!("is", fields.len())
475 );
476 let fields = fields
477 .iter()
478 .map(|field| format!("{}: _", field.ident(tcx)))
479 .collect::<Vec<_>>()
480 .join(", ");
481 let sugg = format!(" {{ {} }}", fields);
482 (msg, sugg)
483 };
484
485 err.span_suggestion_verbose(
486 qpath.span().shrink_to_hi().to(span.shrink_to_hi()),
487 msg,
488 sugg,
489 Applicability::HasPlaceholders,
490 );
491 err
492 }
493 _ => err.with_span_label(span, format!("not a {expected}")),
494 }
495 .emit()
496}
497
498#[derive(Copy, Clone, Eq, PartialEq)]
518enum TupleArgumentsFlag {
519 DontTupleArguments,
520 TupleArguments,
521}
522
523fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! {
524 let dcx = tcx.dcx();
525 let mut diag = dcx.struct_span_bug(
526 span,
527 "It looks like you're trying to break rust; would you like some ICE?",
528 );
529 diag.note("the compiler expectedly panicked. this is a feature.");
530 diag.note(
531 "we would appreciate a joke overview: \
532 https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
533 );
534 diag.note(format!("rustc {} running on {}", tcx.sess.cfg_version, config::host_tuple(),));
535 if let Some((flags, excluded_cargo_defaults)) = rustc_session::utils::extra_compiler_flags() {
536 diag.note(format!("compiler flags: {}", flags.join(" ")));
537 if excluded_cargo_defaults {
538 diag.note("some of the compiler flags provided by cargo are hidden");
539 }
540 }
541 diag.emit()
542}
543
544pub fn provide(providers: &mut Providers) {
546 *providers = Providers {
547 method_autoderef_steps: method::probe::method_autoderef_steps,
548 typeck,
549 used_trait_imports,
550 check_transmutes: intrinsicck::check_transmutes,
551 ..*providers
552 };
553}