]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / compiler / rustc_typeck / src / check / fn_ctxt / checks.rs
1 use crate::astconv::AstConv;
2 use crate::check::coercion::CoerceMany;
3 use crate::check::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error};
4 use crate::check::gather_locals::Declaration;
5 use crate::check::method::MethodCallee;
6 use crate::check::Expectation::*;
7 use crate::check::TupleArgumentsFlag::*;
8 use crate::check::{
9 potentially_plural_count, struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt,
10 LocalTy, Needs, TupleArgumentsFlag,
11 };
12 use crate::structured_errors::StructuredDiagnostic;
13
14 use rustc_ast as ast;
15 use rustc_errors::{Applicability, Diagnostic, DiagnosticId, MultiSpan};
16 use rustc_hir as hir;
17 use rustc_hir::def::{CtorOf, DefKind, Res};
18 use rustc_hir::def_id::DefId;
19 use rustc_hir::{ExprKind, Node, QPath};
20 use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
21 use rustc_infer::infer::InferOk;
22 use rustc_infer::infer::TypeTrace;
23 use rustc_middle::ty::adjustment::AllowTwoPhase;
24 use rustc_middle::ty::error::TypeError;
25 use rustc_middle::ty::fold::TypeFoldable;
26 use rustc_middle::ty::{self, Ty, TyCtxt};
27 use rustc_session::Session;
28 use rustc_span::symbol::Ident;
29 use rustc_span::{self, Span};
30 use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression};
31
32 use std::iter;
33 use std::slice;
34
35 enum TupleMatchFound {
36 None,
37 Single,
38 /// Beginning and end Span
39 Multiple(Span, Span),
40 }
41 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
42 pub(in super::super) fn check_casts(&self) {
43 let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
44 debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
45 for cast in deferred_cast_checks.drain(..) {
46 cast.check(self);
47 }
48 }
49
50 pub(in super::super) fn check_transmutes(&self) {
51 let mut deferred_transmute_checks = self.deferred_transmute_checks.borrow_mut();
52 debug!("FnCtxt::check_transmutes: {} deferred checks", deferred_transmute_checks.len());
53 for (from, to, span) in deferred_transmute_checks.drain(..) {
54 self.check_transmute(span, from, to);
55 }
56 }
57
58 pub(in super::super) fn check_asms(&self) {
59 let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut();
60 debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
61 for (asm, hir_id) in deferred_asm_checks.drain(..) {
62 let enclosing_id = self.tcx.hir().enclosing_body_owner(hir_id);
63 self.check_asm(asm, enclosing_id);
64 }
65 }
66
67 pub(in super::super) fn check_method_argument_types(
68 &self,
69 sp: Span,
70 expr: &'tcx hir::Expr<'tcx>,
71 method: Result<MethodCallee<'tcx>, ()>,
72 args_no_rcvr: &'tcx [hir::Expr<'tcx>],
73 tuple_arguments: TupleArgumentsFlag,
74 expected: Expectation<'tcx>,
75 ) -> Ty<'tcx> {
76 let has_error = match method {
77 Ok(method) => method.substs.references_error() || method.sig.references_error(),
78 Err(_) => true,
79 };
80 if has_error {
81 let err_inputs = self.err_args(args_no_rcvr.len());
82
83 let err_inputs = match tuple_arguments {
84 DontTupleArguments => err_inputs,
85 TupleArguments => vec![self.tcx.intern_tup(&err_inputs)],
86 };
87
88 self.check_argument_types(
89 sp,
90 expr,
91 &err_inputs,
92 None,
93 args_no_rcvr,
94 false,
95 tuple_arguments,
96 None,
97 );
98 return self.tcx.ty_error();
99 }
100
101 let method = method.unwrap();
102 // HACK(eddyb) ignore self in the definition (see above).
103 let expected_input_tys = self.expected_inputs_for_expected_output(
104 sp,
105 expected,
106 method.sig.output(),
107 &method.sig.inputs()[1..],
108 );
109 self.check_argument_types(
110 sp,
111 expr,
112 &method.sig.inputs()[1..],
113 expected_input_tys,
114 args_no_rcvr,
115 method.sig.c_variadic,
116 tuple_arguments,
117 Some(method.def_id),
118 );
119 method.sig.output()
120 }
121
122 /// Generic function that factors out common logic from function calls,
123 /// method calls and overloaded operators.
124 pub(in super::super) fn check_argument_types(
125 &self,
126 // Span enclosing the call site
127 call_span: Span,
128 // Expression of the call site
129 call_expr: &'tcx hir::Expr<'tcx>,
130 // Types (as defined in the *signature* of the target function)
131 formal_input_tys: &[Ty<'tcx>],
132 // More specific expected types, after unifying with caller output types
133 expected_input_tys: Option<Vec<Ty<'tcx>>>,
134 // The expressions for each provided argument
135 provided_args: &'tcx [hir::Expr<'tcx>],
136 // Whether the function is variadic, for example when imported from C
137 c_variadic: bool,
138 // Whether the arguments have been bundled in a tuple (ex: closures)
139 tuple_arguments: TupleArgumentsFlag,
140 // The DefId for the function being called, for better error messages
141 fn_def_id: Option<DefId>,
142 ) {
143 let tcx = self.tcx;
144
145 // Conceptually, we've got some number of expected inputs, and some number of provided aguments
146 // and we can form a grid of whether each argument could satisfy a given input:
147 // in1 | in2 | in3 | ...
148 // arg1 ? | | |
149 // arg2 | ? | |
150 // arg3 | | ? |
151 // ...
152 // Initially, we just check the diagonal, because in the case of correct code
153 // these are the only checks that matter
154 // However, in the unhappy path, we'll fill in this whole grid to attempt to provide
155 // better error messages about invalid method calls.
156
157 // All the input types from the fn signature must outlive the call
158 // so as to validate implied bounds.
159 for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) {
160 self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation);
161 }
162
163 let mut err_code = "E0061";
164
165 // If the arguments should be wrapped in a tuple (ex: closures), unwrap them here
166 let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
167 let tuple_type = self.structurally_resolved_type(call_span, formal_input_tys[0]);
168 match tuple_type.kind() {
169 // We expected a tuple and got a tuple
170 ty::Tuple(arg_types) => {
171 // Argument length differs
172 if arg_types.len() != provided_args.len() {
173 err_code = "E0057";
174 }
175 let expected_input_tys = match expected_input_tys {
176 Some(expected_input_tys) => match expected_input_tys.get(0) {
177 Some(ty) => match ty.kind() {
178 ty::Tuple(tys) => Some(tys.iter().collect()),
179 _ => None,
180 },
181 None => None,
182 },
183 None => None,
184 };
185 (arg_types.iter().collect(), expected_input_tys)
186 }
187 _ => {
188 // Otherwise, there's a mismatch, so clear out what we're expecting, and set
189 // our input types to err_args so we don't blow up the error messages
190 struct_span_err!(
191 tcx.sess,
192 call_span,
193 E0059,
194 "cannot use call notation; the first type parameter \
195 for the function trait is neither a tuple nor unit"
196 )
197 .emit();
198 (self.err_args(provided_args.len()), None)
199 }
200 }
201 } else {
202 (formal_input_tys.to_vec(), expected_input_tys)
203 };
204
205 // If there are no external expectations at the call site, just use the types from the function defn
206 let expected_input_tys = if let Some(expected_input_tys) = expected_input_tys {
207 assert_eq!(expected_input_tys.len(), formal_input_tys.len());
208 expected_input_tys
209 } else {
210 formal_input_tys.clone()
211 };
212
213 let minimum_input_count = expected_input_tys.len();
214 let provided_arg_count = provided_args.len();
215
216 // We'll also want to keep track of the fully coerced argument types, for an awkward hack near the end
217 let mut final_arg_types: Vec<Option<(Ty<'_>, Ty<'_>)>> = vec![None; provided_arg_count];
218
219 // We introduce a helper function to demand that a given argument satisfy a given input
220 // This is more complicated than just checking type equality, as arguments could be coerced
221 // This version writes those types back so further type checking uses the narrowed types
222 let demand_compatible = |idx, final_arg_types: &mut Vec<Option<(Ty<'tcx>, Ty<'tcx>)>>| {
223 let formal_input_ty: Ty<'tcx> = formal_input_tys[idx];
224 let expected_input_ty: Ty<'tcx> = expected_input_tys[idx];
225 let provided_arg = &provided_args[idx];
226
227 debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty);
228
229 // We're on the happy path here, so we'll do a more involved check and write back types
230 // To check compatibility, we'll do 3 things:
231 // 1. Unify the provided argument with the expected type
232 let expectation = Expectation::rvalue_hint(self, expected_input_ty);
233
234 let checked_ty = self.check_expr_with_expectation(provided_arg, expectation);
235
236 // 2. Coerce to the most detailed type that could be coerced
237 // to, which is `expected_ty` if `rvalue_hint` returns an
238 // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
239 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
240
241 // Keep track of these for below
242 final_arg_types[idx] = Some((checked_ty, coerced_ty));
243
244 // Cause selection errors caused by resolving a single argument to point at the
245 // argument and not the call. This lets us customize the span pointed to in the
246 // fulfillment error to be more accurate.
247 let coerced_ty =
248 self.resolve_vars_with_obligations_and_mutate_fulfillment(coerced_ty, |errors| {
249 self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
250 self.point_at_arg_instead_of_call_if_possible(
251 errors,
252 &final_arg_types,
253 call_expr,
254 call_span,
255 provided_args,
256 );
257 });
258
259 // Make sure we store the resolved type
260 final_arg_types[idx] = Some((checked_ty, coerced_ty));
261
262 let coerce_error = self
263 .try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None)
264 .err();
265
266 if coerce_error.is_some() {
267 return Compatibility::Incompatible(coerce_error);
268 }
269
270 // 3. Check if the formal type is a supertype of the checked one
271 // and register any such obligations for future type checks
272 let supertype_error = self
273 .at(&self.misc(provided_arg.span), self.param_env)
274 .sup(formal_input_ty, coerced_ty);
275 let subtyping_error = match supertype_error {
276 Ok(InferOk { obligations, value: () }) => {
277 self.register_predicates(obligations);
278 None
279 }
280 Err(err) => Some(err),
281 };
282
283 // If neither check failed, the types are compatible
284 match subtyping_error {
285 None => Compatibility::Compatible,
286 Some(_) => Compatibility::Incompatible(subtyping_error),
287 }
288 };
289
290 // A "softer" version of the helper above, which checks types without persisting them,
291 // and treats error types differently
292 // This will allow us to "probe" for other argument orders that would likely have been correct
293 let check_compatible = |input_idx, arg_idx| {
294 let formal_input_ty: Ty<'tcx> = formal_input_tys[arg_idx];
295 let expected_input_ty: Ty<'tcx> = expected_input_tys[arg_idx];
296
297 // If either is an error type, we defy the usual convention and consider them to *not* be
298 // coercible. This prevents our error message heuristic from trying to pass errors into
299 // every argument.
300 if formal_input_ty.references_error() || expected_input_ty.references_error() {
301 return Compatibility::Incompatible(None);
302 }
303
304 let provided_arg: &hir::Expr<'tcx> = &provided_args[input_idx];
305 let expectation = Expectation::rvalue_hint(self, expected_input_ty);
306 let already_checked_ty = self.typeck_results.borrow().expr_ty_adjusted_opt(provided_arg);
307 let checked_ty = already_checked_ty.unwrap_or_else(|| self.check_expr(provided_arg));
308
309 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
310 let can_coerce = self.can_coerce(checked_ty, coerced_ty);
311
312 if !can_coerce {
313 return Compatibility::Incompatible(None);
314 }
315
316 let subtyping_result = self
317 .at(&self.misc(provided_arg.span), self.param_env)
318 .sup(formal_input_ty, coerced_ty);
319
320 // Same as above: if either the coerce type or the checked type is an error type,
321 // consider them *not* compatible.
322 let coercible =
323 !coerced_ty.references_error() && !checked_ty.references_error() && can_coerce;
324
325 match (coercible, &subtyping_result) {
326 (true, Ok(_)) => Compatibility::Compatible,
327 _ => Compatibility::Incompatible(subtyping_result.err()),
328 }
329 };
330
331 // To start, we only care "along the diagonal", where we expect every
332 // provided arg to be in the right spot
333 let mut compatibility = vec![Compatibility::Incompatible(None); provided_args.len()];
334
335 // Keep track of whether we *could possibly* be satisfied, i.e. whether we're on the happy path
336 // if the wrong number of arguments were supplied, we CAN'T be satisfied,
337 // and if we're c_variadic, the supplied arguments must be >= the minimum count from the function
338 // otherwise, they need to be identical, because rust doesn't currently support variadic functions
339 let mut call_appears_satisfied = if c_variadic {
340 provided_arg_count >= minimum_input_count
341 } else {
342 provided_arg_count == minimum_input_count
343 };
344
345 // Check the arguments.
346 // We do this in a pretty awful way: first we type-check any arguments
347 // that are not closures, then we type-check the closures. This is so
348 // that we have more information about the types of arguments when we
349 // type-check the functions. This isn't really the right way to do this.
350 for check_closures in [false, true] {
351 // More awful hacks: before we check argument types, try to do
352 // an "opportunistic" trait resolution of any trait bounds on
353 // the call. This helps coercions.
354 if check_closures {
355 self.select_obligations_where_possible(false, |errors| {
356 self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
357 self.point_at_arg_instead_of_call_if_possible(
358 errors,
359 &final_arg_types,
360 call_expr,
361 call_span,
362 &provided_args,
363 );
364 })
365 }
366
367 // Check each argument, to satisfy the input it was provided for
368 // Visually, we're traveling down the diagonal of the compatibility matrix
369 for (idx, arg) in provided_args.iter().enumerate() {
370 // Warn only for the first loop (the "no closures" one).
371 // Closure arguments themselves can't be diverging, but
372 // a previous argument can, e.g., `foo(panic!(), || {})`.
373 if !check_closures {
374 self.warn_if_unreachable(arg.hir_id, arg.span, "expression");
375 }
376
377 // For C-variadic functions, we don't have a declared type for all of
378 // the arguments hence we only do our usual type checking with
379 // the arguments who's types we do know. However, we *can* check
380 // for unreachable expressions (see above).
381 // FIXME: unreachable warning current isn't emitted
382 if idx >= minimum_input_count {
383 continue;
384 }
385
386 let is_closure = matches!(arg.kind, ExprKind::Closure { .. });
387 if is_closure != check_closures {
388 continue;
389 }
390
391 let compatible = demand_compatible(idx, &mut final_arg_types);
392 let is_compatible = matches!(compatible, Compatibility::Compatible);
393 compatibility[idx] = compatible;
394
395 if !is_compatible {
396 call_appears_satisfied = false;
397 }
398 }
399 }
400
401 // Logic here is a bit hairy
402 'errors: {
403 // If something above didn't typecheck, we've fallen off the happy path
404 // and we should make some effort to provide better error messages
405 if call_appears_satisfied {
406 break 'errors;
407 }
408
409 self.set_tainted_by_errors();
410
411 // The algorithm here is inspired by levenshtein distance and longest common subsequence.
412 // We'll try to detect 4 different types of mistakes:
413 // - An extra parameter has been provided that doesn't satisfy *any* of the other inputs
414 // - An input is missing, which isn't satisfied by *any* of the other arguments
415 // - Some number of arguments have been provided in the wrong order
416 // - A type is straight up invalid
417
418 // First, let's find the errors
419 let mut compatibility: Vec<_> = compatibility.into_iter().map(Some).collect();
420 let (mut errors, matched_inputs) =
421 ArgMatrix::new(minimum_input_count, provided_arg_count, |i, j| {
422 if i == j { compatibility[i].take().unwrap() } else { check_compatible(i, j) }
423 })
424 .find_errors();
425
426 // Okay, so here's where it gets complicated in regards to what errors
427 // we emit and how.
428 // There are 3 different "types" of errors we might encounter.
429 // 1) Missing/extra/swapped arguments
430 // 2) Valid but incorrect arguments
431 // 3) Invalid arguments
432 // - Currently I think this only comes up with `CyclicTy`
433 //
434 // We first need to go through, remove those from (3) and emit those
435 // as their own error, particularly since they're error code and
436 // message is special. From what I can tell, we *must* emit these
437 // here (vs somewhere prior to this function) since the arguments
438 // become invalid *because* of how they get used in the function.
439 // It is what it is.
440
441 let found_errors = !errors.is_empty();
442
443 errors.drain_filter(|error| {
444 let Error::Invalid(input_idx, arg_idx, Compatibility::Incompatible(Some(e))) = error else { return false };
445 let expected_ty = expected_input_tys[*arg_idx];
446 let provided_ty = final_arg_types[*input_idx].map(|ty| ty.0).unwrap_or_else(|| tcx.ty_error());
447 let cause = &self.misc(provided_args[*input_idx].span);
448 let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
449 if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
450 self.report_and_explain_type_error(trace, e).emit();
451 return true;
452 }
453 false
454 });
455
456 // We're done if we found errors, but we already emitted them.
457 // I don't think we *should* be able to enter this bit of code
458 // (`!call_appears_satisfied`) without *also* finding errors, but we
459 // don't want to accidentally not emit an error if there is some
460 // logic bug in the `ArgMatrix` code.
461 if found_errors && errors.is_empty() {
462 break 'errors;
463 }
464
465 // Next, let's construct the error
466 let (error_span, full_call_span, ctor_of) = match &call_expr.kind {
467 hir::ExprKind::Call(
468 hir::Expr {
469 span,
470 kind:
471 hir::ExprKind::Path(hir::QPath::Resolved(
472 _,
473 hir::Path { res: Res::Def(DefKind::Ctor(of, _), _), .. },
474 )),
475 ..
476 },
477 _,
478 ) => (call_span, *span, Some(of)),
479 hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None),
480 hir::ExprKind::MethodCall(path_segment, _, span) => {
481 let ident_span = path_segment.ident.span;
482 let ident_span = if let Some(args) = path_segment.args {
483 ident_span.with_hi(args.span_ext.hi())
484 } else {
485 ident_span
486 };
487 (
488 *span, ident_span, None, // methods are never ctors
489 )
490 }
491 k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
492 };
493 let args_span = error_span.trim_start(full_call_span).unwrap_or(error_span);
494 let call_name = match ctor_of {
495 Some(CtorOf::Struct) => "struct",
496 Some(CtorOf::Variant) => "enum variant",
497 None => "function",
498 };
499 if c_variadic && provided_arg_count < minimum_input_count {
500 err_code = "E0060";
501 }
502
503 // Next special case: The case where we expect a single tuple and
504 // wrapping all the args in parentheses (or adding a comma to
505 // already existing parentheses) will result in a tuple that
506 // satisfies the call.
507 // This isn't super ideal code, because we copy code from elsewhere
508 // and somewhat duplicate this. We also delegate to the general type
509 // mismatch suggestions for the single arg case.
510 let sugg_tuple_wrap_args =
511 self.suggested_tuple_wrap(&expected_input_tys, provided_args);
512 match sugg_tuple_wrap_args {
513 TupleMatchFound::None => {}
514 TupleMatchFound::Single => {
515 let expected_ty = expected_input_tys[0];
516 let provided_ty = final_arg_types[0].map(|ty| ty.0).unwrap();
517 let expected_ty = self.resolve_vars_if_possible(expected_ty);
518 let provided_ty = self.resolve_vars_if_possible(provided_ty);
519 let cause = &self.misc(provided_args[0].span);
520 let compatibility = demand_compatible(0, &mut final_arg_types);
521 let type_error = match compatibility {
522 Compatibility::Incompatible(Some(error)) => error,
523 _ => TypeError::Mismatch,
524 };
525 let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
526 let mut err = self.report_and_explain_type_error(trace, &type_error);
527 self.emit_coerce_suggestions(
528 &mut err,
529 &provided_args[0],
530 final_arg_types[0].map(|ty| ty.0).unwrap(),
531 final_arg_types[0].map(|ty| ty.1).unwrap(),
532 None,
533 None,
534 );
535 err.span_label(
536 full_call_span,
537 format!("arguments to this {} are incorrect", call_name),
538 );
539 // Call out where the function is defined
540 label_fn_like(tcx, &mut err, fn_def_id);
541 err.emit();
542 break 'errors;
543 }
544 TupleMatchFound::Multiple(start, end) => {
545 let mut err = tcx.sess.struct_span_err_with_code(
546 full_call_span,
547 &format!(
548 "this {} takes {}{} but {} {} supplied",
549 call_name,
550 if c_variadic { "at least " } else { "" },
551 potentially_plural_count(minimum_input_count, "argument"),
552 potentially_plural_count(provided_arg_count, "argument"),
553 if provided_arg_count == 1 { "was" } else { "were" }
554 ),
555 DiagnosticId::Error(err_code.to_owned()),
556 );
557 // Call out where the function is defined
558 label_fn_like(tcx, &mut err, fn_def_id);
559 err.multipart_suggestion(
560 "use parentheses to construct a tuple",
561 vec![(start, '('.to_string()), (end, ')'.to_string())],
562 Applicability::MachineApplicable,
563 );
564 err.emit();
565 break 'errors;
566 }
567 }
568
569 // Okay, now that we've emitted the special errors separately, we
570 // are only left missing/extra/swapped and mismatched arguments, both
571 // can be collated pretty easily if needed.
572
573 // Next special case: if there is only one "Incompatible" error, just emit that
574 if errors.len() == 1 {
575 if let Some(Error::Invalid(
576 input_idx,
577 arg_idx,
578 Compatibility::Incompatible(Some(error)),
579 )) = errors.iter().next()
580 {
581 let expected_ty = expected_input_tys[*arg_idx];
582 let provided_ty = final_arg_types[*input_idx]
583 .map(|ty| ty.0)
584 .unwrap_or_else(|| tcx.ty_error());
585 let expected_ty = self.resolve_vars_if_possible(expected_ty);
586 let provided_ty = self.resolve_vars_if_possible(provided_ty);
587 let cause = &self.misc(provided_args[*input_idx].span);
588 let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
589 let mut err = self.report_and_explain_type_error(trace, error);
590 self.emit_coerce_suggestions(
591 &mut err,
592 &provided_args[*input_idx],
593 provided_ty,
594 final_arg_types[*input_idx]
595 .map(|ty| ty.1)
596 .unwrap_or_else(|| tcx.ty_error()),
597 None,
598 None,
599 );
600 err.span_label(
601 full_call_span,
602 format!("arguments to this {} are incorrect", call_name),
603 );
604 // Call out where the function is defined
605 label_fn_like(tcx, &mut err, fn_def_id);
606 err.emit();
607 break 'errors;
608 }
609 }
610
611 let mut err = if minimum_input_count == provided_arg_count {
612 struct_span_err!(
613 tcx.sess,
614 full_call_span,
615 E0308,
616 "arguments to this {} are incorrect",
617 call_name,
618 )
619 } else {
620 tcx.sess.struct_span_err_with_code(
621 full_call_span,
622 &format!(
623 "this {} takes {}{} but {} {} supplied",
624 call_name,
625 if c_variadic { "at least " } else { "" },
626 potentially_plural_count(minimum_input_count, "argument"),
627 potentially_plural_count(provided_arg_count, "argument"),
628 if provided_arg_count == 1 { "was" } else { "were" }
629 ),
630 DiagnosticId::Error(err_code.to_owned()),
631 )
632 };
633
634 // As we encounter issues, keep track of what we want to provide for the suggestion
635 let mut labels = vec![];
636 // If there is a single error, we give a specific suggestion; otherwise, we change to
637 // "did you mean" with the suggested function call
638 enum SuggestionText {
639 None,
640 Provide(bool),
641 Remove(bool),
642 Swap,
643 Reorder,
644 DidYouMean,
645 }
646 let mut suggestion_text = SuggestionText::None;
647
648 let mut errors = errors.into_iter().peekable();
649 while let Some(error) = errors.next() {
650 match error {
651 Error::Invalid(input_idx, arg_idx, compatibility) => {
652 let expected_ty = expected_input_tys[arg_idx];
653 let provided_ty = final_arg_types[input_idx]
654 .map(|ty| ty.0)
655 .unwrap_or_else(|| tcx.ty_error());
656 let expected_ty = self.resolve_vars_if_possible(expected_ty);
657 let provided_ty = self.resolve_vars_if_possible(provided_ty);
658 if let Compatibility::Incompatible(error) = &compatibility {
659 let cause = &self.misc(provided_args[input_idx].span);
660 let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
661 if let Some(e) = error {
662 self.note_type_err(
663 &mut err,
664 &trace.cause,
665 None,
666 Some(trace.values),
667 e,
668 false,
669 true,
670 );
671 }
672 }
673
674 self.emit_coerce_suggestions(
675 &mut err,
676 &provided_args[input_idx],
677 provided_ty,
678 // FIXME(compiler-errors): expected_ty?
679 final_arg_types[input_idx]
680 .map(|ty| ty.1)
681 .unwrap_or_else(|| tcx.ty_error()),
682 None,
683 None,
684 );
685 }
686 Error::Extra(arg_idx) => {
687 let arg_type = if let Some((_, ty)) = final_arg_types[arg_idx] {
688 if ty.references_error() || ty.has_infer_types() {
689 "".into()
690 } else {
691 format!(" of type `{}`", ty)
692 }
693 } else {
694 "".into()
695 };
696 labels.push((
697 provided_args[arg_idx].span,
698 format!("argument{} unexpected", arg_type),
699 ));
700 suggestion_text = match suggestion_text {
701 SuggestionText::None => SuggestionText::Remove(false),
702 SuggestionText::Remove(_) => SuggestionText::Remove(true),
703 _ => SuggestionText::DidYouMean,
704 };
705 }
706 Error::Missing(input_idx) => {
707 // If there are multiple missing arguments adjacent to each other,
708 // then we can provide a single error.
709
710 let mut missing_idxs = vec![input_idx];
711 while let Some(e) = errors.next_if(|e| matches!(e, Error::Missing(input_idx) if *input_idx == (missing_idxs.last().unwrap() + 1))) {
712 match e {
713 Error::Missing(input_idx) => missing_idxs.push(input_idx),
714 _ => unreachable!(),
715 }
716 }
717
718 // NOTE: Because we might be re-arranging arguments, might have extra
719 // arguments, etc. it's hard to *really* know where we should provide
720 // this error label, so as a heuristic, we point to the provided arg, or
721 // to the call if the missing inputs pass the provided args.
722 match &missing_idxs[..] {
723 &[input_idx] => {
724 let expected_ty = expected_input_tys[input_idx];
725 let input_ty = self.resolve_vars_if_possible(expected_ty);
726 let span = if input_idx < provided_arg_count {
727 let arg_span = provided_args[input_idx].span;
728 Span::new(arg_span.lo(), arg_span.hi(), arg_span.ctxt(), None)
729 } else {
730 args_span
731 };
732 let arg_type =
733 if input_ty.references_error() || input_ty.has_infer_types() {
734 "".into()
735 } else {
736 format!(" of type `{}`", input_ty)
737 };
738 labels.push((span, format!("an argument{} is missing", arg_type)));
739 suggestion_text = match suggestion_text {
740 SuggestionText::None => SuggestionText::Provide(false),
741 SuggestionText::Provide(_) => SuggestionText::Provide(true),
742 _ => SuggestionText::DidYouMean,
743 };
744 }
745 &[first_idx, second_idx] => {
746 let first_input_ty =
747 self.resolve_vars_if_possible(expected_input_tys[first_idx]);
748 let second_input_ty =
749 self.resolve_vars_if_possible(expected_input_tys[second_idx]);
750
751 let span = if second_idx < provided_arg_count {
752 let first_arg_span = provided_args[first_idx].span;
753 let second_arg_span = provided_args[second_idx].span;
754 Span::new(
755 first_arg_span.lo(),
756 second_arg_span.hi(),
757 first_arg_span.ctxt(),
758 None,
759 )
760 } else {
761 args_span
762 };
763 let any_unnameable = false
764 || first_input_ty.references_error()
765 || first_input_ty.has_infer_types()
766 || second_input_ty.references_error()
767 || second_input_ty.has_infer_types();
768 let arg_type = if any_unnameable {
769 "".into()
770 } else {
771 format!(
772 " of type `{}` and `{}`",
773 first_input_ty, second_input_ty
774 )
775 };
776 labels
777 .push((span, format!("two arguments{} are missing", arg_type)));
778 suggestion_text = match suggestion_text {
779 SuggestionText::None | SuggestionText::Provide(_) => {
780 SuggestionText::Provide(true)
781 }
782 _ => SuggestionText::DidYouMean,
783 };
784 }
785 &[first_idx, second_idx, third_idx] => {
786 let first_input_ty =
787 self.resolve_vars_if_possible(expected_input_tys[first_idx]);
788 let second_input_ty =
789 self.resolve_vars_if_possible(expected_input_tys[second_idx]);
790 let third_input_ty =
791 self.resolve_vars_if_possible(expected_input_tys[third_idx]);
792 let span = if third_idx < provided_arg_count {
793 let first_arg_span = provided_args[first_idx].span;
794 let third_arg_span = provided_args[third_idx].span;
795 Span::new(
796 first_arg_span.lo(),
797 third_arg_span.hi(),
798 first_arg_span.ctxt(),
799 None,
800 )
801 } else {
802 args_span
803 };
804 let any_unnameable = false
805 || first_input_ty.references_error()
806 || first_input_ty.has_infer_types()
807 || second_input_ty.references_error()
808 || second_input_ty.has_infer_types()
809 || third_input_ty.references_error()
810 || third_input_ty.has_infer_types();
811 let arg_type = if any_unnameable {
812 "".into()
813 } else {
814 format!(
815 " of type `{}`, `{}`, and `{}`",
816 first_input_ty, second_input_ty, third_input_ty
817 )
818 };
819 labels.push((
820 span,
821 format!("three arguments{} are missing", arg_type),
822 ));
823 suggestion_text = match suggestion_text {
824 SuggestionText::None | SuggestionText::Provide(_) => {
825 SuggestionText::Provide(true)
826 }
827 _ => SuggestionText::DidYouMean,
828 };
829 }
830 missing_idxs => {
831 let first_idx = *missing_idxs.first().unwrap();
832 let last_idx = *missing_idxs.last().unwrap();
833 // NOTE: Because we might be re-arranging arguments, might have extra arguments, etc.
834 // It's hard to *really* know where we should provide this error label, so this is a
835 // decent heuristic
836 let span = if last_idx < provided_arg_count {
837 let first_arg_span = provided_args[first_idx].span;
838 let last_arg_span = provided_args[last_idx].span;
839 Span::new(
840 first_arg_span.lo(),
841 last_arg_span.hi(),
842 first_arg_span.ctxt(),
843 None,
844 )
845 } else {
846 // Otherwise just label the whole function
847 args_span
848 };
849 labels.push((span, format!("multiple arguments are missing")));
850 suggestion_text = match suggestion_text {
851 SuggestionText::None | SuggestionText::Provide(_) => {
852 SuggestionText::Provide(true)
853 }
854 _ => SuggestionText::DidYouMean,
855 };
856 }
857 }
858 }
859 Error::Swap(input_idx, other_input_idx, arg_idx, other_arg_idx) => {
860 let first_span = provided_args[input_idx].span;
861 let second_span = provided_args[other_input_idx].span;
862
863 let first_expected_ty =
864 self.resolve_vars_if_possible(expected_input_tys[arg_idx]);
865 let first_provided_ty = if let Some((ty, _)) = final_arg_types[input_idx] {
866 format!(", found `{}`", ty)
867 } else {
868 String::new()
869 };
870 labels.push((
871 first_span,
872 format!("expected `{}`{}", first_expected_ty, first_provided_ty),
873 ));
874 let other_expected_ty =
875 self.resolve_vars_if_possible(expected_input_tys[other_arg_idx]);
876 let other_provided_ty =
877 if let Some((ty, _)) = final_arg_types[other_input_idx] {
878 format!(", found `{}`", ty)
879 } else {
880 String::new()
881 };
882 labels.push((
883 second_span,
884 format!("expected `{}`{}", other_expected_ty, other_provided_ty),
885 ));
886 suggestion_text = match suggestion_text {
887 SuggestionText::None => SuggestionText::Swap,
888 _ => SuggestionText::DidYouMean,
889 };
890 }
891 Error::Permutation(args) => {
892 for (dst_arg, dest_input) in args {
893 let expected_ty =
894 self.resolve_vars_if_possible(expected_input_tys[dst_arg]);
895 let provided_ty = if let Some((ty, _)) = final_arg_types[dest_input] {
896 format!(", found `{}`", ty)
897 } else {
898 String::new()
899 };
900 labels.push((
901 provided_args[dest_input].span,
902 format!("expected `{}`{}", expected_ty, provided_ty),
903 ));
904 }
905
906 suggestion_text = match suggestion_text {
907 SuggestionText::None => SuggestionText::Reorder,
908 _ => SuggestionText::DidYouMean,
909 };
910 }
911 }
912 }
913
914 // If we have less than 5 things to say, it would be useful to call out exactly what's wrong
915 if labels.len() <= 5 {
916 for (span, label) in labels {
917 err.span_label(span, label);
918 }
919 }
920
921 // Call out where the function is defined
922 label_fn_like(tcx, &mut err, fn_def_id);
923
924 // And add a suggestion block for all of the parameters
925 let suggestion_text = match suggestion_text {
926 SuggestionText::None => None,
927 SuggestionText::Provide(plural) => {
928 Some(format!("provide the argument{}", if plural { "s" } else { "" }))
929 }
930 SuggestionText::Remove(plural) => {
931 Some(format!("remove the extra argument{}", if plural { "s" } else { "" }))
932 }
933 SuggestionText::Swap => Some("swap these arguments".to_string()),
934 SuggestionText::Reorder => Some("reorder these arguments".to_string()),
935 SuggestionText::DidYouMean => Some("did you mean".to_string()),
936 };
937 if let Some(suggestion_text) = suggestion_text {
938 let source_map = self.sess().source_map();
939 let mut suggestion = format!(
940 "{}(",
941 source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| String::new())
942 );
943 for (arg_index, input_idx) in matched_inputs.iter().enumerate() {
944 let suggestion_text = if let Some(input_idx) = input_idx {
945 let arg_span = provided_args[*input_idx].span.source_callsite();
946 let arg_text = source_map.span_to_snippet(arg_span).unwrap();
947 arg_text
948 } else {
949 // Propose a placeholder of the correct type
950 let expected_ty = expected_input_tys[arg_index];
951 let input_ty = self.resolve_vars_if_possible(expected_ty);
952 if input_ty.is_unit() {
953 "()".to_string()
954 } else if !input_ty.is_ty_var() {
955 format!("/* {} */", input_ty)
956 } else {
957 "/* value */".to_string()
958 }
959 };
960 suggestion += &suggestion_text;
961 if arg_index < minimum_input_count - 1 {
962 suggestion += ", ";
963 }
964 }
965 suggestion += ")";
966 err.span_suggestion_verbose(
967 error_span,
968 &suggestion_text,
969 suggestion,
970 Applicability::HasPlaceholders,
971 );
972 }
973 err.emit();
974 }
975
976 for arg in provided_args.iter().skip(minimum_input_count) {
977 let arg_ty = self.check_expr(&arg);
978
979 // If the function is c-style variadic, we skipped a bunch of arguments
980 // so we need to check those, and write out the types
981 // Ideally this would be folded into the above, for uniform style
982 // but c-variadic is already a corner case
983 if c_variadic {
984 fn variadic_error<'tcx>(
985 sess: &'tcx Session,
986 span: Span,
987 ty: Ty<'tcx>,
988 cast_ty: &str,
989 ) {
990 use crate::structured_errors::MissingCastForVariadicArg;
991
992 MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit();
993 }
994
995 // There are a few types which get autopromoted when passed via varargs
996 // in C but we just error out instead and require explicit casts.
997 let arg_ty = self.structurally_resolved_type(arg.span, arg_ty);
998 match arg_ty.kind() {
999 ty::Float(ty::FloatTy::F32) => {
1000 variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
1001 }
1002 ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => {
1003 variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
1004 }
1005 ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => {
1006 variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
1007 }
1008 ty::FnDef(..) => {
1009 let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx));
1010 let ptr_ty = self.resolve_vars_if_possible(ptr_ty);
1011 variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string());
1012 }
1013 _ => {}
1014 }
1015 }
1016 }
1017 }
1018
1019 fn suggested_tuple_wrap(
1020 &self,
1021 expected_input_tys: &[Ty<'tcx>],
1022 provided_args: &'tcx [hir::Expr<'tcx>],
1023 ) -> TupleMatchFound {
1024 // Only handle the case where we expect only one tuple arg
1025 let [expected_arg_type] = expected_input_tys[..] else { return TupleMatchFound::None };
1026 let &ty::Tuple(expected_types) = self.resolve_vars_if_possible(expected_arg_type).kind()
1027 else { return TupleMatchFound::None };
1028
1029 // First check that there are the same number of types.
1030 if expected_types.len() != provided_args.len() {
1031 return TupleMatchFound::None;
1032 }
1033
1034 let supplied_types: Vec<_> = provided_args.iter().map(|arg| self.check_expr(arg)).collect();
1035
1036 let all_match = iter::zip(expected_types, supplied_types)
1037 .all(|(expected, supplied)| self.can_eq(self.param_env, expected, supplied).is_ok());
1038
1039 if !all_match {
1040 return TupleMatchFound::None;
1041 }
1042 match provided_args {
1043 [] => TupleMatchFound::None,
1044 [_] => TupleMatchFound::Single,
1045 [first, .., last] => {
1046 TupleMatchFound::Multiple(first.span.shrink_to_lo(), last.span.shrink_to_hi())
1047 }
1048 }
1049 }
1050
1051 // AST fragment checking
1052 pub(in super::super) fn check_lit(
1053 &self,
1054 lit: &hir::Lit,
1055 expected: Expectation<'tcx>,
1056 ) -> Ty<'tcx> {
1057 let tcx = self.tcx;
1058
1059 match lit.node {
1060 ast::LitKind::Str(..) => tcx.mk_static_str(),
1061 ast::LitKind::ByteStr(ref v) => {
1062 tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.u8, v.len() as u64))
1063 }
1064 ast::LitKind::Byte(_) => tcx.types.u8,
1065 ast::LitKind::Char(_) => tcx.types.char,
1066 ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => tcx.mk_mach_int(ty::int_ty(t)),
1067 ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => tcx.mk_mach_uint(ty::uint_ty(t)),
1068 ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => {
1069 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1070 ty::Int(_) | ty::Uint(_) => Some(ty),
1071 ty::Char => Some(tcx.types.u8),
1072 ty::RawPtr(..) => Some(tcx.types.usize),
1073 ty::FnDef(..) | ty::FnPtr(_) => Some(tcx.types.usize),
1074 _ => None,
1075 });
1076 opt_ty.unwrap_or_else(|| self.next_int_var())
1077 }
1078 ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => {
1079 tcx.mk_mach_float(ty::float_ty(t))
1080 }
1081 ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => {
1082 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1083 ty::Float(_) => Some(ty),
1084 _ => None,
1085 });
1086 opt_ty.unwrap_or_else(|| self.next_float_var())
1087 }
1088 ast::LitKind::Bool(_) => tcx.types.bool,
1089 ast::LitKind::Err(_) => tcx.ty_error(),
1090 }
1091 }
1092
1093 pub fn check_struct_path(
1094 &self,
1095 qpath: &QPath<'_>,
1096 hir_id: hir::HirId,
1097 ) -> Option<(&'tcx ty::VariantDef, Ty<'tcx>)> {
1098 let path_span = qpath.span();
1099 let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
1100 let variant = match def {
1101 Res::Err => {
1102 self.set_tainted_by_errors();
1103 return None;
1104 }
1105 Res::Def(DefKind::Variant, _) => match ty.kind() {
1106 ty::Adt(adt, substs) => Some((adt.variant_of_res(def), adt.did(), substs)),
1107 _ => bug!("unexpected type: {:?}", ty),
1108 },
1109 Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
1110 | Res::SelfTy { .. } => match ty.kind() {
1111 ty::Adt(adt, substs) if !adt.is_enum() => {
1112 Some((adt.non_enum_variant(), adt.did(), substs))
1113 }
1114 _ => None,
1115 },
1116 _ => bug!("unexpected definition: {:?}", def),
1117 };
1118
1119 if let Some((variant, did, substs)) = variant {
1120 debug!("check_struct_path: did={:?} substs={:?}", did, substs);
1121 self.write_user_type_annotation_from_substs(hir_id, did, substs, None);
1122
1123 // Check bounds on type arguments used in the path.
1124 self.add_required_obligations(path_span, did, substs);
1125
1126 Some((variant, ty))
1127 } else {
1128 match ty.kind() {
1129 ty::Error(_) => {
1130 // E0071 might be caused by a spelling error, which will have
1131 // already caused an error message and probably a suggestion
1132 // elsewhere. Refrain from emitting more unhelpful errors here
1133 // (issue #88844).
1134 }
1135 _ => {
1136 struct_span_err!(
1137 self.tcx.sess,
1138 path_span,
1139 E0071,
1140 "expected struct, variant or union type, found {}",
1141 ty.sort_string(self.tcx)
1142 )
1143 .span_label(path_span, "not a struct")
1144 .emit();
1145 }
1146 }
1147 None
1148 }
1149 }
1150
1151 pub fn check_decl_initializer(
1152 &self,
1153 hir_id: hir::HirId,
1154 pat: &'tcx hir::Pat<'tcx>,
1155 init: &'tcx hir::Expr<'tcx>,
1156 ) -> Ty<'tcx> {
1157 // FIXME(tschottdorf): `contains_explicit_ref_binding()` must be removed
1158 // for #42640 (default match binding modes).
1159 //
1160 // See #44848.
1161 let ref_bindings = pat.contains_explicit_ref_binding();
1162
1163 let local_ty = self.local_ty(init.span, hir_id).revealed_ty;
1164 if let Some(m) = ref_bindings {
1165 // Somewhat subtle: if we have a `ref` binding in the pattern,
1166 // we want to avoid introducing coercions for the RHS. This is
1167 // both because it helps preserve sanity and, in the case of
1168 // ref mut, for soundness (issue #23116). In particular, in
1169 // the latter case, we need to be clear that the type of the
1170 // referent for the reference that results is *equal to* the
1171 // type of the place it is referencing, and not some
1172 // supertype thereof.
1173 let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
1174 self.demand_eqtype(init.span, local_ty, init_ty);
1175 init_ty
1176 } else {
1177 self.check_expr_coercable_to_type(init, local_ty, None)
1178 }
1179 }
1180
1181 pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) {
1182 // Determine and write the type which we'll check the pattern against.
1183 let decl_ty = self.local_ty(decl.span, decl.hir_id).decl_ty;
1184 self.write_ty(decl.hir_id, decl_ty);
1185
1186 // Type check the initializer.
1187 if let Some(ref init) = decl.init {
1188 let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init);
1189 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, init_ty);
1190 }
1191
1192 // Does the expected pattern type originate from an expression and what is the span?
1193 let (origin_expr, ty_span) = match (decl.ty, decl.init) {
1194 (Some(ty), _) => (false, Some(ty.span)), // Bias towards the explicit user type.
1195 (_, Some(init)) => (true, Some(init.span)), // No explicit type; so use the scrutinee.
1196 _ => (false, None), // We have `let $pat;`, so the expected type is unconstrained.
1197 };
1198
1199 // Type check the pattern. Override if necessary to avoid knock-on errors.
1200 self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr);
1201 let pat_ty = self.node_ty(decl.pat.hir_id);
1202 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, pat_ty);
1203 }
1204
1205 /// Type check a `let` statement.
1206 pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) {
1207 self.check_decl(local.into());
1208 }
1209
1210 pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>, is_last: bool) {
1211 // Don't do all the complex logic below for `DeclItem`.
1212 match stmt.kind {
1213 hir::StmtKind::Item(..) => return,
1214 hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
1215 }
1216
1217 self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement");
1218
1219 // Hide the outer diverging and `has_errors` flags.
1220 let old_diverges = self.diverges.replace(Diverges::Maybe);
1221 let old_has_errors = self.has_errors.replace(false);
1222
1223 match stmt.kind {
1224 hir::StmtKind::Local(ref l) => {
1225 self.check_decl_local(&l);
1226 }
1227 // Ignore for now.
1228 hir::StmtKind::Item(_) => {}
1229 hir::StmtKind::Expr(ref expr) => {
1230 // Check with expected type of `()`.
1231 self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit(), |err| {
1232 if expr.can_have_side_effects() {
1233 self.suggest_semicolon_at_end(expr.span, err);
1234 }
1235 });
1236 }
1237 hir::StmtKind::Semi(ref expr) => {
1238 // All of this is equivalent to calling `check_expr`, but it is inlined out here
1239 // in order to capture the fact that this `match` is the last statement in its
1240 // function. This is done for better suggestions to remove the `;`.
1241 let expectation = match expr.kind {
1242 hir::ExprKind::Match(..) if is_last => IsLast(stmt.span),
1243 _ => NoExpectation,
1244 };
1245 self.check_expr_with_expectation(expr, expectation);
1246 }
1247 }
1248
1249 // Combine the diverging and `has_error` flags.
1250 self.diverges.set(self.diverges.get() | old_diverges);
1251 self.has_errors.set(self.has_errors.get() | old_has_errors);
1252 }
1253
1254 pub fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) {
1255 let unit = self.tcx.mk_unit();
1256 let ty = self.check_block_with_expected(blk, ExpectHasType(unit));
1257
1258 // if the block produces a `!` value, that can always be
1259 // (effectively) coerced to unit.
1260 if !ty.is_never() {
1261 self.demand_suptype(blk.span, unit, ty);
1262 }
1263 }
1264
1265 pub(in super::super) fn check_block_with_expected(
1266 &self,
1267 blk: &'tcx hir::Block<'tcx>,
1268 expected: Expectation<'tcx>,
1269 ) -> Ty<'tcx> {
1270 let prev = self.ps.replace(self.ps.get().recurse(blk));
1271
1272 // In some cases, blocks have just one exit, but other blocks
1273 // can be targeted by multiple breaks. This can happen both
1274 // with labeled blocks as well as when we desugar
1275 // a `try { ... }` expression.
1276 //
1277 // Example 1:
1278 //
1279 // 'a: { if true { break 'a Err(()); } Ok(()) }
1280 //
1281 // Here we would wind up with two coercions, one from
1282 // `Err(())` and the other from the tail expression
1283 // `Ok(())`. If the tail expression is omitted, that's a
1284 // "forced unit" -- unless the block diverges, in which
1285 // case we can ignore the tail expression (e.g., `'a: {
1286 // break 'a 22; }` would not force the type of the block
1287 // to be `()`).
1288 let tail_expr = blk.expr.as_ref();
1289 let coerce_to_ty = expected.coercion_target_type(self, blk.span);
1290 let coerce = if blk.targeted_by_break {
1291 CoerceMany::new(coerce_to_ty)
1292 } else {
1293 let tail_expr: &[&hir::Expr<'_>] = match tail_expr {
1294 Some(e) => slice::from_ref(e),
1295 None => &[],
1296 };
1297 CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr)
1298 };
1299
1300 let prev_diverges = self.diverges.get();
1301 let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
1302
1303 let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
1304 for (pos, s) in blk.stmts.iter().enumerate() {
1305 self.check_stmt(s, blk.stmts.len() - 1 == pos);
1306 }
1307
1308 // check the tail expression **without** holding the
1309 // `enclosing_breakables` lock below.
1310 let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
1311
1312 let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
1313 let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
1314 let coerce = ctxt.coerce.as_mut().unwrap();
1315 if let Some(tail_expr_ty) = tail_expr_ty {
1316 let tail_expr = tail_expr.unwrap();
1317 let span = self.get_expr_coercion_span(tail_expr);
1318 let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
1319 let ty_for_diagnostic = coerce.merged_ty();
1320 // We use coerce_inner here because we want to augment the error
1321 // suggesting to wrap the block in square brackets if it might've
1322 // been mistaken array syntax
1323 coerce.coerce_inner(
1324 self,
1325 &cause,
1326 Some(tail_expr),
1327 tail_expr_ty,
1328 Some(&mut |diag: &mut Diagnostic| {
1329 self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
1330 }),
1331 false,
1332 );
1333 } else {
1334 // Subtle: if there is no explicit tail expression,
1335 // that is typically equivalent to a tail expression
1336 // of `()` -- except if the block diverges. In that
1337 // case, there is no value supplied from the tail
1338 // expression (assuming there are no other breaks,
1339 // this implies that the type of the block will be
1340 // `!`).
1341 //
1342 // #41425 -- label the implicit `()` as being the
1343 // "found type" here, rather than the "expected type".
1344 if !self.diverges.get().is_always() {
1345 // #50009 -- Do not point at the entire fn block span, point at the return type
1346 // span, as it is the cause of the requirement, and
1347 // `consider_hint_about_removing_semicolon` will point at the last expression
1348 // if it were a relevant part of the error. This improves usability in editors
1349 // that highlight errors inline.
1350 let mut sp = blk.span;
1351 let mut fn_span = None;
1352 if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) {
1353 let ret_sp = decl.output.span();
1354 if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
1355 // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
1356 // output would otherwise be incorrect and even misleading. Make sure
1357 // the span we're aiming at correspond to a `fn` body.
1358 if block_sp == blk.span {
1359 sp = ret_sp;
1360 fn_span = Some(ident.span);
1361 }
1362 }
1363 }
1364 coerce.coerce_forced_unit(
1365 self,
1366 &self.misc(sp),
1367 &mut |err| {
1368 if let Some(expected_ty) = expected.only_has_type(self) {
1369 self.consider_hint_about_removing_semicolon(blk, expected_ty, err);
1370 if expected_ty == self.tcx.types.bool {
1371 // If this is caused by a missing `let` in a `while let`,
1372 // silence this redundant error, as we already emit E0070.
1373
1374 // Our block must be a `assign desugar local; assignment`
1375 if let Some(hir::Node::Block(hir::Block {
1376 stmts:
1377 [
1378 hir::Stmt {
1379 kind:
1380 hir::StmtKind::Local(hir::Local {
1381 source:
1382 hir::LocalSource::AssignDesugar(_),
1383 ..
1384 }),
1385 ..
1386 },
1387 hir::Stmt {
1388 kind:
1389 hir::StmtKind::Expr(hir::Expr {
1390 kind: hir::ExprKind::Assign(..),
1391 ..
1392 }),
1393 ..
1394 },
1395 ],
1396 ..
1397 })) = self.tcx.hir().find(blk.hir_id)
1398 {
1399 self.comes_from_while_condition(blk.hir_id, |_| {
1400 err.downgrade_to_delayed_bug();
1401 })
1402 }
1403 }
1404 }
1405 if let Some(fn_span) = fn_span {
1406 err.span_label(
1407 fn_span,
1408 "implicitly returns `()` as its body has no tail or `return` \
1409 expression",
1410 );
1411 }
1412 },
1413 false,
1414 );
1415 }
1416 }
1417 });
1418
1419 if ctxt.may_break {
1420 // If we can break from the block, then the block's exit is always reachable
1421 // (... as long as the entry is reachable) - regardless of the tail of the block.
1422 self.diverges.set(prev_diverges);
1423 }
1424
1425 let mut ty = ctxt.coerce.unwrap().complete(self);
1426
1427 if self.has_errors.get() || ty.references_error() {
1428 ty = self.tcx.ty_error()
1429 }
1430
1431 self.write_ty(blk.hir_id, ty);
1432
1433 self.ps.set(prev);
1434 ty
1435 }
1436
1437 /// A common error is to add an extra semicolon:
1438 ///
1439 /// ```compile_fail,E0308
1440 /// fn foo() -> usize {
1441 /// 22;
1442 /// }
1443 /// ```
1444 ///
1445 /// This routine checks if the final statement in a block is an
1446 /// expression with an explicit semicolon whose type is compatible
1447 /// with `expected_ty`. If so, it suggests removing the semicolon.
1448 fn consider_hint_about_removing_semicolon(
1449 &self,
1450 blk: &'tcx hir::Block<'tcx>,
1451 expected_ty: Ty<'tcx>,
1452 err: &mut Diagnostic,
1453 ) {
1454 if let Some((span_semi, boxed)) = self.could_remove_semicolon(blk, expected_ty) {
1455 if let StatementAsExpression::NeedsBoxing = boxed {
1456 err.span_suggestion_verbose(
1457 span_semi,
1458 "consider removing this semicolon and boxing the expression",
1459 "",
1460 Applicability::HasPlaceholders,
1461 );
1462 } else {
1463 err.span_suggestion_short(
1464 span_semi,
1465 "remove this semicolon",
1466 "",
1467 Applicability::MachineApplicable,
1468 );
1469 }
1470 }
1471 }
1472
1473 fn parent_item_span(&self, id: hir::HirId) -> Option<Span> {
1474 let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id));
1475 match node {
1476 Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })
1477 | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
1478 let body = self.tcx.hir().body(body_id);
1479 if let ExprKind::Block(block, _) = &body.value.kind {
1480 return Some(block.span);
1481 }
1482 }
1483 _ => {}
1484 }
1485 None
1486 }
1487
1488 /// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
1489 fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> {
1490 let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id));
1491 self.get_node_fn_decl(parent).map(|(fn_decl, ident, _)| (fn_decl, ident))
1492 }
1493
1494 /// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail
1495 /// expression's `Span`, otherwise return `expr.span`. This is done to give better errors
1496 /// when given code like the following:
1497 /// ```text
1498 /// if false { return 0i32; } else { 1u32 }
1499 /// // ^^^^ point at this instead of the whole `if` expression
1500 /// ```
1501 fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span {
1502 let check_in_progress = |elem: &hir::Expr<'_>| {
1503 self.in_progress_typeck_results
1504 .and_then(|typeck_results| typeck_results.borrow().node_type_opt(elem.hir_id))
1505 .and_then(|ty| {
1506 if ty.is_never() {
1507 None
1508 } else {
1509 Some(match elem.kind {
1510 // Point at the tail expression when possible.
1511 hir::ExprKind::Block(block, _) => {
1512 block.expr.map_or(block.span, |e| e.span)
1513 }
1514 _ => elem.span,
1515 })
1516 }
1517 })
1518 };
1519
1520 if let hir::ExprKind::If(_, _, Some(el)) = expr.kind {
1521 if let Some(rslt) = check_in_progress(el) {
1522 return rslt;
1523 }
1524 }
1525
1526 if let hir::ExprKind::Match(_, arms, _) = expr.kind {
1527 let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body));
1528 if let Some(span) = iter.next() {
1529 if iter.next().is_none() {
1530 return span;
1531 }
1532 }
1533 }
1534
1535 expr.span
1536 }
1537
1538 fn overwrite_local_ty_if_err(
1539 &self,
1540 hir_id: hir::HirId,
1541 pat: &'tcx hir::Pat<'tcx>,
1542 decl_ty: Ty<'tcx>,
1543 ty: Ty<'tcx>,
1544 ) {
1545 if ty.references_error() {
1546 // Override the types everywhere with `err()` to avoid knock on errors.
1547 self.write_ty(hir_id, ty);
1548 self.write_ty(pat.hir_id, ty);
1549 let local_ty = LocalTy { decl_ty, revealed_ty: ty };
1550 self.locals.borrow_mut().insert(hir_id, local_ty);
1551 self.locals.borrow_mut().insert(pat.hir_id, local_ty);
1552 }
1553 }
1554
1555 // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
1556 // The newly resolved definition is written into `type_dependent_defs`.
1557 fn finish_resolving_struct_path(
1558 &self,
1559 qpath: &QPath<'_>,
1560 path_span: Span,
1561 hir_id: hir::HirId,
1562 ) -> (Res, Ty<'tcx>) {
1563 match *qpath {
1564 QPath::Resolved(ref maybe_qself, ref path) => {
1565 let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
1566 let ty = <dyn AstConv<'_>>::res_to_ty(self, self_ty, path, true);
1567 (path.res, ty)
1568 }
1569 QPath::TypeRelative(ref qself, ref segment) => {
1570 let ty = self.to_ty(qself);
1571
1572 let result = <dyn AstConv<'_>>::associated_path_to_ty(
1573 self, hir_id, path_span, ty, qself, segment, true,
1574 );
1575 let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error());
1576 let result = result.map(|(_, kind, def_id)| (kind, def_id));
1577
1578 // Write back the new resolution.
1579 self.write_resolution(hir_id, result);
1580
1581 (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
1582 }
1583 QPath::LangItem(lang_item, span, id) => {
1584 self.resolve_lang_item_path(lang_item, span, hir_id, id)
1585 }
1586 }
1587 }
1588
1589 /// Given a vec of evaluated `FulfillmentError`s and an `fn` call argument expressions, we walk
1590 /// the checked and coerced types for each argument to see if any of the `FulfillmentError`s
1591 /// reference a type argument. The reason to walk also the checked type is that the coerced type
1592 /// can be not easily comparable with predicate type (because of coercion). If the types match
1593 /// for either checked or coerced type, and there's only *one* argument that does, we point at
1594 /// the corresponding argument's expression span instead of the `fn` call path span.
1595 fn point_at_arg_instead_of_call_if_possible(
1596 &self,
1597 errors: &mut Vec<traits::FulfillmentError<'tcx>>,
1598 final_arg_types: &[Option<(Ty<'tcx>, Ty<'tcx>)>],
1599 expr: &'tcx hir::Expr<'tcx>,
1600 call_sp: Span,
1601 args: &'tcx [hir::Expr<'tcx>],
1602 ) {
1603 // We *do not* do this for desugared call spans to keep good diagnostics when involving
1604 // the `?` operator.
1605 if call_sp.desugaring_kind().is_some() {
1606 return;
1607 }
1608
1609 for error in errors {
1610 // Only if the cause is somewhere inside the expression we want try to point at arg.
1611 // Otherwise, it means that the cause is somewhere else and we should not change
1612 // anything because we can break the correct span.
1613 if !call_sp.contains(error.obligation.cause.span) {
1614 continue;
1615 }
1616
1617 // Peel derived obligation, because it's the type that originally
1618 // started this inference chain that matters, not the one we wound
1619 // up with at the end.
1620 fn unpeel_to_top<'a, 'tcx>(
1621 mut code: &'a ObligationCauseCode<'tcx>,
1622 ) -> &'a ObligationCauseCode<'tcx> {
1623 let mut result_code = code;
1624 loop {
1625 let parent = match code {
1626 ObligationCauseCode::ImplDerivedObligation(c) => &c.derived.parent_code,
1627 ObligationCauseCode::BuiltinDerivedObligation(c)
1628 | ObligationCauseCode::DerivedObligation(c) => &c.parent_code,
1629 _ => break result_code,
1630 };
1631 (result_code, code) = (code, parent);
1632 }
1633 }
1634 let self_: ty::subst::GenericArg<'_> = match unpeel_to_top(error.obligation.cause.code()) {
1635 ObligationCauseCode::BuiltinDerivedObligation(code) |
1636 ObligationCauseCode::DerivedObligation(code) => {
1637 code.parent_trait_pred.self_ty().skip_binder().into()
1638 }
1639 ObligationCauseCode::ImplDerivedObligation(code) => {
1640 code.derived.parent_trait_pred.self_ty().skip_binder().into()
1641 }
1642 _ if let ty::PredicateKind::Trait(predicate) =
1643 error.obligation.predicate.kind().skip_binder() => {
1644 predicate.self_ty().into()
1645 }
1646 _ => continue,
1647 };
1648 let self_ = self.resolve_vars_if_possible(self_);
1649
1650 // Collect the argument position for all arguments that could have caused this
1651 // `FulfillmentError`.
1652 let mut referenced_in = final_arg_types
1653 .iter()
1654 .enumerate()
1655 .filter_map(|(i, arg)| match arg {
1656 Some((checked_ty, coerce_ty)) => Some([(i, *checked_ty), (i, *coerce_ty)]),
1657 _ => None,
1658 })
1659 .flatten()
1660 .flat_map(|(i, ty)| {
1661 let ty = self.resolve_vars_if_possible(ty);
1662 // We walk the argument type because the argument's type could have
1663 // been `Option<T>`, but the `FulfillmentError` references `T`.
1664 if ty.walk().any(|arg| arg == self_) { Some(i) } else { None }
1665 })
1666 .collect::<Vec<usize>>();
1667
1668 // Both checked and coerced types could have matched, thus we need to remove
1669 // duplicates.
1670
1671 // We sort primitive type usize here and can use unstable sort
1672 referenced_in.sort_unstable();
1673 referenced_in.dedup();
1674
1675 if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
1676 // Do not point at the inside of a macro.
1677 // That would often result in poor error messages.
1678 if args[ref_in].span.from_expansion() {
1679 return;
1680 }
1681 // We make sure that only *one* argument matches the obligation failure
1682 // and we assign the obligation's span to its expression's.
1683 error.obligation.cause.span = args[ref_in].span;
1684 error.obligation.cause.map_code(|parent_code| {
1685 ObligationCauseCode::FunctionArgumentObligation {
1686 arg_hir_id: args[ref_in].hir_id,
1687 call_hir_id: expr.hir_id,
1688 parent_code,
1689 }
1690 });
1691 } else if error.obligation.cause.span == call_sp {
1692 // Make function calls point at the callee, not the whole thing.
1693 if let hir::ExprKind::Call(callee, _) = expr.kind {
1694 error.obligation.cause.span = callee.span;
1695 }
1696 }
1697 }
1698 }
1699
1700 /// Given a vec of evaluated `FulfillmentError`s and an `fn` call expression, we walk the
1701 /// `PathSegment`s and resolve their type parameters to see if any of the `FulfillmentError`s
1702 /// were caused by them. If they were, we point at the corresponding type argument's span
1703 /// instead of the `fn` call path span.
1704 fn point_at_type_arg_instead_of_call_if_possible(
1705 &self,
1706 errors: &mut Vec<traits::FulfillmentError<'tcx>>,
1707 call_expr: &'tcx hir::Expr<'tcx>,
1708 ) {
1709 if let hir::ExprKind::Call(path, _) = &call_expr.kind {
1710 if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &path.kind {
1711 for error in errors {
1712 if let ty::PredicateKind::Trait(predicate) =
1713 error.obligation.predicate.kind().skip_binder()
1714 {
1715 // If any of the type arguments in this path segment caused the
1716 // `FulfillmentError`, point at its span (#61860).
1717 for arg in path
1718 .segments
1719 .iter()
1720 .filter_map(|seg| seg.args.as_ref())
1721 .flat_map(|a| a.args.iter())
1722 {
1723 if let hir::GenericArg::Type(hir_ty) = &arg {
1724 if let hir::TyKind::Path(hir::QPath::TypeRelative(..)) =
1725 &hir_ty.kind
1726 {
1727 // Avoid ICE with associated types. As this is best
1728 // effort only, it's ok to ignore the case. It
1729 // would trigger in `is_send::<T::AssocType>();`
1730 // from `typeck-default-trait-impl-assoc-type.rs`.
1731 } else {
1732 let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, hir_ty);
1733 let ty = self.resolve_vars_if_possible(ty);
1734 if ty == predicate.self_ty() {
1735 error.obligation.cause.span = hir_ty.span;
1736 }
1737 }
1738 }
1739 }
1740 }
1741 }
1742 }
1743 }
1744 }
1745 }
1746
1747 fn label_fn_like<'tcx>(
1748 tcx: TyCtxt<'tcx>,
1749 err: &mut rustc_errors::DiagnosticBuilder<'tcx, rustc_errors::ErrorGuaranteed>,
1750 def_id: Option<DefId>,
1751 ) {
1752 let Some(def_id) = def_id else {
1753 return;
1754 };
1755
1756 if let Some(def_span) = tcx.def_ident_span(def_id) {
1757 let mut spans: MultiSpan = def_span.into();
1758
1759 let params = tcx
1760 .hir()
1761 .get_if_local(def_id)
1762 .and_then(|node| node.body_id())
1763 .into_iter()
1764 .flat_map(|id| tcx.hir().body(id).params);
1765
1766 for param in params {
1767 spans.push_span_label(param.span, String::new());
1768 }
1769
1770 let def_kind = tcx.def_kind(def_id);
1771 err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
1772 } else {
1773 match tcx.hir().get_if_local(def_id) {
1774 Some(hir::Node::Expr(hir::Expr {
1775 kind: hir::ExprKind::Closure { fn_decl_span, .. },
1776 ..
1777 })) => {
1778 let spans: MultiSpan = (*fn_decl_span).into();
1779
1780 // Note: We don't point to param spans here because they overlap
1781 // with the closure span itself
1782
1783 err.span_note(spans, "closure defined here");
1784 }
1785 _ => {}
1786 }
1787 }
1788 }