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
::*;
9 potentially_plural_count
, struct_span_err
, BreakableCtxt
, Diverges
, Expectation
, FnCtxt
,
10 LocalTy
, Needs
, TupleArgumentsFlag
,
12 use crate::structured_errors
::StructuredDiagnostic
;
15 use rustc_errors
::{Applicability, Diagnostic, DiagnosticId, MultiSpan}
;
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}
;
35 enum TupleMatchFound
{
38 /// Beginning and end Span
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(..) {
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
);
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
);
67 pub(in super::super) fn check_method_argument_types(
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
>,
76 let has_error
= match method
{
77 Ok(method
) => method
.substs
.references_error() || method
.sig
.references_error(),
81 let err_inputs
= self.err_args(args_no_rcvr
.len());
83 let err_inputs
= match tuple_arguments
{
84 DontTupleArguments
=> err_inputs
,
85 TupleArguments
=> vec
![self.tcx
.intern_tup(&err_inputs
)],
88 self.check_argument_types(
98 return self.tcx
.ty_error();
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(
107 &method
.sig
.inputs()[1..],
109 self.check_argument_types(
112 &method
.sig
.inputs()[1..],
115 method
.sig
.c_variadic
,
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(
126 // Span enclosing the call site
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
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
>,
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 | ...
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.
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
);
163 let mut err_code
= "E0061";
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() {
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()),
185 (arg_types
.iter().collect(), expected_input_tys
)
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
194 "cannot use call notation; the first type parameter \
195 for the function trait is neither a tuple nor unit"
198 (self.err_args(provided_args
.len()), None
)
202 (formal_input_tys
.to_vec(), expected_input_tys
)
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());
210 formal_input_tys
.clone()
213 let minimum_input_count
= expected_input_tys
.len();
214 let provided_arg_count
= provided_args
.len();
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
];
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
];
227 debug
!("checking argument {}: {:?} = {:?}", idx
, provided_arg
, formal_input_ty
);
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
);
234 let checked_ty
= self.check_expr_with_expectation(provided_arg
, expectation
);
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
);
241 // Keep track of these for below
242 final_arg_types
[idx
] = Some((checked_ty
, coerced_ty
));
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.
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(
259 // Make sure we store the resolved type
260 final_arg_types
[idx
] = Some((checked_ty
, coerced_ty
));
262 let coerce_error
= self
263 .try_coerce(provided_arg
, checked_ty
, coerced_ty
, AllowTwoPhase
::Yes
, None
)
266 if coerce_error
.is_some() {
267 return Compatibility
::Incompatible(coerce_error
);
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
);
280 Err(err
) => Some(err
),
283 // If neither check failed, the types are compatible
284 match subtyping_error
{
285 None
=> Compatibility
::Compatible
,
286 Some(_
) => Compatibility
::Incompatible(subtyping_error
),
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
];
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
300 if formal_input_ty
.references_error() || expected_input_ty
.references_error() {
301 return Compatibility
::Incompatible(None
);
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
));
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
);
313 return Compatibility
::Incompatible(None
);
316 let subtyping_result
= self
317 .at(&self.misc(provided_arg
.span
), self.param_env
)
318 .sup(formal_input_ty
, coerced_ty
);
320 // Same as above: if either the coerce type or the checked type is an error type,
321 // consider them *not* compatible.
323 !coerced_ty
.references_error() && !checked_ty
.references_error() && can_coerce
;
325 match (coercible
, &subtyping_result
) {
326 (true, Ok(_
)) => Compatibility
::Compatible
,
327 _
=> Compatibility
::Incompatible(subtyping_result
.err()),
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()];
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
342 provided_arg_count
== minimum_input_count
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.
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(
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!(), || {})`.
374 self.warn_if_unreachable(arg
.hir_id
, arg
.span
, "expression");
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
{
386 let is_closure
= matches
!(arg
.kind
, ExprKind
::Closure { .. }
);
387 if is_closure
!= check_closures
{
391 let compatible
= demand_compatible(idx
, &mut final_arg_types
);
392 let is_compatible
= matches
!(compatible
, Compatibility
::Compatible
);
393 compatibility
[idx
] = compatible
;
396 call_appears_satisfied
= false;
401 // Logic here is a bit hairy
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
{
409 self.set_tainted_by_errors();
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
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) }
426 // Okay, so here's where it gets complicated in regards to what errors
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`
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.
441 let found_errors
= !errors
.is_empty();
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();
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() {
465 // Next, let's construct the error
466 let (error_span
, full_call_span
, ctor_of
) = match &call_expr
.kind
{
471 hir
::ExprKind
::Path(hir
::QPath
::Resolved(
473 hir
::Path { res: Res::Def(DefKind::Ctor(of, _), _), .. }
,
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())
488 *span
, ident_span
, None
, // methods are never ctors
491 k
=> span_bug
!(call_span
, "checking argument types on a non-call: `{:?}`", k
),
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",
499 if c_variadic
&& provided_arg_count
< minimum_input_count
{
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
,
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(
530 final_arg_types
[0].map(|ty
| ty
.0).unwrap(),
531 final_arg_types
[0].map(|ty
| ty
.1).unwrap(),
537 format
!("arguments to this {} are incorrect", call_name
),
539 // Call out where the function is defined
540 label_fn_like(tcx
, &mut err
, fn_def_id
);
544 TupleMatchFound
::Multiple(start
, end
) => {
545 let mut err
= tcx
.sess
.struct_span_err_with_code(
548 "this {} takes {}{} but {} {} supplied",
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" }
555 DiagnosticId
::Error(err_code
.to_owned()),
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
,
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.
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(
578 Compatibility
::Incompatible(Some(error
)),
579 )) = errors
.iter().next()
581 let expected_ty
= expected_input_tys
[*arg_idx
];
582 let provided_ty
= final_arg_types
[*input_idx
]
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(
592 &provided_args
[*input_idx
],
594 final_arg_types
[*input_idx
]
596 .unwrap_or_else(|| tcx
.ty_error()),
602 format
!("arguments to this {} are incorrect", call_name
),
604 // Call out where the function is defined
605 label_fn_like(tcx
, &mut err
, fn_def_id
);
611 let mut err
= if minimum_input_count
== provided_arg_count
{
616 "arguments to this {} are incorrect",
620 tcx
.sess
.struct_span_err_with_code(
623 "this {} takes {}{} but {} {} supplied",
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" }
630 DiagnosticId
::Error(err_code
.to_owned()),
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
{
646 let mut suggestion_text
= SuggestionText
::None
;
648 let mut errors
= errors
.into_iter().peekable();
649 while let Some(error
) = errors
.next() {
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
]
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
{
674 self.emit_coerce_suggestions(
676 &provided_args
[input_idx
],
678 // FIXME(compiler-errors): expected_ty?
679 final_arg_types
[input_idx
]
681 .unwrap_or_else(|| tcx
.ty_error()),
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() {
691 format
!(" of type `{}`", ty
)
697 provided_args
[arg_idx
].span
,
698 format
!("argument{} unexpected", arg_type
),
700 suggestion_text
= match suggestion_text
{
701 SuggestionText
::None
=> SuggestionText
::Remove(false),
702 SuggestionText
::Remove(_
) => SuggestionText
::Remove(true),
703 _
=> SuggestionText
::DidYouMean
,
706 Error
::Missing(input_idx
) => {
707 // If there are multiple missing arguments adjacent to each other,
708 // then we can provide a single error.
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))) {
713 Error
::Missing(input_idx
) => missing_idxs
.push(input_idx
),
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
[..] {
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
)
733 if input_ty
.references_error() || input_ty
.has_infer_types() {
736 format
!(" of type `{}`", input_ty
)
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
,
745 &[first_idx
, second_idx
] => {
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
]);
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
;
756 second_arg_span
.hi(),
757 first_arg_span
.ctxt(),
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
{
772 " of type `{}` and `{}`",
773 first_input_ty
, second_input_ty
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)
782 _
=> SuggestionText
::DidYouMean
,
785 &[first_idx
, second_idx
, third_idx
] => {
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
]);
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
;
798 first_arg_span
.ctxt(),
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
{
815 " of type `{}`, `{}`, and `{}`",
816 first_input_ty
, second_input_ty
, third_input_ty
821 format
!("three arguments{} are missing", arg_type
),
823 suggestion_text
= match suggestion_text
{
824 SuggestionText
::None
| SuggestionText
::Provide(_
) => {
825 SuggestionText
::Provide(true)
827 _
=> SuggestionText
::DidYouMean
,
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
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
;
842 first_arg_span
.ctxt(),
846 // Otherwise just label the whole function
849 labels
.push((span
, format
!("multiple arguments are missing")));
850 suggestion_text
= match suggestion_text
{
851 SuggestionText
::None
| SuggestionText
::Provide(_
) => {
852 SuggestionText
::Provide(true)
854 _
=> SuggestionText
::DidYouMean
,
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
;
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
)
872 format
!("expected `{}`{}", first_expected_ty
, first_provided_ty
),
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
)
884 format
!("expected `{}`{}", other_expected_ty
, other_provided_ty
),
886 suggestion_text
= match suggestion_text
{
887 SuggestionText
::None
=> SuggestionText
::Swap
,
888 _
=> SuggestionText
::DidYouMean
,
891 Error
::Permutation(args
) => {
892 for (dst_arg
, dest_input
) in args
{
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
)
901 provided_args
[dest_input
].span
,
902 format
!("expected `{}`{}", expected_ty
, provided_ty
),
906 suggestion_text
= match suggestion_text
{
907 SuggestionText
::None
=> SuggestionText
::Reorder
,
908 _
=> SuggestionText
::DidYouMean
,
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
);
921 // Call out where the function is defined
922 label_fn_like(tcx
, &mut err
, fn_def_id
);
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 { "" }
))
930 SuggestionText
::Remove(plural
) => {
931 Some(format
!("remove the extra argument{}", if plural { "s" }
else { "" }
))
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()),
937 if let Some(suggestion_text
) = suggestion_text
{
938 let source_map
= self.sess().source_map();
939 let mut suggestion
= format
!(
941 source_map
.span_to_snippet(full_call_span
).unwrap_or_else(|_
| String
::new())
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();
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() {
954 } else if !input_ty
.is_ty_var() {
955 format
!("/* {} */", input_ty
)
957 "/* value */".to_string()
960 suggestion
+= &suggestion_text
;
961 if arg_index
< minimum_input_count
- 1 {
966 err
.span_suggestion_verbose(
970 Applicability
::HasPlaceholders
,
976 for arg
in provided_args
.iter().skip(minimum_input_count
) {
977 let arg_ty
= self.check_expr(&arg
);
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
984 fn variadic_error
<'tcx
>(
990 use crate::structured_errors
::MissingCastForVariadicArg
;
992 MissingCastForVariadicArg { sess, span, ty, cast_ty }
.diagnostic().emit();
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");
1002 ty
::Int(ty
::IntTy
::I8
| ty
::IntTy
::I16
) | ty
::Bool
=> {
1003 variadic_error(tcx
.sess
, arg
.span
, arg_ty
, "c_int");
1005 ty
::Uint(ty
::UintTy
::U8
| ty
::UintTy
::U16
) => {
1006 variadic_error(tcx
.sess
, arg
.span
, arg_ty
, "c_uint");
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());
1019 fn suggested_tuple_wrap(
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 }
;
1029 // First check that there are the same number of types.
1030 if expected_types
.len() != provided_args
.len() {
1031 return TupleMatchFound
::None
;
1034 let supplied_types
: Vec
<_
> = provided_args
.iter().map(|arg
| self.check_expr(arg
)).collect();
1036 let all_match
= iter
::zip(expected_types
, supplied_types
)
1037 .all(|(expected
, supplied
)| self.can_eq(self.param_env
, expected
, supplied
).is_ok());
1040 return TupleMatchFound
::None
;
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())
1051 // AST fragment checking
1052 pub(in super::super) fn check_lit(
1055 expected
: Expectation
<'tcx
>,
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))
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),
1076 opt_ty
.unwrap_or_else(|| self.next_int_var())
1078 ast
::LitKind
::Float(_
, ast
::LitFloatType
::Suffixed(t
)) => {
1079 tcx
.mk_mach_float(ty
::float_ty(t
))
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
),
1086 opt_ty
.unwrap_or_else(|| self.next_float_var())
1088 ast
::LitKind
::Bool(_
) => tcx
.types
.bool
,
1089 ast
::LitKind
::Err(_
) => tcx
.ty_error(),
1093 pub fn check_struct_path(
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
{
1102 self.set_tainted_by_errors();
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
),
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
))
1116 _
=> bug
!("unexpected definition: {:?}", def
),
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
);
1123 // Check bounds on type arguments used in the path.
1124 self.add_required_obligations(path_span
, did
, substs
);
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
1140 "expected struct, variant or union type, found {}",
1141 ty
.sort_string(self.tcx
)
1143 .span_label(path_span
, "not a struct")
1151 pub fn check_decl_initializer(
1154 pat
: &'tcx hir
::Pat
<'tcx
>,
1155 init
: &'tcx hir
::Expr
<'tcx
>,
1157 // FIXME(tschottdorf): `contains_explicit_ref_binding()` must be removed
1158 // for #42640 (default match binding modes).
1161 let ref_bindings
= pat
.contains_explicit_ref_binding();
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
);
1177 self.check_expr_coercable_to_type(init
, local_ty
, None
)
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
);
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
);
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.
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
);
1205 /// Type check a `let` statement.
1206 pub fn check_decl_local(&self, local
: &'tcx hir
::Local
<'tcx
>) {
1207 self.check_decl(local
.into());
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`.
1213 hir
::StmtKind
::Item(..) => return,
1214 hir
::StmtKind
::Local(..) | hir
::StmtKind
::Expr(..) | hir
::StmtKind
::Semi(..) => {}
1217 self.warn_if_unreachable(stmt
.hir_id
, stmt
.span
, "statement");
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);
1224 hir
::StmtKind
::Local(ref l
) => {
1225 self.check_decl_local(&l
);
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
);
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
),
1245 self.check_expr_with_expectation(expr
, expectation
);
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
);
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
));
1258 // if the block produces a `!` value, that can always be
1259 // (effectively) coerced to unit.
1261 self.demand_suptype(blk
.span
, unit
, ty
);
1265 pub(in super::super) fn check_block_with_expected(
1267 blk
: &'tcx hir
::Block
<'tcx
>,
1268 expected
: Expectation
<'tcx
>,
1270 let prev
= self.ps
.replace(self.ps
.get().recurse(blk
));
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.
1279 // 'a: { if true { break 'a Err(()); } Ok(()) }
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
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
)
1293 let tail_expr
: &[&hir
::Expr
<'_
>] = match tail_expr
{
1294 Some(e
) => slice
::from_ref(e
),
1297 CoerceMany
::with_coercion_sites(coerce_to_ty
, tail_expr
)
1300 let prev_diverges
= self.diverges
.get();
1301 let ctxt
= BreakableCtxt { coerce: Some(coerce), may_break: false }
;
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
);
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
));
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(
1328 Some(&mut |diag
: &mut Diagnostic
| {
1329 self.suggest_block_to_brackets(diag
, blk
, tail_expr_ty
, ty_for_diagnostic
);
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
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
{
1360 fn_span
= Some(ident
.span
);
1364 coerce
.coerce_forced_unit(
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.
1374 // Our block must be a `assign desugar local; assignment`
1375 if let Some(hir
::Node
::Block(hir
::Block
{
1380 hir
::StmtKind
::Local(hir
::Local
{
1382 hir
::LocalSource
::AssignDesugar(_
),
1389 hir
::StmtKind
::Expr(hir
::Expr
{
1390 kind
: hir
::ExprKind
::Assign(..),
1397 })) = self.tcx
.hir().find(blk
.hir_id
)
1399 self.comes_from_while_condition(blk
.hir_id
, |_
| {
1400 err
.downgrade_to_delayed_bug();
1405 if let Some(fn_span
) = fn_span
{
1408 "implicitly returns `()` as its body has no tail or `return` \
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
);
1425 let mut ty
= ctxt
.coerce
.unwrap().complete(self);
1427 if self.has_errors
.get() || ty
.references_error() {
1428 ty
= self.tcx
.ty_error()
1431 self.write_ty(blk
.hir_id
, ty
);
1437 /// A common error is to add an extra semicolon:
1439 /// ```compile_fail,E0308
1440 /// fn foo() -> usize {
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(
1450 blk
: &'tcx hir
::Block
<'tcx
>,
1451 expected_ty
: Ty
<'tcx
>,
1452 err
: &mut Diagnostic
,
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(
1458 "consider removing this semicolon and boxing the expression",
1460 Applicability
::HasPlaceholders
,
1463 err
.span_suggestion_short(
1465 "remove this semicolon",
1467 Applicability
::MachineApplicable
,
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
));
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
);
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
))
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:
1498 /// if false { return 0i32; } else { 1u32 }
1499 /// // ^^^^ point at this instead of the whole `if` expression
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
))
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
)
1520 if let hir
::ExprKind
::If(_
, _
, Some(el
)) = expr
.kind
{
1521 if let Some(rslt
) = check_in_progress(el
) {
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() {
1538 fn overwrite_local_ty_if_err(
1541 pat
: &'tcx hir
::Pat
<'tcx
>,
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
);
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(
1562 ) -> (Res
, Ty
<'tcx
>) {
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);
1569 QPath
::TypeRelative(ref qself
, ref segment
) => {
1570 let ty
= self.to_ty(qself
);
1572 let result
= <dyn AstConv
<'_
>>::associated_path_to_ty(
1573 self, hir_id
, path_span
, ty
, qself
, segment
, true,
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
));
1578 // Write back the new resolution.
1579 self.write_resolution(hir_id
, result
);
1581 (result
.map_or(Res
::Err
, |(kind
, def_id
)| Res
::Def(kind
, def_id
)), ty
)
1583 QPath
::LangItem(lang_item
, span
, id
) => {
1584 self.resolve_lang_item_path(lang_item
, span
, hir_id
, id
)
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(
1597 errors
: &mut Vec
<traits
::FulfillmentError
<'tcx
>>,
1598 final_arg_types
: &[Option
<(Ty
<'tcx
>, Ty
<'tcx
>)>],
1599 expr
: &'tcx hir
::Expr
<'tcx
>,
1601 args
: &'tcx
[hir
::Expr
<'tcx
>],
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() {
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
) {
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
;
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
,
1631 (result_code
, code
) = (code
, parent
);
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()
1639 ObligationCauseCode
::ImplDerivedObligation(code
) => {
1640 code
.derived
.parent_trait_pred
.self_ty().skip_binder().into()
1642 _
if let ty
::PredicateKind
::Trait(predicate
) =
1643 error
.obligation
.predicate
.kind().skip_binder() => {
1644 predicate
.self_ty().into()
1648 let self_
= self.resolve_vars_if_possible(self_
);
1650 // Collect the argument position for all arguments that could have caused this
1651 // `FulfillmentError`.
1652 let mut referenced_in
= final_arg_types
1655 .filter_map(|(i
, arg
)| match arg
{
1656 Some((checked_ty
, coerce_ty
)) => Some([(i
, *checked_ty
), (i
, *coerce_ty
)]),
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 }
1666 .collect
::<Vec
<usize>>();
1668 // Both checked and coerced types could have matched, thus we need to remove
1671 // We sort primitive type usize here and can use unstable sort
1672 referenced_in
.sort_unstable();
1673 referenced_in
.dedup();
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() {
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
,
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
;
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(
1706 errors
: &mut Vec
<traits
::FulfillmentError
<'tcx
>>,
1707 call_expr
: &'tcx hir
::Expr
<'tcx
>,
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()
1715 // If any of the type arguments in this path segment caused the
1716 // `FulfillmentError`, point at its span (#61860).
1720 .filter_map(|seg
| seg
.args
.as_ref())
1721 .flat_map(|a
| a
.args
.iter())
1723 if let hir
::GenericArg
::Type(hir_ty
) = &arg
{
1724 if let hir
::TyKind
::Path(hir
::QPath
::TypeRelative(..)) =
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`.
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
;
1747 fn label_fn_like
<'tcx
>(
1749 err
: &mut rustc_errors
::DiagnosticBuilder
<'tcx
, rustc_errors
::ErrorGuaranteed
>,
1750 def_id
: Option
<DefId
>,
1752 let Some(def_id
) = def_id
else {
1756 if let Some(def_span
) = tcx
.def_ident_span(def_id
) {
1757 let mut spans
: MultiSpan
= def_span
.into();
1761 .get_if_local(def_id
)
1762 .and_then(|node
| node
.body_id())
1764 .flat_map(|id
| tcx
.hir().body(id
).params
);
1766 for param
in params
{
1767 spans
.push_span_label(param
.span
, String
::new());
1770 let def_kind
= tcx
.def_kind(def_id
);
1771 err
.span_note(spans
, &format
!("{} defined here", def_kind
.descr(def_id
)));
1773 match tcx
.hir().get_if_local(def_id
) {
1774 Some(hir
::Node
::Expr(hir
::Expr
{
1775 kind
: hir
::ExprKind
::Closure { fn_decl_span, .. }
,
1778 let spans
: MultiSpan
= (*fn_decl_span
).into();
1780 // Note: We don't point to param spans here because they overlap
1781 // with the closure span itself
1783 err
.span_note(spans
, "closure defined here");