1 use crate::coercion::CoerceMany; 2 use crate::errors::SuggestPtrNullMut; 3 use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx}; 4 use crate::gather_locals::Declaration; 5 use crate::method::MethodCallee; 6 use crate::TupleArgumentsFlag::*; 7 use crate::{errors, Expectation::*}; 8 use crate::{ 9 struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, Needs, RawTy, TupleArgumentsFlag, 10 }; 11 use rustc_ast as ast; 12 use rustc_data_structures::fx::FxIndexSet; 13 use rustc_errors::{ 14 pluralize, Applicability, Diagnostic, DiagnosticId, ErrorGuaranteed, MultiSpan, 15 }; 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_hir_analysis::astconv::AstConv; 21 use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt; 22 use rustc_hir_analysis::check::potentially_plural_count; 23 use rustc_hir_analysis::structured_errors::StructuredDiagnostic; 24 use rustc_index::IndexVec; 25 use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt}; 26 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; 27 use rustc_infer::infer::TypeTrace; 28 use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; 29 use rustc_middle::ty::adjustment::AllowTwoPhase; 30 use rustc_middle::ty::visit::TypeVisitableExt; 31 use rustc_middle::ty::{self, IsSuggestable, Ty}; 32 use rustc_session::Session; 33 use rustc_span::symbol::{kw, Ident}; 34 use rustc_span::{self, sym, BytePos, Span}; 35 use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}; 36 37 use std::iter; 38 use std::mem; 39 40 impl<'a, 'tcx> FnCtxt<'a, 'tcx> { check_casts(&mut self)41 pub(in super::super) fn check_casts(&mut self) { 42 // don't hold the borrow to deferred_cast_checks while checking to avoid borrow checker errors 43 // when writing to `self.param_env`. 44 let mut deferred_cast_checks = mem::take(&mut *self.deferred_cast_checks.borrow_mut()); 45 46 debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len()); 47 for cast in deferred_cast_checks.drain(..) { 48 let prev_env = self.param_env; 49 self.param_env = self.param_env.with_constness(cast.constness); 50 51 cast.check(self); 52 53 self.param_env = prev_env; 54 } 55 56 *self.deferred_cast_checks.borrow_mut() = deferred_cast_checks; 57 } 58 check_transmutes(&self)59 pub(in super::super) fn check_transmutes(&self) { 60 let mut deferred_transmute_checks = self.deferred_transmute_checks.borrow_mut(); 61 debug!("FnCtxt::check_transmutes: {} deferred checks", deferred_transmute_checks.len()); 62 for (from, to, hir_id) in deferred_transmute_checks.drain(..) { 63 self.check_transmute(from, to, hir_id); 64 } 65 } 66 check_asms(&self)67 pub(in super::super) fn check_asms(&self) { 68 let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut(); 69 debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len()); 70 for (asm, hir_id) in deferred_asm_checks.drain(..) { 71 let enclosing_id = self.tcx.hir().enclosing_body_owner(hir_id); 72 let get_operand_ty = |expr| { 73 let ty = self.typeck_results.borrow().expr_ty_adjusted(expr); 74 let ty = self.resolve_vars_if_possible(ty); 75 if ty.has_non_region_infer() { 76 Ty::new_misc_error(self.tcx) 77 } else { 78 self.tcx.erase_regions(ty) 79 } 80 }; 81 InlineAsmCtxt::new_in_fn(self.tcx, self.param_env, get_operand_ty) 82 .check_asm(asm, enclosing_id); 83 } 84 } 85 check_method_argument_types( &self, sp: Span, expr: &'tcx hir::Expr<'tcx>, method: Result<MethodCallee<'tcx>, ()>, args_no_rcvr: &'tcx [hir::Expr<'tcx>], tuple_arguments: TupleArgumentsFlag, expected: Expectation<'tcx>, ) -> Ty<'tcx>86 pub(in super::super) fn check_method_argument_types( 87 &self, 88 sp: Span, 89 expr: &'tcx hir::Expr<'tcx>, 90 method: Result<MethodCallee<'tcx>, ()>, 91 args_no_rcvr: &'tcx [hir::Expr<'tcx>], 92 tuple_arguments: TupleArgumentsFlag, 93 expected: Expectation<'tcx>, 94 ) -> Ty<'tcx> { 95 let has_error = match method { 96 Ok(method) => method.substs.references_error() || method.sig.references_error(), 97 Err(_) => true, 98 }; 99 if has_error { 100 let err_inputs = self.err_args(args_no_rcvr.len()); 101 102 let err_inputs = match tuple_arguments { 103 DontTupleArguments => err_inputs, 104 TupleArguments => vec![Ty::new_tup(self.tcx, &err_inputs)], 105 }; 106 107 self.check_argument_types( 108 sp, 109 expr, 110 &err_inputs, 111 None, 112 args_no_rcvr, 113 false, 114 tuple_arguments, 115 method.ok().map(|method| method.def_id), 116 ); 117 return Ty::new_misc_error(self.tcx); 118 } 119 120 let method = method.unwrap(); 121 // HACK(eddyb) ignore self in the definition (see above). 122 let expected_input_tys = self.expected_inputs_for_expected_output( 123 sp, 124 expected, 125 method.sig.output(), 126 &method.sig.inputs()[1..], 127 ); 128 self.check_argument_types( 129 sp, 130 expr, 131 &method.sig.inputs()[1..], 132 expected_input_tys, 133 args_no_rcvr, 134 method.sig.c_variadic, 135 tuple_arguments, 136 Some(method.def_id), 137 ); 138 139 method.sig.output() 140 } 141 142 /// Generic function that factors out common logic from function calls, 143 /// method calls and overloaded operators. check_argument_types( &self, call_span: Span, call_expr: &'tcx hir::Expr<'tcx>, formal_input_tys: &[Ty<'tcx>], expected_input_tys: Option<Vec<Ty<'tcx>>>, provided_args: &'tcx [hir::Expr<'tcx>], c_variadic: bool, tuple_arguments: TupleArgumentsFlag, fn_def_id: Option<DefId>, )144 pub(in super::super) fn check_argument_types( 145 &self, 146 // Span enclosing the call site 147 call_span: Span, 148 // Expression of the call site 149 call_expr: &'tcx hir::Expr<'tcx>, 150 // Types (as defined in the *signature* of the target function) 151 formal_input_tys: &[Ty<'tcx>], 152 // More specific expected types, after unifying with caller output types 153 expected_input_tys: Option<Vec<Ty<'tcx>>>, 154 // The expressions for each provided argument 155 provided_args: &'tcx [hir::Expr<'tcx>], 156 // Whether the function is variadic, for example when imported from C 157 c_variadic: bool, 158 // Whether the arguments have been bundled in a tuple (ex: closures) 159 tuple_arguments: TupleArgumentsFlag, 160 // The DefId for the function being called, for better error messages 161 fn_def_id: Option<DefId>, 162 ) { 163 let tcx = self.tcx; 164 165 // Conceptually, we've got some number of expected inputs, and some number of provided arguments 166 // and we can form a grid of whether each argument could satisfy a given input: 167 // in1 | in2 | in3 | ... 168 // arg1 ? | | | 169 // arg2 | ? | | 170 // arg3 | | ? | 171 // ... 172 // Initially, we just check the diagonal, because in the case of correct code 173 // these are the only checks that matter 174 // However, in the unhappy path, we'll fill in this whole grid to attempt to provide 175 // better error messages about invalid method calls. 176 177 // All the input types from the fn signature must outlive the call 178 // so as to validate implied bounds. 179 for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) { 180 self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation); 181 } 182 183 let mut err_code = "E0061"; 184 185 // If the arguments should be wrapped in a tuple (ex: closures), unwrap them here 186 let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments { 187 let tuple_type = self.structurally_resolve_type(call_span, formal_input_tys[0]); 188 match tuple_type.kind() { 189 // We expected a tuple and got a tuple 190 ty::Tuple(arg_types) => { 191 // Argument length differs 192 if arg_types.len() != provided_args.len() { 193 err_code = "E0057"; 194 } 195 let expected_input_tys = match expected_input_tys { 196 Some(expected_input_tys) => match expected_input_tys.get(0) { 197 Some(ty) => match ty.kind() { 198 ty::Tuple(tys) => Some(tys.iter().collect()), 199 _ => None, 200 }, 201 None => None, 202 }, 203 None => None, 204 }; 205 (arg_types.iter().collect(), expected_input_tys) 206 } 207 _ => { 208 // Otherwise, there's a mismatch, so clear out what we're expecting, and set 209 // our input types to err_args so we don't blow up the error messages 210 struct_span_err!( 211 tcx.sess, 212 call_span, 213 E0059, 214 "cannot use call notation; the first type parameter \ 215 for the function trait is neither a tuple nor unit" 216 ) 217 .emit(); 218 (self.err_args(provided_args.len()), None) 219 } 220 } 221 } else { 222 (formal_input_tys.to_vec(), expected_input_tys) 223 }; 224 225 // If there are no external expectations at the call site, just use the types from the function defn 226 let expected_input_tys = if let Some(expected_input_tys) = expected_input_tys { 227 assert_eq!(expected_input_tys.len(), formal_input_tys.len()); 228 expected_input_tys 229 } else { 230 formal_input_tys.clone() 231 }; 232 233 let minimum_input_count = expected_input_tys.len(); 234 let provided_arg_count = provided_args.len(); 235 236 let is_const_eval_select = matches!(fn_def_id, Some(def_id) if 237 self.tcx.def_kind(def_id) == hir::def::DefKind::Fn 238 && self.tcx.is_intrinsic(def_id) 239 && self.tcx.item_name(def_id) == sym::const_eval_select); 240 241 // We introduce a helper function to demand that a given argument satisfy a given input 242 // This is more complicated than just checking type equality, as arguments could be coerced 243 // This version writes those types back so further type checking uses the narrowed types 244 let demand_compatible = |idx| { 245 let formal_input_ty: Ty<'tcx> = formal_input_tys[idx]; 246 let expected_input_ty: Ty<'tcx> = expected_input_tys[idx]; 247 let provided_arg = &provided_args[idx]; 248 249 debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty); 250 251 // We're on the happy path here, so we'll do a more involved check and write back types 252 // To check compatibility, we'll do 3 things: 253 // 1. Unify the provided argument with the expected type 254 let expectation = Expectation::rvalue_hint(self, expected_input_ty); 255 256 let checked_ty = self.check_expr_with_expectation(provided_arg, expectation); 257 258 // 2. Coerce to the most detailed type that could be coerced 259 // to, which is `expected_ty` if `rvalue_hint` returns an 260 // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise. 261 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty); 262 263 // Cause selection errors caused by resolving a single argument to point at the 264 // argument and not the call. This lets us customize the span pointed to in the 265 // fulfillment error to be more accurate. 266 let coerced_ty = self.resolve_vars_with_obligations(coerced_ty); 267 268 let coerce_error = self 269 .try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None) 270 .err(); 271 272 if coerce_error.is_some() { 273 return Compatibility::Incompatible(coerce_error); 274 } 275 276 // Check that second and third argument of `const_eval_select` must be `FnDef`, and additionally that 277 // the second argument must be `const fn`. The first argument must be a tuple, but this is already expressed 278 // in the function signature (`F: FnOnce<ARG>`), so I did not bother to add another check here. 279 // 280 // This check is here because there is currently no way to express a trait bound for `FnDef` types only. 281 if is_const_eval_select && (1..=2).contains(&idx) { 282 if let ty::FnDef(def_id, _) = checked_ty.kind() { 283 if idx == 1 && !self.tcx.is_const_fn_raw(*def_id) { 284 self.tcx 285 .sess 286 .emit_err(errors::ConstSelectMustBeConst { span: provided_arg.span }); 287 } 288 } else { 289 self.tcx.sess.emit_err(errors::ConstSelectMustBeFn { 290 span: provided_arg.span, 291 ty: checked_ty, 292 }); 293 } 294 } 295 296 // 3. Check if the formal type is a supertype of the checked one 297 // and register any such obligations for future type checks 298 let supertype_error = self.at(&self.misc(provided_arg.span), self.param_env).sup( 299 DefineOpaqueTypes::No, 300 formal_input_ty, 301 coerced_ty, 302 ); 303 let subtyping_error = match supertype_error { 304 Ok(InferOk { obligations, value: () }) => { 305 self.register_predicates(obligations); 306 None 307 } 308 Err(err) => Some(err), 309 }; 310 311 // If neither check failed, the types are compatible 312 match subtyping_error { 313 None => Compatibility::Compatible, 314 Some(_) => Compatibility::Incompatible(subtyping_error), 315 } 316 }; 317 318 // To start, we only care "along the diagonal", where we expect every 319 // provided arg to be in the right spot 320 let mut compatibility_diagonal = 321 vec![Compatibility::Incompatible(None); provided_args.len()]; 322 323 // Keep track of whether we *could possibly* be satisfied, i.e. whether we're on the happy path 324 // if the wrong number of arguments were supplied, we CAN'T be satisfied, 325 // and if we're c_variadic, the supplied arguments must be >= the minimum count from the function 326 // otherwise, they need to be identical, because rust doesn't currently support variadic functions 327 let mut call_appears_satisfied = if c_variadic { 328 provided_arg_count >= minimum_input_count 329 } else { 330 provided_arg_count == minimum_input_count 331 }; 332 333 // Check the arguments. 334 // We do this in a pretty awful way: first we type-check any arguments 335 // that are not closures, then we type-check the closures. This is so 336 // that we have more information about the types of arguments when we 337 // type-check the functions. This isn't really the right way to do this. 338 for check_closures in [false, true] { 339 // More awful hacks: before we check argument types, try to do 340 // an "opportunistic" trait resolution of any trait bounds on 341 // the call. This helps coercions. 342 if check_closures { 343 self.select_obligations_where_possible(|_| {}) 344 } 345 346 // Check each argument, to satisfy the input it was provided for 347 // Visually, we're traveling down the diagonal of the compatibility matrix 348 for (idx, arg) in provided_args.iter().enumerate() { 349 // Warn only for the first loop (the "no closures" one). 350 // Closure arguments themselves can't be diverging, but 351 // a previous argument can, e.g., `foo(panic!(), || {})`. 352 if !check_closures { 353 self.warn_if_unreachable(arg.hir_id, arg.span, "expression"); 354 } 355 356 // For C-variadic functions, we don't have a declared type for all of 357 // the arguments hence we only do our usual type checking with 358 // the arguments who's types we do know. However, we *can* check 359 // for unreachable expressions (see above). 360 // FIXME: unreachable warning current isn't emitted 361 if idx >= minimum_input_count { 362 continue; 363 } 364 365 // For this check, we do *not* want to treat async generator closures (async blocks) 366 // as proper closures. Doing so would regress type inference when feeding 367 // the return value of an argument-position async block to an argument-position 368 // closure wrapped in a block. 369 // See <https://github.com/rust-lang/rust/issues/112225>. 370 let is_closure = if let ExprKind::Closure(closure) = arg.kind { 371 !tcx.generator_is_async(closure.def_id.to_def_id()) 372 } else { 373 false 374 }; 375 if is_closure != check_closures { 376 continue; 377 } 378 379 let compatible = demand_compatible(idx); 380 let is_compatible = matches!(compatible, Compatibility::Compatible); 381 compatibility_diagonal[idx] = compatible; 382 383 if !is_compatible { 384 call_appears_satisfied = false; 385 } 386 } 387 } 388 389 if c_variadic && provided_arg_count < minimum_input_count { 390 err_code = "E0060"; 391 } 392 393 for arg in provided_args.iter().skip(minimum_input_count) { 394 // Make sure we've checked this expr at least once. 395 let arg_ty = self.check_expr(&arg); 396 397 // If the function is c-style variadic, we skipped a bunch of arguments 398 // so we need to check those, and write out the types 399 // Ideally this would be folded into the above, for uniform style 400 // but c-variadic is already a corner case 401 if c_variadic { 402 fn variadic_error<'tcx>( 403 sess: &'tcx Session, 404 span: Span, 405 ty: Ty<'tcx>, 406 cast_ty: &str, 407 ) { 408 use rustc_hir_analysis::structured_errors::MissingCastForVariadicArg; 409 410 MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit(); 411 } 412 413 // There are a few types which get autopromoted when passed via varargs 414 // in C but we just error out instead and require explicit casts. 415 let arg_ty = self.structurally_resolve_type(arg.span, arg_ty); 416 match arg_ty.kind() { 417 ty::Float(ty::FloatTy::F32) => { 418 variadic_error(tcx.sess, arg.span, arg_ty, "c_double"); 419 } 420 ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => { 421 variadic_error(tcx.sess, arg.span, arg_ty, "c_int"); 422 } 423 ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => { 424 variadic_error(tcx.sess, arg.span, arg_ty, "c_uint"); 425 } 426 ty::FnDef(..) => { 427 let ptr_ty = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx)); 428 let ptr_ty = self.resolve_vars_if_possible(ptr_ty); 429 variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string()); 430 } 431 _ => {} 432 } 433 } 434 } 435 436 if !call_appears_satisfied { 437 let compatibility_diagonal = IndexVec::from_raw(compatibility_diagonal); 438 let provided_args = IndexVec::from_iter(provided_args.iter().take(if c_variadic { 439 minimum_input_count 440 } else { 441 provided_arg_count 442 })); 443 debug_assert_eq!( 444 formal_input_tys.len(), 445 expected_input_tys.len(), 446 "expected formal_input_tys to be the same size as expected_input_tys" 447 ); 448 let formal_and_expected_inputs = IndexVec::from_iter( 449 formal_input_tys 450 .iter() 451 .copied() 452 .zip(expected_input_tys.iter().copied()) 453 .map(|vars| self.resolve_vars_if_possible(vars)), 454 ); 455 456 self.report_arg_errors( 457 compatibility_diagonal, 458 formal_and_expected_inputs, 459 provided_args, 460 c_variadic, 461 err_code, 462 fn_def_id, 463 call_span, 464 call_expr, 465 ); 466 } 467 } 468 report_arg_errors( &self, compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>, formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>, provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>, c_variadic: bool, err_code: &str, fn_def_id: Option<DefId>, call_span: Span, call_expr: &'tcx hir::Expr<'tcx>, )469 fn report_arg_errors( 470 &self, 471 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>, 472 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>, 473 provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>, 474 c_variadic: bool, 475 err_code: &str, 476 fn_def_id: Option<DefId>, 477 call_span: Span, 478 call_expr: &'tcx hir::Expr<'tcx>, 479 ) { 480 // Next, let's construct the error 481 let (error_span, full_call_span, call_name, is_method) = match &call_expr.kind { 482 hir::ExprKind::Call( 483 hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. }, 484 _, 485 ) => { 486 if let Res::Def(DefKind::Ctor(of, _), _) = 487 self.typeck_results.borrow().qpath_res(qpath, *hir_id) 488 { 489 let name = match of { 490 CtorOf::Struct => "struct", 491 CtorOf::Variant => "enum variant", 492 }; 493 (call_span, *span, name, false) 494 } else { 495 (call_span, *span, "function", false) 496 } 497 } 498 hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, "function", false), 499 hir::ExprKind::MethodCall(path_segment, _, _, span) => { 500 let ident_span = path_segment.ident.span; 501 let ident_span = if let Some(args) = path_segment.args { 502 ident_span.with_hi(args.span_ext.hi()) 503 } else { 504 ident_span 505 }; 506 (*span, ident_span, "method", true) 507 } 508 k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k), 509 }; 510 let args_span = error_span.trim_start(full_call_span).unwrap_or(error_span); 511 512 // Don't print if it has error types or is just plain `_` 513 fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool { 514 tys.into_iter().any(|ty| ty.references_error() || ty.is_ty_var()) 515 } 516 517 let tcx = self.tcx; 518 // FIXME: taint after emitting errors and pass through an `ErrorGuaranteed` 519 self.set_tainted_by_errors( 520 tcx.sess.delay_span_bug(call_span, "no errors reported for args"), 521 ); 522 523 // Get the argument span in the context of the call span so that 524 // suggestions and labels are (more) correct when an arg is a 525 // macro invocation. 526 let normalize_span = |span: Span| -> Span { 527 let normalized_span = span.find_ancestor_inside(error_span).unwrap_or(span); 528 // Sometimes macros mess up the spans, so do not normalize the 529 // arg span to equal the error span, because that's less useful 530 // than pointing out the arg expr in the wrong context. 531 if normalized_span.source_equal(error_span) { span } else { normalized_span } 532 }; 533 534 // Precompute the provided types and spans, since that's all we typically need for below 535 let provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> = provided_args 536 .iter() 537 .map(|expr| { 538 let ty = self 539 .typeck_results 540 .borrow() 541 .expr_ty_adjusted_opt(*expr) 542 .unwrap_or_else(|| Ty::new_misc_error(tcx)); 543 (self.resolve_vars_if_possible(ty), normalize_span(expr.span)) 544 }) 545 .collect(); 546 let callee_expr = match &call_expr.peel_blocks().kind { 547 hir::ExprKind::Call(callee, _) => Some(*callee), 548 hir::ExprKind::MethodCall(_, receiver, ..) => { 549 if let Some((DefKind::AssocFn, def_id)) = 550 self.typeck_results.borrow().type_dependent_def(call_expr.hir_id) 551 && let Some(assoc) = tcx.opt_associated_item(def_id) 552 && assoc.fn_has_self_parameter 553 { 554 Some(*receiver) 555 } else { 556 None 557 } 558 } 559 _ => None, 560 }; 561 let callee_ty = callee_expr 562 .and_then(|callee_expr| self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)); 563 564 // A "softer" version of the `demand_compatible`, which checks types without persisting them, 565 // and treats error types differently 566 // This will allow us to "probe" for other argument orders that would likely have been correct 567 let check_compatible = |provided_idx: ProvidedIdx, expected_idx: ExpectedIdx| { 568 if provided_idx.as_usize() == expected_idx.as_usize() { 569 return compatibility_diagonal[provided_idx].clone(); 570 } 571 572 let (formal_input_ty, expected_input_ty) = formal_and_expected_inputs[expected_idx]; 573 // If either is an error type, we defy the usual convention and consider them to *not* be 574 // coercible. This prevents our error message heuristic from trying to pass errors into 575 // every argument. 576 if (formal_input_ty, expected_input_ty).references_error() { 577 return Compatibility::Incompatible(None); 578 } 579 580 let (arg_ty, arg_span) = provided_arg_tys[provided_idx]; 581 582 let expectation = Expectation::rvalue_hint(self, expected_input_ty); 583 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty); 584 let can_coerce = self.can_coerce(arg_ty, coerced_ty); 585 if !can_coerce { 586 return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts( 587 ty::error::ExpectedFound::new(true, coerced_ty, arg_ty), 588 ))); 589 } 590 591 // Using probe here, since we don't want this subtyping to affect inference. 592 let subtyping_error = self.probe(|_| { 593 self.at(&self.misc(arg_span), self.param_env) 594 .sup(DefineOpaqueTypes::No, formal_input_ty, coerced_ty) 595 .err() 596 }); 597 598 // Same as above: if either the coerce type or the checked type is an error type, 599 // consider them *not* compatible. 600 let references_error = (coerced_ty, arg_ty).references_error(); 601 match (references_error, subtyping_error) { 602 (false, None) => Compatibility::Compatible, 603 (_, subtyping_error) => Compatibility::Incompatible(subtyping_error), 604 } 605 }; 606 607 let mk_trace = |span, (formal_ty, expected_ty), provided_ty| { 608 let mismatched_ty = if expected_ty == provided_ty { 609 // If expected == provided, then we must have failed to sup 610 // the formal type. Avoid printing out "expected Ty, found Ty" 611 // in that case. 612 formal_ty 613 } else { 614 expected_ty 615 }; 616 TypeTrace::types(&self.misc(span), true, mismatched_ty, provided_ty) 617 }; 618 619 // The algorithm here is inspired by levenshtein distance and longest common subsequence. 620 // We'll try to detect 4 different types of mistakes: 621 // - An extra parameter has been provided that doesn't satisfy *any* of the other inputs 622 // - An input is missing, which isn't satisfied by *any* of the other arguments 623 // - Some number of arguments have been provided in the wrong order 624 // - A type is straight up invalid 625 626 // First, let's find the errors 627 let (mut errors, matched_inputs) = 628 ArgMatrix::new(provided_args.len(), formal_and_expected_inputs.len(), check_compatible) 629 .find_errors(); 630 631 // First, check if we just need to wrap some arguments in a tuple. 632 if let Some((mismatch_idx, terr)) = 633 compatibility_diagonal.iter().enumerate().find_map(|(i, c)| { 634 if let Compatibility::Incompatible(Some(terr)) = c { 635 Some((i, *terr)) 636 } else { 637 None 638 } 639 }) 640 { 641 // Is the first bad expected argument a tuple? 642 // Do we have as many extra provided arguments as the tuple's length? 643 // If so, we might have just forgotten to wrap some args in a tuple. 644 if let Some(ty::Tuple(tys)) = 645 formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| tys.1.kind()) 646 // If the tuple is unit, we're not actually wrapping any arguments. 647 && !tys.is_empty() 648 && provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len() 649 { 650 // Wrap up the N provided arguments starting at this position in a tuple. 651 let provided_as_tuple = Ty::new_tup_from_iter(tcx, 652 provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx).take(tys.len()), 653 ); 654 655 let mut satisfied = true; 656 // Check if the newly wrapped tuple + rest of the arguments are compatible. 657 for ((_, expected_ty), provided_ty) in std::iter::zip( 658 formal_and_expected_inputs.iter().skip(mismatch_idx), 659 [provided_as_tuple].into_iter().chain( 660 provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx + tys.len()), 661 ), 662 ) { 663 if !self.can_coerce(provided_ty, *expected_ty) { 664 satisfied = false; 665 break; 666 } 667 } 668 669 // If they're compatible, suggest wrapping in an arg, and we're done! 670 // Take some care with spans, so we don't suggest wrapping a macro's 671 // innards in parenthesis, for example. 672 if satisfied 673 && let Some((_, lo)) = 674 provided_arg_tys.get(ProvidedIdx::from_usize(mismatch_idx)) 675 && let Some((_, hi)) = 676 provided_arg_tys.get(ProvidedIdx::from_usize(mismatch_idx + tys.len() - 1)) 677 { 678 let mut err; 679 if tys.len() == 1 { 680 // A tuple wrap suggestion actually occurs within, 681 // so don't do anything special here. 682 err = self.err_ctxt().report_and_explain_type_error( 683 mk_trace( 684 *lo, 685 formal_and_expected_inputs[mismatch_idx.into()], 686 provided_arg_tys[mismatch_idx.into()].0, 687 ), 688 terr, 689 ); 690 err.span_label( 691 full_call_span, 692 format!("arguments to this {} are incorrect", call_name), 693 ); 694 } else { 695 err = tcx.sess.struct_span_err_with_code( 696 full_call_span, 697 format!( 698 "{call_name} takes {}{} but {} {} supplied", 699 if c_variadic { "at least " } else { "" }, 700 potentially_plural_count( 701 formal_and_expected_inputs.len(), 702 "argument" 703 ), 704 potentially_plural_count(provided_args.len(), "argument"), 705 pluralize!("was", provided_args.len()) 706 ), 707 DiagnosticId::Error(err_code.to_owned()), 708 ); 709 err.multipart_suggestion_verbose( 710 "wrap these arguments in parentheses to construct a tuple", 711 vec![ 712 (lo.shrink_to_lo(), "(".to_string()), 713 (hi.shrink_to_hi(), ")".to_string()), 714 ], 715 Applicability::MachineApplicable, 716 ); 717 }; 718 self.label_fn_like( 719 &mut err, 720 fn_def_id, 721 callee_ty, 722 Some(mismatch_idx), 723 is_method, 724 ); 725 err.emit(); 726 return; 727 } 728 } 729 } 730 731 // Okay, so here's where it gets complicated in regards to what errors 732 // we emit and how. 733 // There are 3 different "types" of errors we might encounter. 734 // 1) Missing/extra/swapped arguments 735 // 2) Valid but incorrect arguments 736 // 3) Invalid arguments 737 // - Currently I think this only comes up with `CyclicTy` 738 // 739 // We first need to go through, remove those from (3) and emit those 740 // as their own error, particularly since they're error code and 741 // message is special. From what I can tell, we *must* emit these 742 // here (vs somewhere prior to this function) since the arguments 743 // become invalid *because* of how they get used in the function. 744 // It is what it is. 745 746 if errors.is_empty() { 747 if cfg!(debug_assertions) { 748 span_bug!(error_span, "expected errors from argument matrix"); 749 } else { 750 tcx.sess.emit_err(errors::ArgMismatchIndeterminate { span: error_span }); 751 } 752 return; 753 } 754 755 errors.retain(|error| { 756 let Error::Invalid( 757 provided_idx, 758 expected_idx, 759 Compatibility::Incompatible(Some(e)), 760 ) = error else { return true }; 761 let (provided_ty, provided_span) = provided_arg_tys[*provided_idx]; 762 let trace = 763 mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty); 764 if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) { 765 self.err_ctxt().report_and_explain_type_error(trace, *e).emit(); 766 return false; 767 } 768 true 769 }); 770 771 // We're done if we found errors, but we already emitted them. 772 if errors.is_empty() { 773 return; 774 } 775 776 // Okay, now that we've emitted the special errors separately, we 777 // are only left missing/extra/swapped and mismatched arguments, both 778 // can be collated pretty easily if needed. 779 780 // Next special case: if there is only one "Incompatible" error, just emit that 781 if let [ 782 Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))), 783 ] = &errors[..] 784 { 785 let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx]; 786 let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx]; 787 let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty); 788 let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err); 789 self.emit_coerce_suggestions( 790 &mut err, 791 &provided_args[*provided_idx], 792 provided_ty, 793 Expectation::rvalue_hint(self, expected_ty) 794 .only_has_type(self) 795 .unwrap_or(formal_ty), 796 None, 797 None, 798 ); 799 err.span_label( 800 full_call_span, 801 format!("arguments to this {} are incorrect", call_name), 802 ); 803 804 if let hir::ExprKind::MethodCall(_, rcvr, _, _) = call_expr.kind 805 && provided_idx.as_usize() == expected_idx.as_usize() 806 { 807 self.note_source_of_type_mismatch_constraint( 808 &mut err, 809 rcvr, 810 crate::demand::TypeMismatchSource::Arg { 811 call_expr, 812 incompatible_arg: provided_idx.as_usize(), 813 }, 814 ); 815 } 816 817 self.suggest_ptr_null_mut( 818 expected_ty, 819 provided_ty, 820 provided_args[*provided_idx], 821 &mut err, 822 ); 823 824 // Call out where the function is defined 825 self.label_fn_like( 826 &mut err, 827 fn_def_id, 828 callee_ty, 829 Some(expected_idx.as_usize()), 830 is_method, 831 ); 832 err.emit(); 833 return; 834 } 835 836 let mut err = if formal_and_expected_inputs.len() == provided_args.len() { 837 struct_span_err!( 838 tcx.sess, 839 full_call_span, 840 E0308, 841 "arguments to this {} are incorrect", 842 call_name, 843 ) 844 } else { 845 tcx.sess.struct_span_err_with_code( 846 full_call_span, 847 format!( 848 "this {} takes {}{} but {} {} supplied", 849 call_name, 850 if c_variadic { "at least " } else { "" }, 851 potentially_plural_count(formal_and_expected_inputs.len(), "argument"), 852 potentially_plural_count(provided_args.len(), "argument"), 853 pluralize!("was", provided_args.len()) 854 ), 855 DiagnosticId::Error(err_code.to_owned()), 856 ) 857 }; 858 859 // As we encounter issues, keep track of what we want to provide for the suggestion 860 let mut labels = vec![]; 861 // If there is a single error, we give a specific suggestion; otherwise, we change to 862 // "did you mean" with the suggested function call 863 enum SuggestionText { 864 None, 865 Provide(bool), 866 Remove(bool), 867 Swap, 868 Reorder, 869 DidYouMean, 870 } 871 let mut suggestion_text = SuggestionText::None; 872 873 let ty_to_snippet = |ty: Ty<'tcx>, expected_idx: ExpectedIdx| { 874 if ty.is_unit() { 875 "()".to_string() 876 } else if ty.is_suggestable(tcx, false) { 877 format!("/* {} */", ty) 878 } else if let Some(fn_def_id) = fn_def_id 879 && self.tcx.def_kind(fn_def_id).is_fn_like() 880 && let self_implicit = 881 matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize 882 && let Some(arg) = self.tcx.fn_arg_names(fn_def_id) 883 .get(expected_idx.as_usize() + self_implicit) 884 && arg.name != kw::SelfLower 885 { 886 format!("/* {} */", arg.name) 887 } else { 888 "/* value */".to_string() 889 } 890 }; 891 892 let mut errors = errors.into_iter().peekable(); 893 let mut only_extras_so_far = errors 894 .peek() 895 .is_some_and(|first| matches!(first, Error::Extra(arg_idx) if arg_idx.index() == 0)); 896 let mut suggestions = vec![]; 897 while let Some(error) = errors.next() { 898 only_extras_so_far &= matches!(error, Error::Extra(_)); 899 900 match error { 901 Error::Invalid(provided_idx, expected_idx, compatibility) => { 902 let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx]; 903 let (provided_ty, provided_span) = provided_arg_tys[provided_idx]; 904 if let Compatibility::Incompatible(error) = compatibility { 905 let trace = mk_trace(provided_span, (formal_ty, expected_ty), provided_ty); 906 if let Some(e) = error { 907 self.err_ctxt().note_type_err( 908 &mut err, 909 &trace.cause, 910 None, 911 Some(trace.values), 912 e, 913 false, 914 true, 915 ); 916 } 917 } 918 919 self.emit_coerce_suggestions( 920 &mut err, 921 &provided_args[provided_idx], 922 provided_ty, 923 Expectation::rvalue_hint(self, expected_ty) 924 .only_has_type(self) 925 .unwrap_or(formal_ty), 926 None, 927 None, 928 ); 929 } 930 Error::Extra(arg_idx) => { 931 let (provided_ty, provided_span) = provided_arg_tys[arg_idx]; 932 let provided_ty_name = if !has_error_or_infer([provided_ty]) { 933 // FIXME: not suggestable, use something else 934 format!(" of type `{}`", provided_ty) 935 } else { 936 "".to_string() 937 }; 938 labels 939 .push((provided_span, format!("unexpected argument{}", provided_ty_name))); 940 let mut span = provided_span; 941 if span.can_be_used_for_suggestions() { 942 if arg_idx.index() > 0 943 && let Some((_, prev)) = provided_arg_tys 944 .get(ProvidedIdx::from_usize(arg_idx.index() - 1) 945 ) { 946 // Include previous comma 947 span = prev.shrink_to_hi().to(span); 948 } 949 950 // Is last argument for deletion in a row starting from the 0-th argument? 951 // Then delete the next comma, so we are not left with `f(, ...)` 952 // 953 // fn f() {} 954 // - f(0, 1,) 955 // + f() 956 if only_extras_so_far 957 && !errors 958 .peek() 959 .is_some_and(|next_error| matches!(next_error, Error::Extra(_))) 960 { 961 let next = provided_arg_tys 962 .get(arg_idx + 1) 963 .map(|&(_, sp)| sp) 964 .unwrap_or_else(|| { 965 // Subtract one to move before `)` 966 call_expr.span.with_lo(call_expr.span.hi() - BytePos(1)) 967 }); 968 969 // Include next comma 970 span = span.until(next); 971 } 972 973 suggestions.push((span, String::new())); 974 975 suggestion_text = match suggestion_text { 976 SuggestionText::None => SuggestionText::Remove(false), 977 SuggestionText::Remove(_) => SuggestionText::Remove(true), 978 _ => SuggestionText::DidYouMean, 979 }; 980 } 981 } 982 Error::Missing(expected_idx) => { 983 // If there are multiple missing arguments adjacent to each other, 984 // then we can provide a single error. 985 986 let mut missing_idxs = vec![expected_idx]; 987 while let Some(e) = errors.next_if(|e| { 988 matches!(e, Error::Missing(next_expected_idx) 989 if *next_expected_idx == *missing_idxs.last().unwrap() + 1) 990 }) { 991 match e { 992 Error::Missing(expected_idx) => missing_idxs.push(expected_idx), 993 _ => unreachable!(), 994 } 995 } 996 997 // NOTE: Because we might be re-arranging arguments, might have extra 998 // arguments, etc. it's hard to *really* know where we should provide 999 // this error label, so as a heuristic, we point to the provided arg, or 1000 // to the call if the missing inputs pass the provided args. 1001 match &missing_idxs[..] { 1002 &[expected_idx] => { 1003 let (_, input_ty) = formal_and_expected_inputs[expected_idx]; 1004 let span = if let Some((_, arg_span)) = 1005 provided_arg_tys.get(expected_idx.to_provided_idx()) 1006 { 1007 *arg_span 1008 } else { 1009 args_span 1010 }; 1011 let rendered = if !has_error_or_infer([input_ty]) { 1012 format!(" of type `{}`", input_ty) 1013 } else { 1014 "".to_string() 1015 }; 1016 labels.push((span, format!("an argument{} is missing", rendered))); 1017 suggestion_text = match suggestion_text { 1018 SuggestionText::None => SuggestionText::Provide(false), 1019 SuggestionText::Provide(_) => SuggestionText::Provide(true), 1020 _ => SuggestionText::DidYouMean, 1021 }; 1022 } 1023 &[first_idx, second_idx] => { 1024 let (_, first_expected_ty) = formal_and_expected_inputs[first_idx]; 1025 let (_, second_expected_ty) = formal_and_expected_inputs[second_idx]; 1026 let span = if let (Some((_, first_span)), Some((_, second_span))) = ( 1027 provided_arg_tys.get(first_idx.to_provided_idx()), 1028 provided_arg_tys.get(second_idx.to_provided_idx()), 1029 ) { 1030 first_span.to(*second_span) 1031 } else { 1032 args_span 1033 }; 1034 let rendered = 1035 if !has_error_or_infer([first_expected_ty, second_expected_ty]) { 1036 format!( 1037 " of type `{}` and `{}`", 1038 first_expected_ty, second_expected_ty 1039 ) 1040 } else { 1041 "".to_string() 1042 }; 1043 labels.push((span, format!("two arguments{} are missing", rendered))); 1044 suggestion_text = match suggestion_text { 1045 SuggestionText::None | SuggestionText::Provide(_) => { 1046 SuggestionText::Provide(true) 1047 } 1048 _ => SuggestionText::DidYouMean, 1049 }; 1050 } 1051 &[first_idx, second_idx, third_idx] => { 1052 let (_, first_expected_ty) = formal_and_expected_inputs[first_idx]; 1053 let (_, second_expected_ty) = formal_and_expected_inputs[second_idx]; 1054 let (_, third_expected_ty) = formal_and_expected_inputs[third_idx]; 1055 let span = if let (Some((_, first_span)), Some((_, third_span))) = ( 1056 provided_arg_tys.get(first_idx.to_provided_idx()), 1057 provided_arg_tys.get(third_idx.to_provided_idx()), 1058 ) { 1059 first_span.to(*third_span) 1060 } else { 1061 args_span 1062 }; 1063 let rendered = if !has_error_or_infer([ 1064 first_expected_ty, 1065 second_expected_ty, 1066 third_expected_ty, 1067 ]) { 1068 format!( 1069 " of type `{}`, `{}`, and `{}`", 1070 first_expected_ty, second_expected_ty, third_expected_ty 1071 ) 1072 } else { 1073 "".to_string() 1074 }; 1075 labels.push((span, format!("three arguments{} are missing", rendered))); 1076 suggestion_text = match suggestion_text { 1077 SuggestionText::None | SuggestionText::Provide(_) => { 1078 SuggestionText::Provide(true) 1079 } 1080 _ => SuggestionText::DidYouMean, 1081 }; 1082 } 1083 missing_idxs => { 1084 let first_idx = *missing_idxs.first().unwrap(); 1085 let last_idx = *missing_idxs.last().unwrap(); 1086 // NOTE: Because we might be re-arranging arguments, might have extra arguments, etc. 1087 // It's hard to *really* know where we should provide this error label, so this is a 1088 // decent heuristic 1089 let span = if let (Some((_, first_span)), Some((_, last_span))) = ( 1090 provided_arg_tys.get(first_idx.to_provided_idx()), 1091 provided_arg_tys.get(last_idx.to_provided_idx()), 1092 ) { 1093 first_span.to(*last_span) 1094 } else { 1095 args_span 1096 }; 1097 labels.push((span, "multiple arguments are missing".to_string())); 1098 suggestion_text = match suggestion_text { 1099 SuggestionText::None | SuggestionText::Provide(_) => { 1100 SuggestionText::Provide(true) 1101 } 1102 _ => SuggestionText::DidYouMean, 1103 }; 1104 } 1105 } 1106 } 1107 Error::Swap( 1108 first_provided_idx, 1109 second_provided_idx, 1110 first_expected_idx, 1111 second_expected_idx, 1112 ) => { 1113 let (first_provided_ty, first_span) = provided_arg_tys[first_provided_idx]; 1114 let (_, first_expected_ty) = formal_and_expected_inputs[first_expected_idx]; 1115 let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) { 1116 format!(", found `{}`", first_provided_ty) 1117 } else { 1118 String::new() 1119 }; 1120 labels.push(( 1121 first_span, 1122 format!("expected `{}`{}", first_expected_ty, first_provided_ty_name), 1123 )); 1124 1125 let (second_provided_ty, second_span) = provided_arg_tys[second_provided_idx]; 1126 let (_, second_expected_ty) = formal_and_expected_inputs[second_expected_idx]; 1127 let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) { 1128 format!(", found `{}`", second_provided_ty) 1129 } else { 1130 String::new() 1131 }; 1132 labels.push(( 1133 second_span, 1134 format!("expected `{}`{}", second_expected_ty, second_provided_ty_name), 1135 )); 1136 1137 suggestion_text = match suggestion_text { 1138 SuggestionText::None => SuggestionText::Swap, 1139 _ => SuggestionText::DidYouMean, 1140 }; 1141 } 1142 Error::Permutation(args) => { 1143 for (dst_arg, dest_input) in args { 1144 let (_, expected_ty) = formal_and_expected_inputs[dst_arg]; 1145 let (provided_ty, provided_span) = provided_arg_tys[dest_input]; 1146 let provided_ty_name = if !has_error_or_infer([provided_ty]) { 1147 format!(", found `{}`", provided_ty) 1148 } else { 1149 String::new() 1150 }; 1151 labels.push(( 1152 provided_span, 1153 format!("expected `{}`{}", expected_ty, provided_ty_name), 1154 )); 1155 } 1156 1157 suggestion_text = match suggestion_text { 1158 SuggestionText::None => SuggestionText::Reorder, 1159 _ => SuggestionText::DidYouMean, 1160 }; 1161 } 1162 } 1163 } 1164 1165 // Incorporate the argument changes in the removal suggestion. 1166 // When a type is *missing*, and the rest are additional, we want to suggest these with a 1167 // multipart suggestion, but in order to do so we need to figure out *where* the arg that 1168 // was provided but had the wrong type should go, because when looking at `expected_idx` 1169 // that is the position in the argument list in the definition, while `provided_idx` will 1170 // not be present. So we have to look at what the *last* provided position was, and point 1171 // one after to suggest the replacement. FIXME(estebank): This is hacky, and there's 1172 // probably a better more involved change we can make to make this work. 1173 // For example, if we have 1174 // ``` 1175 // fn foo(i32, &'static str) {} 1176 // foo((), (), ()); 1177 // ``` 1178 // what should be suggested is 1179 // ``` 1180 // foo(/* i32 */, /* &str */); 1181 // ``` 1182 // which includes the replacement of the first two `()` for the correct type, and the 1183 // removal of the last `()`. 1184 let mut prev = -1; 1185 for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() { 1186 // We want to point not at the *current* argument expression index, but rather at the 1187 // index position where it *should have been*, which is *after* the previous one. 1188 if let Some(provided_idx) = provided_idx { 1189 prev = provided_idx.index() as i64; 1190 continue; 1191 } 1192 let idx = ProvidedIdx::from_usize((prev + 1) as usize); 1193 if let Some((_, arg_span)) = provided_arg_tys.get(idx) { 1194 prev += 1; 1195 // There is a type that was *not* found anywhere, so it isn't a move, but a 1196 // replacement and we look at what type it should have been. This will allow us 1197 // To suggest a multipart suggestion when encountering `foo(1, "")` where the def 1198 // was `fn foo(())`. 1199 let (_, expected_ty) = formal_and_expected_inputs[expected_idx]; 1200 suggestions.push((*arg_span, ty_to_snippet(expected_ty, expected_idx))); 1201 } 1202 } 1203 1204 // If we have less than 5 things to say, it would be useful to call out exactly what's wrong 1205 if labels.len() <= 5 { 1206 for (span, label) in labels { 1207 err.span_label(span, label); 1208 } 1209 } 1210 1211 // Call out where the function is defined 1212 self.label_fn_like(&mut err, fn_def_id, callee_ty, None, is_method); 1213 1214 // And add a suggestion block for all of the parameters 1215 let suggestion_text = match suggestion_text { 1216 SuggestionText::None => None, 1217 SuggestionText::Provide(plural) => { 1218 Some(format!("provide the argument{}", if plural { "s" } else { "" })) 1219 } 1220 SuggestionText::Remove(plural) => { 1221 err.multipart_suggestion( 1222 format!("remove the extra argument{}", if plural { "s" } else { "" }), 1223 suggestions, 1224 Applicability::HasPlaceholders, 1225 ); 1226 None 1227 } 1228 SuggestionText::Swap => Some("swap these arguments".to_string()), 1229 SuggestionText::Reorder => Some("reorder these arguments".to_string()), 1230 SuggestionText::DidYouMean => Some("did you mean".to_string()), 1231 }; 1232 if let Some(suggestion_text) = suggestion_text { 1233 let source_map = self.sess().source_map(); 1234 let (mut suggestion, suggestion_span) = 1235 if let Some(call_span) = full_call_span.find_ancestor_inside(error_span) { 1236 ("(".to_string(), call_span.shrink_to_hi().to(error_span.shrink_to_hi())) 1237 } else { 1238 ( 1239 format!( 1240 "{}(", 1241 source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| { 1242 fn_def_id.map_or("".to_string(), |fn_def_id| { 1243 tcx.item_name(fn_def_id).to_string() 1244 }) 1245 }) 1246 ), 1247 error_span, 1248 ) 1249 }; 1250 let mut needs_comma = false; 1251 for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() { 1252 if needs_comma { 1253 suggestion += ", "; 1254 } else { 1255 needs_comma = true; 1256 } 1257 let suggestion_text = if let Some(provided_idx) = provided_idx 1258 && let (_, provided_span) = provided_arg_tys[*provided_idx] 1259 && let Ok(arg_text) = source_map.span_to_snippet(provided_span) 1260 { 1261 arg_text 1262 } else { 1263 // Propose a placeholder of the correct type 1264 let (_, expected_ty) = formal_and_expected_inputs[expected_idx]; 1265 ty_to_snippet(expected_ty, expected_idx) 1266 }; 1267 suggestion += &suggestion_text; 1268 } 1269 suggestion += ")"; 1270 err.span_suggestion_verbose( 1271 suggestion_span, 1272 suggestion_text, 1273 suggestion, 1274 Applicability::HasPlaceholders, 1275 ); 1276 } 1277 1278 err.emit(); 1279 } 1280 suggest_ptr_null_mut( &self, expected_ty: Ty<'tcx>, provided_ty: Ty<'tcx>, arg: &hir::Expr<'tcx>, err: &mut rustc_errors::DiagnosticBuilder<'tcx, ErrorGuaranteed>, )1281 fn suggest_ptr_null_mut( 1282 &self, 1283 expected_ty: Ty<'tcx>, 1284 provided_ty: Ty<'tcx>, 1285 arg: &hir::Expr<'tcx>, 1286 err: &mut rustc_errors::DiagnosticBuilder<'tcx, ErrorGuaranteed>, 1287 ) { 1288 if let ty::RawPtr(ty::TypeAndMut { mutbl: hir::Mutability::Mut, .. }) = expected_ty.kind() 1289 && let ty::RawPtr(ty::TypeAndMut { mutbl: hir::Mutability::Not, .. }) = provided_ty.kind() 1290 && let hir::ExprKind::Call(callee, _) = arg.kind 1291 && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = callee.kind 1292 && let Res::Def(_, def_id) = path.res 1293 && self.tcx.get_diagnostic_item(sym::ptr_null) == Some(def_id) 1294 { 1295 // The user provided `ptr::null()`, but the function expects 1296 // `ptr::null_mut()`. 1297 err.subdiagnostic(SuggestPtrNullMut { 1298 span: arg.span 1299 }); 1300 } 1301 } 1302 1303 // AST fragment checking check_lit( &self, lit: &hir::Lit, expected: Expectation<'tcx>, ) -> Ty<'tcx>1304 pub(in super::super) fn check_lit( 1305 &self, 1306 lit: &hir::Lit, 1307 expected: Expectation<'tcx>, 1308 ) -> Ty<'tcx> { 1309 let tcx = self.tcx; 1310 1311 match lit.node { 1312 ast::LitKind::Str(..) => Ty::new_static_str(tcx), 1313 ast::LitKind::ByteStr(ref v, _) => Ty::new_imm_ref( 1314 tcx, 1315 tcx.lifetimes.re_static, 1316 Ty::new_array(tcx, tcx.types.u8, v.len() as u64), 1317 ), 1318 ast::LitKind::Byte(_) => tcx.types.u8, 1319 ast::LitKind::Char(_) => tcx.types.char, 1320 ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => Ty::new_int(tcx, ty::int_ty(t)), 1321 ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => Ty::new_uint(tcx, ty::uint_ty(t)), 1322 ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => { 1323 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() { 1324 ty::Int(_) | ty::Uint(_) => Some(ty), 1325 ty::Char => Some(tcx.types.u8), 1326 ty::RawPtr(..) => Some(tcx.types.usize), 1327 ty::FnDef(..) | ty::FnPtr(_) => Some(tcx.types.usize), 1328 _ => None, 1329 }); 1330 opt_ty.unwrap_or_else(|| self.next_int_var()) 1331 } 1332 ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => { 1333 Ty::new_float(tcx, ty::float_ty(t)) 1334 } 1335 ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => { 1336 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() { 1337 ty::Float(_) => Some(ty), 1338 _ => None, 1339 }); 1340 opt_ty.unwrap_or_else(|| self.next_float_var()) 1341 } 1342 ast::LitKind::Bool(_) => tcx.types.bool, 1343 ast::LitKind::CStr(_, _) => Ty::new_imm_ref( 1344 tcx, 1345 tcx.lifetimes.re_static, 1346 tcx.type_of(tcx.require_lang_item(hir::LangItem::CStr, Some(lit.span))) 1347 .skip_binder(), 1348 ), 1349 ast::LitKind::Err => Ty::new_misc_error(tcx), 1350 } 1351 } 1352 check_struct_path( &self, qpath: &QPath<'_>, hir_id: hir::HirId, ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed>1353 pub fn check_struct_path( 1354 &self, 1355 qpath: &QPath<'_>, 1356 hir_id: hir::HirId, 1357 ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> { 1358 let path_span = qpath.span(); 1359 let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id); 1360 let variant = match def { 1361 Res::Err => { 1362 let guar = 1363 self.tcx.sess.delay_span_bug(path_span, "`Res::Err` but no error emitted"); 1364 self.set_tainted_by_errors(guar); 1365 return Err(guar); 1366 } 1367 Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() { 1368 Some(adt) => { 1369 Some((adt.variant_of_res(def), adt.did(), Self::user_substs_for_adt(ty))) 1370 } 1371 _ => bug!("unexpected type: {:?}", ty.normalized), 1372 }, 1373 Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _) 1374 | Res::SelfTyParam { .. } 1375 | Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() { 1376 Some(adt) if !adt.is_enum() => { 1377 Some((adt.non_enum_variant(), adt.did(), Self::user_substs_for_adt(ty))) 1378 } 1379 _ => None, 1380 }, 1381 _ => bug!("unexpected definition: {:?}", def), 1382 }; 1383 1384 if let Some((variant, did, ty::UserSubsts { substs, user_self_ty })) = variant { 1385 debug!("check_struct_path: did={:?} substs={:?}", did, substs); 1386 1387 // Register type annotation. 1388 self.write_user_type_annotation_from_substs(hir_id, did, substs, user_self_ty); 1389 1390 // Check bounds on type arguments used in the path. 1391 self.add_required_obligations_for_hir(path_span, did, substs, hir_id); 1392 1393 Ok((variant, ty.normalized)) 1394 } else { 1395 Err(match *ty.normalized.kind() { 1396 ty::Error(guar) => { 1397 // E0071 might be caused by a spelling error, which will have 1398 // already caused an error message and probably a suggestion 1399 // elsewhere. Refrain from emitting more unhelpful errors here 1400 // (issue #88844). 1401 guar 1402 } 1403 _ => struct_span_err!( 1404 self.tcx.sess, 1405 path_span, 1406 E0071, 1407 "expected struct, variant or union type, found {}", 1408 ty.normalized.sort_string(self.tcx) 1409 ) 1410 .span_label(path_span, "not a struct") 1411 .emit(), 1412 }) 1413 } 1414 } 1415 check_decl_initializer( &self, hir_id: hir::HirId, pat: &'tcx hir::Pat<'tcx>, init: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx>1416 pub fn check_decl_initializer( 1417 &self, 1418 hir_id: hir::HirId, 1419 pat: &'tcx hir::Pat<'tcx>, 1420 init: &'tcx hir::Expr<'tcx>, 1421 ) -> Ty<'tcx> { 1422 // FIXME(tschottdorf): `contains_explicit_ref_binding()` must be removed 1423 // for #42640 (default match binding modes). 1424 // 1425 // See #44848. 1426 let ref_bindings = pat.contains_explicit_ref_binding(); 1427 1428 let local_ty = self.local_ty(init.span, hir_id); 1429 if let Some(m) = ref_bindings { 1430 // Somewhat subtle: if we have a `ref` binding in the pattern, 1431 // we want to avoid introducing coercions for the RHS. This is 1432 // both because it helps preserve sanity and, in the case of 1433 // ref mut, for soundness (issue #23116). In particular, in 1434 // the latter case, we need to be clear that the type of the 1435 // referent for the reference that results is *equal to* the 1436 // type of the place it is referencing, and not some 1437 // supertype thereof. 1438 let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m)); 1439 if let Some(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) { 1440 self.emit_type_mismatch_suggestions( 1441 &mut diag, 1442 init.peel_drop_temps(), 1443 init_ty, 1444 local_ty, 1445 None, 1446 None, 1447 ); 1448 diag.emit(); 1449 } 1450 init_ty 1451 } else { 1452 self.check_expr_coercible_to_type(init, local_ty, None) 1453 } 1454 } 1455 check_decl(&self, decl: Declaration<'tcx>)1456 pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) { 1457 // Determine and write the type which we'll check the pattern against. 1458 let decl_ty = self.local_ty(decl.span, decl.hir_id); 1459 self.write_ty(decl.hir_id, decl_ty); 1460 1461 // Type check the initializer. 1462 if let Some(ref init) = decl.init { 1463 let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init); 1464 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty); 1465 } 1466 1467 // Does the expected pattern type originate from an expression and what is the span? 1468 let (origin_expr, ty_span) = match (decl.ty, decl.init) { 1469 (Some(ty), _) => (None, Some(ty.span)), // Bias towards the explicit user type. 1470 (_, Some(init)) => { 1471 (Some(init), Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span))) 1472 } // No explicit type; so use the scrutinee. 1473 _ => (None, None), // We have `let $pat;`, so the expected type is unconstrained. 1474 }; 1475 1476 // Type check the pattern. Override if necessary to avoid knock-on errors. 1477 self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr); 1478 let pat_ty = self.node_ty(decl.pat.hir_id); 1479 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty); 1480 1481 if let Some(blk) = decl.els { 1482 let previous_diverges = self.diverges.get(); 1483 let else_ty = self.check_block_with_expected(blk, NoExpectation); 1484 let cause = self.cause(blk.span, ObligationCauseCode::LetElse); 1485 if let Some(mut err) = 1486 self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty) 1487 { 1488 err.emit(); 1489 } 1490 self.diverges.set(previous_diverges); 1491 } 1492 } 1493 1494 /// Type check a `let` statement. check_decl_local(&self, local: &'tcx hir::Local<'tcx>)1495 pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) { 1496 self.check_decl(local.into()); 1497 } 1498 check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>, is_last: bool)1499 pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>, is_last: bool) { 1500 // Don't do all the complex logic below for `DeclItem`. 1501 match stmt.kind { 1502 hir::StmtKind::Item(..) => return, 1503 hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {} 1504 } 1505 1506 self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement"); 1507 1508 // Hide the outer diverging and `has_errors` flags. 1509 let old_diverges = self.diverges.replace(Diverges::Maybe); 1510 1511 match stmt.kind { 1512 hir::StmtKind::Local(l) => { 1513 self.check_decl_local(l); 1514 } 1515 // Ignore for now. 1516 hir::StmtKind::Item(_) => {} 1517 hir::StmtKind::Expr(ref expr) => { 1518 // Check with expected type of `()`. 1519 self.check_expr_has_type_or_error(&expr, Ty::new_unit(self.tcx), |err| { 1520 if expr.can_have_side_effects() { 1521 self.suggest_semicolon_at_end(expr.span, err); 1522 } 1523 }); 1524 } 1525 hir::StmtKind::Semi(ref expr) => { 1526 // All of this is equivalent to calling `check_expr`, but it is inlined out here 1527 // in order to capture the fact that this `match` is the last statement in its 1528 // function. This is done for better suggestions to remove the `;`. 1529 let expectation = match expr.kind { 1530 hir::ExprKind::Match(..) if is_last => IsLast(stmt.span), 1531 _ => NoExpectation, 1532 }; 1533 self.check_expr_with_expectation(expr, expectation); 1534 } 1535 } 1536 1537 // Combine the diverging and `has_error` flags. 1538 self.diverges.set(self.diverges.get() | old_diverges); 1539 } 1540 check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>)1541 pub fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) { 1542 let unit = Ty::new_unit(self.tcx); 1543 let ty = self.check_block_with_expected(blk, ExpectHasType(unit)); 1544 1545 // if the block produces a `!` value, that can always be 1546 // (effectively) coerced to unit. 1547 if !ty.is_never() { 1548 self.demand_suptype(blk.span, unit, ty); 1549 } 1550 } 1551 check_block_with_expected( &self, blk: &'tcx hir::Block<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx>1552 pub(in super::super) fn check_block_with_expected( 1553 &self, 1554 blk: &'tcx hir::Block<'tcx>, 1555 expected: Expectation<'tcx>, 1556 ) -> Ty<'tcx> { 1557 // In some cases, blocks have just one exit, but other blocks 1558 // can be targeted by multiple breaks. This can happen both 1559 // with labeled blocks as well as when we desugar 1560 // a `try { ... }` expression. 1561 // 1562 // Example 1: 1563 // 1564 // 'a: { if true { break 'a Err(()); } Ok(()) } 1565 // 1566 // Here we would wind up with two coercions, one from 1567 // `Err(())` and the other from the tail expression 1568 // `Ok(())`. If the tail expression is omitted, that's a 1569 // "forced unit" -- unless the block diverges, in which 1570 // case we can ignore the tail expression (e.g., `'a: { 1571 // break 'a 22; }` would not force the type of the block 1572 // to be `()`). 1573 let coerce_to_ty = expected.coercion_target_type(self, blk.span); 1574 let coerce = if blk.targeted_by_break { 1575 CoerceMany::new(coerce_to_ty) 1576 } else { 1577 CoerceMany::with_coercion_sites(coerce_to_ty, blk.expr.as_slice()) 1578 }; 1579 1580 let prev_diverges = self.diverges.get(); 1581 let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false }; 1582 1583 let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || { 1584 for (pos, s) in blk.stmts.iter().enumerate() { 1585 self.check_stmt(s, blk.stmts.len() - 1 == pos); 1586 } 1587 1588 // check the tail expression **without** holding the 1589 // `enclosing_breakables` lock below. 1590 let tail_expr_ty = 1591 blk.expr.map(|expr| (expr, self.check_expr_with_expectation(expr, expected))); 1592 1593 let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); 1594 let ctxt = enclosing_breakables.find_breakable(blk.hir_id); 1595 let coerce = ctxt.coerce.as_mut().unwrap(); 1596 if let Some((tail_expr, tail_expr_ty)) = tail_expr_ty { 1597 let span = self.get_expr_coercion_span(tail_expr); 1598 let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id)); 1599 let ty_for_diagnostic = coerce.merged_ty(); 1600 // We use coerce_inner here because we want to augment the error 1601 // suggesting to wrap the block in square brackets if it might've 1602 // been mistaken array syntax 1603 coerce.coerce_inner( 1604 self, 1605 &cause, 1606 Some(tail_expr), 1607 tail_expr_ty, 1608 Some(&mut |diag: &mut Diagnostic| { 1609 self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic); 1610 }), 1611 false, 1612 ); 1613 } else { 1614 // Subtle: if there is no explicit tail expression, 1615 // that is typically equivalent to a tail expression 1616 // of `()` -- except if the block diverges. In that 1617 // case, there is no value supplied from the tail 1618 // expression (assuming there are no other breaks, 1619 // this implies that the type of the block will be 1620 // `!`). 1621 // 1622 // #41425 -- label the implicit `()` as being the 1623 // "found type" here, rather than the "expected type". 1624 if !self.diverges.get().is_always() { 1625 // #50009 -- Do not point at the entire fn block span, point at the return type 1626 // span, as it is the cause of the requirement, and 1627 // `consider_hint_about_removing_semicolon` will point at the last expression 1628 // if it were a relevant part of the error. This improves usability in editors 1629 // that highlight errors inline. 1630 let mut sp = blk.span; 1631 let mut fn_span = None; 1632 if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) { 1633 let ret_sp = decl.output.span(); 1634 if let Some(block_sp) = self.parent_item_span(blk.hir_id) { 1635 // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the 1636 // output would otherwise be incorrect and even misleading. Make sure 1637 // the span we're aiming at correspond to a `fn` body. 1638 if block_sp == blk.span { 1639 sp = ret_sp; 1640 fn_span = Some(ident.span); 1641 } 1642 } 1643 } 1644 coerce.coerce_forced_unit( 1645 self, 1646 &self.misc(sp), 1647 &mut |err| { 1648 if let Some(expected_ty) = expected.only_has_type(self) { 1649 if blk.stmts.is_empty() && blk.expr.is_none() { 1650 self.suggest_boxing_when_appropriate( 1651 err, 1652 blk.span, 1653 blk.hir_id, 1654 expected_ty, 1655 Ty::new_unit(self.tcx), 1656 ); 1657 } 1658 if !self.consider_removing_semicolon(blk, expected_ty, err) { 1659 self.err_ctxt().consider_returning_binding( 1660 blk, 1661 expected_ty, 1662 err, 1663 ); 1664 } 1665 if expected_ty == self.tcx.types.bool { 1666 // If this is caused by a missing `let` in a `while let`, 1667 // silence this redundant error, as we already emit E0070. 1668 1669 // Our block must be a `assign desugar local; assignment` 1670 if let hir::Block { 1671 stmts: 1672 [ 1673 hir::Stmt { 1674 kind: 1675 hir::StmtKind::Local(hir::Local { 1676 source: 1677 hir::LocalSource::AssignDesugar(_), 1678 .. 1679 }), 1680 .. 1681 }, 1682 hir::Stmt { 1683 kind: 1684 hir::StmtKind::Expr(hir::Expr { 1685 kind: hir::ExprKind::Assign(lhs, ..), 1686 .. 1687 }), 1688 .. 1689 }, 1690 ], 1691 .. 1692 } = blk 1693 { 1694 self.comes_from_while_condition(blk.hir_id, |_| { 1695 // We cannot suppress the error if the LHS of assignment 1696 // is a syntactic place expression because E0070 would 1697 // not be emitted by `check_lhs_assignable`. 1698 let res = self.typeck_results.borrow().expr_ty_opt(lhs); 1699 1700 if !lhs.is_syntactic_place_expr() 1701 || res.references_error() 1702 { 1703 err.downgrade_to_delayed_bug(); 1704 } 1705 }) 1706 } 1707 } 1708 } 1709 if let Some(fn_span) = fn_span { 1710 err.span_label( 1711 fn_span, 1712 "implicitly returns `()` as its body has no tail or `return` \ 1713 expression", 1714 ); 1715 } 1716 }, 1717 false, 1718 ); 1719 } 1720 } 1721 }); 1722 1723 if ctxt.may_break { 1724 // If we can break from the block, then the block's exit is always reachable 1725 // (... as long as the entry is reachable) - regardless of the tail of the block. 1726 self.diverges.set(prev_diverges); 1727 } 1728 1729 let ty = ctxt.coerce.unwrap().complete(self); 1730 1731 self.write_ty(blk.hir_id, ty); 1732 1733 ty 1734 } 1735 parent_item_span(&self, id: hir::HirId) -> Option<Span>1736 fn parent_item_span(&self, id: hir::HirId) -> Option<Span> { 1737 let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id).def_id); 1738 match node { 1739 Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) 1740 | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => { 1741 let body = self.tcx.hir().body(body_id); 1742 if let ExprKind::Block(block, _) = &body.value.kind { 1743 return Some(block.span); 1744 } 1745 } 1746 _ => {} 1747 } 1748 None 1749 } 1750 1751 /// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise. get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)>1752 fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> { 1753 let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id); 1754 self.get_node_fn_decl(parent).map(|(_, fn_decl, ident, _)| (fn_decl, ident)) 1755 } 1756 1757 /// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail 1758 /// expression's `Span`, otherwise return `expr.span`. This is done to give better errors 1759 /// when given code like the following: 1760 /// ```text 1761 /// if false { return 0i32; } else { 1u32 } 1762 /// // ^^^^ point at this instead of the whole `if` expression 1763 /// ``` get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span1764 fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span { 1765 let check_in_progress = |elem: &hir::Expr<'_>| { 1766 self.typeck_results.borrow().node_type_opt(elem.hir_id).filter(|ty| !ty.is_never()).map( 1767 |_| match elem.kind { 1768 // Point at the tail expression when possible. 1769 hir::ExprKind::Block(block, _) => block.expr.map_or(block.span, |e| e.span), 1770 _ => elem.span, 1771 }, 1772 ) 1773 }; 1774 1775 if let hir::ExprKind::If(_, _, Some(el)) = expr.kind { 1776 if let Some(rslt) = check_in_progress(el) { 1777 return rslt; 1778 } 1779 } 1780 1781 if let hir::ExprKind::Match(_, arms, _) = expr.kind { 1782 let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body)); 1783 if let Some(span) = iter.next() { 1784 if iter.next().is_none() { 1785 return span; 1786 } 1787 } 1788 } 1789 1790 expr.span 1791 } 1792 overwrite_local_ty_if_err( &self, hir_id: hir::HirId, pat: &'tcx hir::Pat<'tcx>, ty: Ty<'tcx>, )1793 fn overwrite_local_ty_if_err( 1794 &self, 1795 hir_id: hir::HirId, 1796 pat: &'tcx hir::Pat<'tcx>, 1797 ty: Ty<'tcx>, 1798 ) { 1799 if let Err(guar) = ty.error_reported() { 1800 // Override the types everywhere with `err()` to avoid knock on errors. 1801 let err = Ty::new_error(self.tcx, guar); 1802 self.write_ty(hir_id, err); 1803 self.write_ty(pat.hir_id, err); 1804 self.locals.borrow_mut().insert(hir_id, err); 1805 self.locals.borrow_mut().insert(pat.hir_id, err); 1806 } 1807 } 1808 1809 // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary. 1810 // The newly resolved definition is written into `type_dependent_defs`. finish_resolving_struct_path( &self, qpath: &QPath<'_>, path_span: Span, hir_id: hir::HirId, ) -> (Res, RawTy<'tcx>)1811 fn finish_resolving_struct_path( 1812 &self, 1813 qpath: &QPath<'_>, 1814 path_span: Span, 1815 hir_id: hir::HirId, 1816 ) -> (Res, RawTy<'tcx>) { 1817 match *qpath { 1818 QPath::Resolved(ref maybe_qself, ref path) => { 1819 let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw); 1820 let ty = self.astconv().res_to_ty(self_ty, path, hir_id, true); 1821 (path.res, self.handle_raw_ty(path_span, ty)) 1822 } 1823 QPath::TypeRelative(ref qself, ref segment) => { 1824 let ty = self.to_ty(qself); 1825 1826 let result = self 1827 .astconv() 1828 .associated_path_to_ty(hir_id, path_span, ty.raw, qself, segment, true); 1829 let ty = result 1830 .map(|(ty, _, _)| ty) 1831 .unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar)); 1832 let ty = self.handle_raw_ty(path_span, ty); 1833 let result = result.map(|(_, kind, def_id)| (kind, def_id)); 1834 1835 // Write back the new resolution. 1836 self.write_resolution(hir_id, result); 1837 1838 (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty) 1839 } 1840 QPath::LangItem(lang_item, span, id) => { 1841 let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id, id); 1842 (res, self.handle_raw_ty(path_span, ty)) 1843 } 1844 } 1845 } 1846 1847 /// Given a vector of fulfillment errors, try to adjust the spans of the 1848 /// errors to more accurately point at the cause of the failure. 1849 /// 1850 /// This applies to calls, methods, and struct expressions. This will also 1851 /// try to deduplicate errors that are due to the same cause but might 1852 /// have been created with different [`ObligationCause`][traits::ObligationCause]s. adjust_fulfillment_errors_for_expr_obligation( &self, errors: &mut Vec<traits::FulfillmentError<'tcx>>, )1853 pub(super) fn adjust_fulfillment_errors_for_expr_obligation( 1854 &self, 1855 errors: &mut Vec<traits::FulfillmentError<'tcx>>, 1856 ) { 1857 // Store a mapping from `(Span, Predicate) -> ObligationCause`, so that 1858 // other errors that have the same span and predicate can also get fixed, 1859 // even if their `ObligationCauseCode` isn't an `Expr*Obligation` kind. 1860 // This is important since if we adjust one span but not the other, then 1861 // we will have "duplicated" the error on the UI side. 1862 let mut remap_cause = FxIndexSet::default(); 1863 let mut not_adjusted = vec![]; 1864 1865 for error in errors { 1866 let before_span = error.obligation.cause.span; 1867 if self.adjust_fulfillment_error_for_expr_obligation(error) 1868 || before_span != error.obligation.cause.span 1869 { 1870 // Store both the predicate and the predicate *without constness* 1871 // since sometimes we instantiate and check both of these in a 1872 // method call, for example. 1873 remap_cause.insert(( 1874 before_span, 1875 error.obligation.predicate, 1876 error.obligation.cause.clone(), 1877 )); 1878 remap_cause.insert(( 1879 before_span, 1880 error.obligation.predicate.without_const(self.tcx), 1881 error.obligation.cause.clone(), 1882 )); 1883 } else { 1884 // If it failed to be adjusted once around, it may be adjusted 1885 // via the "remap cause" mapping the second time... 1886 not_adjusted.push(error); 1887 } 1888 } 1889 1890 // Adjust any other errors that come from other cause codes, when these 1891 // errors are of the same predicate as one we successfully adjusted, and 1892 // when their spans overlap (suggesting they're due to the same root cause). 1893 // 1894 // This is because due to normalization, we often register duplicate 1895 // obligations with misc obligations that are basically impossible to 1896 // line back up with a useful ExprBindingObligation. 1897 for error in not_adjusted { 1898 for (span, predicate, cause) in &remap_cause { 1899 if *predicate == error.obligation.predicate 1900 && span.contains(error.obligation.cause.span) 1901 { 1902 error.obligation.cause = cause.clone(); 1903 continue; 1904 } 1905 } 1906 } 1907 } 1908 label_fn_like( &self, err: &mut Diagnostic, callable_def_id: Option<DefId>, callee_ty: Option<Ty<'tcx>>, expected_idx: Option<usize>, is_method: bool, )1909 fn label_fn_like( 1910 &self, 1911 err: &mut Diagnostic, 1912 callable_def_id: Option<DefId>, 1913 callee_ty: Option<Ty<'tcx>>, 1914 // A specific argument should be labeled, instead of all of them 1915 expected_idx: Option<usize>, 1916 is_method: bool, 1917 ) { 1918 let Some(mut def_id) = callable_def_id else { 1919 return; 1920 }; 1921 1922 if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) 1923 // Possibly points at either impl or trait item, so try to get it 1924 // to point to trait item, then get the parent. 1925 // This parent might be an impl in the case of an inherent function, 1926 // but the next check will fail. 1927 && let maybe_trait_item_def_id = assoc_item.trait_item_def_id.unwrap_or(def_id) 1928 && let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id) 1929 // Just an easy way to check "trait_def_id == Fn/FnMut/FnOnce" 1930 && let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id) 1931 && let Some(callee_ty) = callee_ty 1932 { 1933 let callee_ty = callee_ty.peel_refs(); 1934 match *callee_ty.kind() { 1935 ty::Param(param) => { 1936 let param = 1937 self.tcx.generics_of(self.body_id).type_param(¶m, self.tcx); 1938 if param.kind.is_synthetic() { 1939 // if it's `impl Fn() -> ..` then just fall down to the def-id based logic 1940 def_id = param.def_id; 1941 } else { 1942 // Otherwise, find the predicate that makes this generic callable, 1943 // and point at that. 1944 let instantiated = self 1945 .tcx 1946 .explicit_predicates_of(self.body_id) 1947 .instantiate_identity(self.tcx); 1948 // FIXME(compiler-errors): This could be problematic if something has two 1949 // fn-like predicates with different args, but callable types really never 1950 // do that, so it's OK. 1951 for (predicate, span) in instantiated 1952 { 1953 if let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder() 1954 && pred.self_ty().peel_refs() == callee_ty 1955 && self.tcx.is_fn_trait(pred.def_id()) 1956 { 1957 err.span_note(span, "callable defined here"); 1958 return; 1959 } 1960 } 1961 } 1962 } 1963 ty::Alias(ty::Opaque, ty::AliasTy { def_id: new_def_id, .. }) 1964 | ty::Closure(new_def_id, _) 1965 | ty::FnDef(new_def_id, _) => { 1966 def_id = new_def_id; 1967 } 1968 _ => { 1969 // Look for a user-provided impl of a `Fn` trait, and point to it. 1970 let new_def_id = self.probe(|_| { 1971 let trait_ref = ty::TraitRef::new(self.tcx, 1972 call_kind.to_def_id(self.tcx), 1973 [ 1974 callee_ty, 1975 self.next_ty_var(TypeVariableOrigin { 1976 kind: TypeVariableOriginKind::MiscVariable, 1977 span: rustc_span::DUMMY_SP, 1978 }), 1979 ], 1980 ); 1981 let obligation = traits::Obligation::new( 1982 self.tcx, 1983 traits::ObligationCause::dummy(), 1984 self.param_env, 1985 trait_ref, 1986 ); 1987 match SelectionContext::new(&self).select(&obligation) { 1988 Ok(Some(traits::ImplSource::UserDefined(impl_source))) => { 1989 Some(impl_source.impl_def_id) 1990 } 1991 _ => None, 1992 } 1993 }); 1994 if let Some(new_def_id) = new_def_id { 1995 def_id = new_def_id; 1996 } else { 1997 return; 1998 } 1999 } 2000 } 2001 } 2002 2003 if let Some(def_span) = self.tcx.def_ident_span(def_id) && !def_span.is_dummy() { 2004 let mut spans: MultiSpan = def_span.into(); 2005 2006 let params = self 2007 .tcx 2008 .hir() 2009 .get_if_local(def_id) 2010 .and_then(|node| node.body_id()) 2011 .into_iter() 2012 .flat_map(|id| self.tcx.hir().body(id).params) 2013 .skip(if is_method { 1 } else { 0 }); 2014 2015 for (_, param) in params 2016 .into_iter() 2017 .enumerate() 2018 .filter(|(idx, _)| expected_idx.map_or(true, |expected_idx| expected_idx == *idx)) 2019 { 2020 spans.push_span_label(param.span, ""); 2021 } 2022 2023 err.span_note(spans, format!("{} defined here", self.tcx.def_descr(def_id))); 2024 } else if let Some(hir::Node::Expr(e)) = self.tcx.hir().get_if_local(def_id) 2025 && let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind 2026 { 2027 let param = expected_idx 2028 .and_then(|expected_idx| self.tcx.hir().body(*body).params.get(expected_idx)); 2029 let (kind, span) = if let Some(param) = param { 2030 ("closure parameter", param.span) 2031 } else { 2032 ("closure", self.tcx.def_span(def_id)) 2033 }; 2034 err.span_note(span, format!("{} defined here", kind)); 2035 } else { 2036 err.span_note( 2037 self.tcx.def_span(def_id), 2038 format!("{} defined here", self.tcx.def_descr(def_id)), 2039 ); 2040 } 2041 } 2042 } 2043