1 //! Type checking expressions. 2 //! 3 //! See `mod.rs` for more context on type checking in general. 4 5 use crate::cast; 6 use crate::coercion::CoerceMany; 7 use crate::coercion::DynamicCoerceMany; 8 use crate::errors::ReturnLikeStatementKind; 9 use crate::errors::TypeMismatchFruTypo; 10 use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive}; 11 use crate::errors::{ 12 FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, HelpUseLatestEdition, 13 YieldExprOutsideOfGenerator, 14 }; 15 use crate::fatally_break_rust; 16 use crate::method::SelfSource; 17 use crate::type_error_struct; 18 use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation}; 19 use crate::{ 20 report_unexpected_variant_res, BreakableCtxt, Diverges, FnCtxt, Needs, 21 TupleArgumentsFlag::DontTupleArguments, 22 }; 23 use rustc_ast as ast; 24 use rustc_data_structures::fx::FxHashMap; 25 use rustc_data_structures::stack::ensure_sufficient_stack; 26 use rustc_errors::{ 27 pluralize, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, 28 DiagnosticId, ErrorGuaranteed, StashKey, 29 }; 30 use rustc_hir as hir; 31 use rustc_hir::def::{CtorKind, DefKind, Res}; 32 use rustc_hir::def_id::DefId; 33 use rustc_hir::intravisit::Visitor; 34 use rustc_hir::lang_items::LangItem; 35 use rustc_hir::{ExprKind, HirId, QPath}; 36 use rustc_hir_analysis::astconv::AstConv as _; 37 use rustc_hir_analysis::check::ty_kind_suggestion; 38 use rustc_infer::infer; 39 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; 40 use rustc_infer::infer::DefineOpaqueTypes; 41 use rustc_infer::infer::InferOk; 42 use rustc_infer::traits::query::NoSolution; 43 use rustc_infer::traits::ObligationCause; 44 use rustc_middle::middle::stability; 45 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase}; 46 use rustc_middle::ty::error::TypeError::FieldMisMatch; 47 use rustc_middle::ty::subst::SubstsRef; 48 use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitableExt}; 49 use rustc_session::errors::ExprParenthesesNeeded; 50 use rustc_session::parse::feature_err; 51 use rustc_span::edit_distance::find_best_match_for_name; 52 use rustc_span::hygiene::DesugaringKind; 53 use rustc_span::source_map::{Span, Spanned}; 54 use rustc_span::symbol::{kw, sym, Ident, Symbol}; 55 use rustc_target::abi::FieldIdx; 56 use rustc_target::spec::abi::Abi::RustIntrinsic; 57 use rustc_trait_selection::infer::InferCtxtExt; 58 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; 59 use rustc_trait_selection::traits::ObligationCtxt; 60 use rustc_trait_selection::traits::{self, ObligationCauseCode}; 61 62 impl<'a, 'tcx> FnCtxt<'a, 'tcx> { check_expr_eq_type(&self, expr: &'tcx hir::Expr<'tcx>, expected: Ty<'tcx>)63 fn check_expr_eq_type(&self, expr: &'tcx hir::Expr<'tcx>, expected: Ty<'tcx>) { 64 let ty = self.check_expr_with_hint(expr, expected); 65 self.demand_eqtype(expr.span, expected, ty); 66 } 67 check_expr_has_type_or_error( &self, expr: &'tcx hir::Expr<'tcx>, expected: Ty<'tcx>, extend_err: impl FnMut(&mut Diagnostic), ) -> Ty<'tcx>68 pub fn check_expr_has_type_or_error( 69 &self, 70 expr: &'tcx hir::Expr<'tcx>, 71 expected: Ty<'tcx>, 72 extend_err: impl FnMut(&mut Diagnostic), 73 ) -> Ty<'tcx> { 74 self.check_expr_meets_expectation_or_error(expr, ExpectHasType(expected), extend_err) 75 } 76 check_expr_meets_expectation_or_error( &self, expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, mut extend_err: impl FnMut(&mut Diagnostic), ) -> Ty<'tcx>77 fn check_expr_meets_expectation_or_error( 78 &self, 79 expr: &'tcx hir::Expr<'tcx>, 80 expected: Expectation<'tcx>, 81 mut extend_err: impl FnMut(&mut Diagnostic), 82 ) -> Ty<'tcx> { 83 let expected_ty = expected.to_option(&self).unwrap_or(self.tcx.types.bool); 84 let mut ty = self.check_expr_with_expectation(expr, expected); 85 86 // While we don't allow *arbitrary* coercions here, we *do* allow 87 // coercions from ! to `expected`. 88 if ty.is_never() { 89 if let Some(adjustments) = self.typeck_results.borrow().adjustments().get(expr.hir_id) { 90 let reported = self.tcx().sess.delay_span_bug( 91 expr.span, 92 "expression with never type wound up being adjusted", 93 ); 94 return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &adjustments[..] { 95 target.to_owned() 96 } else { 97 Ty::new_error(self.tcx(), reported) 98 }; 99 } 100 101 let adj_ty = self.next_ty_var(TypeVariableOrigin { 102 kind: TypeVariableOriginKind::AdjustmentType, 103 span: expr.span, 104 }); 105 self.apply_adjustments( 106 expr, 107 vec![Adjustment { kind: Adjust::NeverToAny, target: adj_ty }], 108 ); 109 ty = adj_ty; 110 } 111 112 if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) { 113 let _ = self.emit_type_mismatch_suggestions( 114 &mut err, 115 expr.peel_drop_temps(), 116 ty, 117 expected_ty, 118 None, 119 None, 120 ); 121 extend_err(&mut err); 122 err.emit(); 123 } 124 ty 125 } 126 check_expr_coercible_to_type( &self, expr: &'tcx hir::Expr<'tcx>, expected: Ty<'tcx>, expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, ) -> Ty<'tcx>127 pub(super) fn check_expr_coercible_to_type( 128 &self, 129 expr: &'tcx hir::Expr<'tcx>, 130 expected: Ty<'tcx>, 131 expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, 132 ) -> Ty<'tcx> { 133 let ty = self.check_expr_with_hint(expr, expected); 134 // checks don't need two phase 135 self.demand_coerce(expr, ty, expected, expected_ty_expr, AllowTwoPhase::No) 136 } 137 check_expr_with_hint( &self, expr: &'tcx hir::Expr<'tcx>, expected: Ty<'tcx>, ) -> Ty<'tcx>138 pub(super) fn check_expr_with_hint( 139 &self, 140 expr: &'tcx hir::Expr<'tcx>, 141 expected: Ty<'tcx>, 142 ) -> Ty<'tcx> { 143 self.check_expr_with_expectation(expr, ExpectHasType(expected)) 144 } 145 check_expr_with_expectation_and_needs( &self, expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, needs: Needs, ) -> Ty<'tcx>146 fn check_expr_with_expectation_and_needs( 147 &self, 148 expr: &'tcx hir::Expr<'tcx>, 149 expected: Expectation<'tcx>, 150 needs: Needs, 151 ) -> Ty<'tcx> { 152 let ty = self.check_expr_with_expectation(expr, expected); 153 154 // If the expression is used in a place whether mutable place is required 155 // e.g. LHS of assignment, perform the conversion. 156 if let Needs::MutPlace = needs { 157 self.convert_place_derefs_to_mutable(expr); 158 } 159 160 ty 161 } 162 check_expr(&self, expr: &'tcx hir::Expr<'tcx>) -> Ty<'tcx>163 pub(super) fn check_expr(&self, expr: &'tcx hir::Expr<'tcx>) -> Ty<'tcx> { 164 self.check_expr_with_expectation(expr, NoExpectation) 165 } 166 check_expr_with_needs( &self, expr: &'tcx hir::Expr<'tcx>, needs: Needs, ) -> Ty<'tcx>167 pub(super) fn check_expr_with_needs( 168 &self, 169 expr: &'tcx hir::Expr<'tcx>, 170 needs: Needs, 171 ) -> Ty<'tcx> { 172 self.check_expr_with_expectation_and_needs(expr, NoExpectation, needs) 173 } 174 175 /// Invariant: 176 /// If an expression has any sub-expressions that result in a type error, 177 /// inspecting that expression's type with `ty.references_error()` will return 178 /// true. Likewise, if an expression is known to diverge, inspecting its 179 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is 180 /// strict, _|_ can appear in the type of an expression that does not, 181 /// itself, diverge: for example, fn() -> _|_.) 182 /// Note that inspecting a type's structure *directly* may expose the fact 183 /// that there are actually multiple representations for `Error`, so avoid 184 /// that when err needs to be handled differently. 185 #[instrument(skip(self, expr), level = "debug")] check_expr_with_expectation( &self, expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx>186 pub(super) fn check_expr_with_expectation( 187 &self, 188 expr: &'tcx hir::Expr<'tcx>, 189 expected: Expectation<'tcx>, 190 ) -> Ty<'tcx> { 191 self.check_expr_with_expectation_and_args(expr, expected, &[]) 192 } 193 194 /// Same as `check_expr_with_expectation`, but allows us to pass in the arguments of a 195 /// `ExprKind::Call` when evaluating its callee when it is an `ExprKind::Path`. check_expr_with_expectation_and_args( &self, expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, args: &'tcx [hir::Expr<'tcx>], ) -> Ty<'tcx>196 pub(super) fn check_expr_with_expectation_and_args( 197 &self, 198 expr: &'tcx hir::Expr<'tcx>, 199 expected: Expectation<'tcx>, 200 args: &'tcx [hir::Expr<'tcx>], 201 ) -> Ty<'tcx> { 202 if self.tcx().sess.verbose() { 203 // make this code only run with -Zverbose because it is probably slow 204 if let Ok(lint_str) = self.tcx.sess.source_map().span_to_snippet(expr.span) { 205 if !lint_str.contains('\n') { 206 debug!("expr text: {lint_str}"); 207 } else { 208 let mut lines = lint_str.lines(); 209 if let Some(line0) = lines.next() { 210 let remaining_lines = lines.count(); 211 debug!("expr text: {line0}"); 212 debug!("expr text: ...(and {remaining_lines} more lines)"); 213 } 214 } 215 } 216 } 217 218 // True if `expr` is a `Try::from_ok(())` that is a result of desugaring a try block 219 // without the final expr (e.g. `try { return; }`). We don't want to generate an 220 // unreachable_code lint for it since warnings for autogenerated code are confusing. 221 let is_try_block_generated_unit_expr = match expr.kind { 222 ExprKind::Call(_, args) if expr.span.is_desugaring(DesugaringKind::TryBlock) => { 223 args.len() == 1 && args[0].span.is_desugaring(DesugaringKind::TryBlock) 224 } 225 226 _ => false, 227 }; 228 229 // Warn for expressions after diverging siblings. 230 if !is_try_block_generated_unit_expr { 231 self.warn_if_unreachable(expr.hir_id, expr.span, "expression"); 232 } 233 234 // Hide the outer diverging and has_errors flags. 235 let old_diverges = self.diverges.replace(Diverges::Maybe); 236 237 let ty = ensure_sufficient_stack(|| match &expr.kind { 238 hir::ExprKind::Path( 239 qpath @ (hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)), 240 ) => self.check_expr_path(qpath, expr, args), 241 _ => self.check_expr_kind(expr, expected), 242 }); 243 let ty = self.resolve_vars_if_possible(ty); 244 245 // Warn for non-block expressions with diverging children. 246 match expr.kind { 247 ExprKind::Block(..) 248 | ExprKind::If(..) 249 | ExprKind::Let(..) 250 | ExprKind::Loop(..) 251 | ExprKind::Match(..) => {} 252 // If `expr` is a result of desugaring the try block and is an ok-wrapped 253 // diverging expression (e.g. it arose from desugaring of `try { return }`), 254 // we skip issuing a warning because it is autogenerated code. 255 ExprKind::Call(..) if expr.span.is_desugaring(DesugaringKind::TryBlock) => {} 256 ExprKind::Call(callee, _) => self.warn_if_unreachable(expr.hir_id, callee.span, "call"), 257 ExprKind::MethodCall(segment, ..) => { 258 self.warn_if_unreachable(expr.hir_id, segment.ident.span, "call") 259 } 260 _ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression"), 261 } 262 263 // Any expression that produces a value of type `!` must have diverged 264 if ty.is_never() { 265 self.diverges.set(self.diverges.get() | Diverges::always(expr.span)); 266 } 267 268 // Record the type, which applies it effects. 269 // We need to do this after the warning above, so that 270 // we don't warn for the diverging expression itself. 271 self.write_ty(expr.hir_id, ty); 272 273 // Combine the diverging and has_error flags. 274 self.diverges.set(self.diverges.get() | old_diverges); 275 276 debug!("type of {} is...", self.tcx.hir().node_to_string(expr.hir_id)); 277 debug!("... {:?}, expected is {:?}", ty, expected); 278 279 ty 280 } 281 282 #[instrument(skip(self, expr), level = "debug")] check_expr_kind( &self, expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx>283 fn check_expr_kind( 284 &self, 285 expr: &'tcx hir::Expr<'tcx>, 286 expected: Expectation<'tcx>, 287 ) -> Ty<'tcx> { 288 trace!("expr={:#?}", expr); 289 290 let tcx = self.tcx; 291 match expr.kind { 292 ExprKind::Lit(ref lit) => self.check_lit(&lit, expected), 293 ExprKind::Binary(op, lhs, rhs) => self.check_binop(expr, op, lhs, rhs, expected), 294 ExprKind::Assign(lhs, rhs, span) => { 295 self.check_expr_assign(expr, expected, lhs, rhs, span) 296 } 297 ExprKind::AssignOp(op, lhs, rhs) => { 298 self.check_binop_assign(expr, op, lhs, rhs, expected) 299 } 300 ExprKind::Unary(unop, oprnd) => self.check_expr_unary(unop, oprnd, expected, expr), 301 ExprKind::AddrOf(kind, mutbl, oprnd) => { 302 self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr) 303 } 304 ExprKind::Path(QPath::LangItem(lang_item, _, hir_id)) => { 305 self.check_lang_item_path(lang_item, expr, hir_id) 306 } 307 ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]), 308 ExprKind::InlineAsm(asm) => { 309 // We defer some asm checks as we may not have resolved the input and output types yet (they may still be infer vars). 310 self.deferred_asm_checks.borrow_mut().push((asm, expr.hir_id)); 311 self.check_expr_asm(asm) 312 } 313 ExprKind::OffsetOf(container, ref fields) => { 314 self.check_offset_of(container, fields, expr) 315 } 316 ExprKind::Break(destination, ref expr_opt) => { 317 self.check_expr_break(destination, expr_opt.as_deref(), expr) 318 } 319 ExprKind::Continue(destination) => { 320 if destination.target_id.is_ok() { 321 tcx.types.never 322 } else { 323 // There was an error; make type-check fail. 324 Ty::new_misc_error(tcx) 325 } 326 } 327 ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr), 328 ExprKind::Become(call) => self.check_expr_become(call, expr), 329 ExprKind::Let(let_expr) => self.check_expr_let(let_expr), 330 ExprKind::Loop(body, _, source, _) => { 331 self.check_expr_loop(body, source, expected, expr) 332 } 333 ExprKind::Match(discrim, arms, match_src) => { 334 self.check_match(expr, &discrim, arms, expected, match_src) 335 } 336 ExprKind::Closure(closure) => self.check_expr_closure(closure, expr.span, expected), 337 ExprKind::Block(body, _) => self.check_block_with_expected(&body, expected), 338 ExprKind::Call(callee, args) => self.check_call(expr, &callee, args, expected), 339 ExprKind::MethodCall(segment, receiver, args, _) => { 340 self.check_method_call(expr, segment, receiver, args, expected) 341 } 342 ExprKind::Cast(e, t) => self.check_expr_cast(e, t, expr), 343 ExprKind::Type(e, t) => { 344 let ty = self.to_ty_saving_user_provided_ty(&t); 345 self.check_expr_eq_type(&e, ty); 346 ty 347 } 348 ExprKind::If(cond, then_expr, opt_else_expr) => { 349 self.check_then_else(cond, then_expr, opt_else_expr, expr.span, expected) 350 } 351 ExprKind::DropTemps(e) => self.check_expr_with_expectation(e, expected), 352 ExprKind::Array(args) => self.check_expr_array(args, expected, expr), 353 ExprKind::ConstBlock(ref block) => self.check_expr_const_block(block, expected, expr), 354 ExprKind::Repeat(element, ref count) => { 355 self.check_expr_repeat(element, count, expected, expr) 356 } 357 ExprKind::Tup(elts) => self.check_expr_tuple(elts, expected, expr), 358 ExprKind::Struct(qpath, fields, ref base_expr) => { 359 self.check_expr_struct(expr, expected, qpath, fields, base_expr) 360 } 361 ExprKind::Field(base, field) => self.check_field(expr, &base, field, expected), 362 ExprKind::Index(base, idx) => self.check_expr_index(base, idx, expr), 363 ExprKind::Yield(value, ref src) => self.check_expr_yield(value, expr, src), 364 hir::ExprKind::Err(guar) => Ty::new_error(tcx, guar), 365 } 366 } 367 check_expr_unary( &self, unop: hir::UnOp, oprnd: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx>368 fn check_expr_unary( 369 &self, 370 unop: hir::UnOp, 371 oprnd: &'tcx hir::Expr<'tcx>, 372 expected: Expectation<'tcx>, 373 expr: &'tcx hir::Expr<'tcx>, 374 ) -> Ty<'tcx> { 375 let tcx = self.tcx; 376 let expected_inner = match unop { 377 hir::UnOp::Not | hir::UnOp::Neg => expected, 378 hir::UnOp::Deref => NoExpectation, 379 }; 380 let mut oprnd_t = self.check_expr_with_expectation(&oprnd, expected_inner); 381 382 if !oprnd_t.references_error() { 383 oprnd_t = self.structurally_resolve_type(expr.span, oprnd_t); 384 match unop { 385 hir::UnOp::Deref => { 386 if let Some(ty) = self.lookup_derefing(expr, oprnd, oprnd_t) { 387 oprnd_t = ty; 388 } else { 389 let mut err = type_error_struct!( 390 tcx.sess, 391 expr.span, 392 oprnd_t, 393 E0614, 394 "type `{oprnd_t}` cannot be dereferenced", 395 ); 396 let sp = tcx.sess.source_map().start_point(expr.span).with_parent(None); 397 if let Some(sp) = 398 tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) 399 { 400 err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); 401 } 402 oprnd_t = Ty::new_error(tcx, err.emit()); 403 } 404 } 405 hir::UnOp::Not => { 406 let result = self.check_user_unop(expr, oprnd_t, unop, expected_inner); 407 // If it's builtin, we can reuse the type, this helps inference. 408 if !(oprnd_t.is_integral() || *oprnd_t.kind() == ty::Bool) { 409 oprnd_t = result; 410 } 411 } 412 hir::UnOp::Neg => { 413 let result = self.check_user_unop(expr, oprnd_t, unop, expected_inner); 414 // If it's builtin, we can reuse the type, this helps inference. 415 if !oprnd_t.is_numeric() { 416 oprnd_t = result; 417 } 418 } 419 } 420 } 421 oprnd_t 422 } 423 check_expr_addr_of( &self, kind: hir::BorrowKind, mutbl: hir::Mutability, oprnd: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx>424 fn check_expr_addr_of( 425 &self, 426 kind: hir::BorrowKind, 427 mutbl: hir::Mutability, 428 oprnd: &'tcx hir::Expr<'tcx>, 429 expected: Expectation<'tcx>, 430 expr: &'tcx hir::Expr<'tcx>, 431 ) -> Ty<'tcx> { 432 let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| { 433 match ty.kind() { 434 ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => { 435 if oprnd.is_syntactic_place_expr() { 436 // Places may legitimately have unsized types. 437 // For example, dereferences of a fat pointer and 438 // the last field of a struct can be unsized. 439 ExpectHasType(*ty) 440 } else { 441 Expectation::rvalue_hint(self, *ty) 442 } 443 } 444 _ => NoExpectation, 445 } 446 }); 447 let ty = 448 self.check_expr_with_expectation_and_needs(&oprnd, hint, Needs::maybe_mut_place(mutbl)); 449 450 let tm = ty::TypeAndMut { ty, mutbl }; 451 match kind { 452 _ if tm.ty.references_error() => Ty::new_misc_error(self.tcx), 453 hir::BorrowKind::Raw => { 454 self.check_named_place_expr(oprnd); 455 Ty::new_ptr(self.tcx, tm) 456 } 457 hir::BorrowKind::Ref => { 458 // Note: at this point, we cannot say what the best lifetime 459 // is to use for resulting pointer. We want to use the 460 // shortest lifetime possible so as to avoid spurious borrowck 461 // errors. Moreover, the longest lifetime will depend on the 462 // precise details of the value whose address is being taken 463 // (and how long it is valid), which we don't know yet until 464 // type inference is complete. 465 // 466 // Therefore, here we simply generate a region variable. The 467 // region inferencer will then select a suitable value. 468 // Finally, borrowck will infer the value of the region again, 469 // this time with enough precision to check that the value 470 // whose address was taken can actually be made to live as long 471 // as it needs to live. 472 let region = self.next_region_var(infer::AddrOfRegion(expr.span)); 473 Ty::new_ref(self.tcx, region, tm) 474 } 475 } 476 } 477 478 /// Does this expression refer to a place that either: 479 /// * Is based on a local or static. 480 /// * Contains a dereference 481 /// Note that the adjustments for the children of `expr` should already 482 /// have been resolved. check_named_place_expr(&self, oprnd: &'tcx hir::Expr<'tcx>)483 fn check_named_place_expr(&self, oprnd: &'tcx hir::Expr<'tcx>) { 484 let is_named = oprnd.is_place_expr(|base| { 485 // Allow raw borrows if there are any deref adjustments. 486 // 487 // const VAL: (i32,) = (0,); 488 // const REF: &(i32,) = &(0,); 489 // 490 // &raw const VAL.0; // ERROR 491 // &raw const REF.0; // OK, same as &raw const (*REF).0; 492 // 493 // This is maybe too permissive, since it allows 494 // `let u = &raw const Box::new((1,)).0`, which creates an 495 // immediately dangling raw pointer. 496 self.typeck_results 497 .borrow() 498 .adjustments() 499 .get(base.hir_id) 500 .is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_)))) 501 }); 502 if !is_named { 503 self.tcx.sess.emit_err(AddressOfTemporaryTaken { span: oprnd.span }); 504 } 505 } 506 check_lang_item_path( &self, lang_item: hir::LangItem, expr: &'tcx hir::Expr<'tcx>, hir_id: Option<hir::HirId>, ) -> Ty<'tcx>507 fn check_lang_item_path( 508 &self, 509 lang_item: hir::LangItem, 510 expr: &'tcx hir::Expr<'tcx>, 511 hir_id: Option<hir::HirId>, 512 ) -> Ty<'tcx> { 513 self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id, hir_id).1 514 } 515 check_expr_path( &self, qpath: &'tcx hir::QPath<'tcx>, expr: &'tcx hir::Expr<'tcx>, args: &'tcx [hir::Expr<'tcx>], ) -> Ty<'tcx>516 pub(crate) fn check_expr_path( 517 &self, 518 qpath: &'tcx hir::QPath<'tcx>, 519 expr: &'tcx hir::Expr<'tcx>, 520 args: &'tcx [hir::Expr<'tcx>], 521 ) -> Ty<'tcx> { 522 let tcx = self.tcx; 523 let (res, opt_ty, segs) = 524 self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span); 525 let ty = match res { 526 Res::Err => { 527 self.suggest_assoc_method_call(segs); 528 let e = 529 self.tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted"); 530 self.set_tainted_by_errors(e); 531 Ty::new_error(tcx, e) 532 } 533 Res::Def(DefKind::Variant, _) => { 534 let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, "E0533", "value"); 535 Ty::new_error(tcx, e) 536 } 537 _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0, 538 }; 539 540 if let ty::FnDef(did, ..) = *ty.kind() { 541 let fn_sig = ty.fn_sig(tcx); 542 if tcx.fn_sig(did).skip_binder().abi() == RustIntrinsic 543 && tcx.item_name(did) == sym::transmute 544 { 545 let from = fn_sig.inputs().skip_binder()[0]; 546 let to = fn_sig.output().skip_binder(); 547 // We defer the transmute to the end of typeck, once all inference vars have 548 // been resolved or we errored. This is important as we can only check transmute 549 // on concrete types, but the output type may not be known yet (it would only 550 // be known if explicitly specified via turbofish). 551 self.deferred_transmute_checks.borrow_mut().push((from, to, expr.hir_id)); 552 } 553 if !tcx.features().unsized_fn_params { 554 // We want to remove some Sized bounds from std functions, 555 // but don't want to expose the removal to stable Rust. 556 // i.e., we don't want to allow 557 // 558 // ```rust 559 // drop as fn(str); 560 // ``` 561 // 562 // to work in stable even if the Sized bound on `drop` is relaxed. 563 for i in 0..fn_sig.inputs().skip_binder().len() { 564 // We just want to check sizedness, so instead of introducing 565 // placeholder lifetimes with probing, we just replace higher lifetimes 566 // with fresh vars. 567 let span = args.get(i).map(|a| a.span).unwrap_or(expr.span); 568 let input = self.instantiate_binder_with_fresh_vars( 569 span, 570 infer::LateBoundRegionConversionTime::FnCall, 571 fn_sig.input(i), 572 ); 573 self.require_type_is_sized_deferred( 574 input, 575 span, 576 traits::SizedArgumentType(None), 577 ); 578 } 579 } 580 // Here we want to prevent struct constructors from returning unsized types. 581 // There were two cases this happened: fn pointer coercion in stable 582 // and usual function call in presence of unsized_locals. 583 // Also, as we just want to check sizedness, instead of introducing 584 // placeholder lifetimes with probing, we just replace higher lifetimes 585 // with fresh vars. 586 let output = self.instantiate_binder_with_fresh_vars( 587 expr.span, 588 infer::LateBoundRegionConversionTime::FnCall, 589 fn_sig.output(), 590 ); 591 self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); 592 } 593 594 // We always require that the type provided as the value for 595 // a type parameter outlives the moment of instantiation. 596 let substs = self.typeck_results.borrow().node_substs(expr.hir_id); 597 self.add_wf_bounds(substs, expr); 598 599 ty 600 } 601 check_expr_break( &self, destination: hir::Destination, expr_opt: Option<&'tcx hir::Expr<'tcx>>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx>602 fn check_expr_break( 603 &self, 604 destination: hir::Destination, 605 expr_opt: Option<&'tcx hir::Expr<'tcx>>, 606 expr: &'tcx hir::Expr<'tcx>, 607 ) -> Ty<'tcx> { 608 let tcx = self.tcx; 609 if let Ok(target_id) = destination.target_id { 610 let (e_ty, cause); 611 if let Some(e) = expr_opt { 612 // If this is a break with a value, we need to type-check 613 // the expression. Get an expected type from the loop context. 614 let opt_coerce_to = { 615 // We should release `enclosing_breakables` before the `check_expr_with_hint` 616 // below, so can't move this block of code to the enclosing scope and share 617 // `ctxt` with the second `enclosing_breakables` borrow below. 618 let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); 619 match enclosing_breakables.opt_find_breakable(target_id) { 620 Some(ctxt) => ctxt.coerce.as_ref().map(|coerce| coerce.expected_ty()), 621 None => { 622 // Avoid ICE when `break` is inside a closure (#65383). 623 return Ty::new_error_with_message( 624 tcx, 625 expr.span, 626 "break was outside loop, but no error was emitted", 627 ); 628 } 629 } 630 }; 631 632 // If the loop context is not a `loop { }`, then break with 633 // a value is illegal, and `opt_coerce_to` will be `None`. 634 // Just set expectation to error in that case. 635 let coerce_to = opt_coerce_to.unwrap_or_else(|| Ty::new_misc_error(tcx)); 636 637 // Recurse without `enclosing_breakables` borrowed. 638 e_ty = self.check_expr_with_hint(e, coerce_to); 639 cause = self.misc(e.span); 640 } else { 641 // Otherwise, this is a break *without* a value. That's 642 // always legal, and is equivalent to `break ()`. 643 e_ty = Ty::new_unit(tcx); 644 cause = self.misc(expr.span); 645 } 646 647 // Now that we have type-checked `expr_opt`, borrow 648 // the `enclosing_loops` field and let's coerce the 649 // type of `expr_opt` into what is expected. 650 let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); 651 let Some(ctxt) = enclosing_breakables.opt_find_breakable(target_id) else { 652 // Avoid ICE when `break` is inside a closure (#65383). 653 return Ty::new_error_with_message(tcx, 654 expr.span, 655 "break was outside loop, but no error was emitted", 656 ); 657 }; 658 659 if let Some(ref mut coerce) = ctxt.coerce { 660 if let Some(ref e) = expr_opt { 661 coerce.coerce(self, &cause, e, e_ty); 662 } else { 663 assert!(e_ty.is_unit()); 664 let ty = coerce.expected_ty(); 665 coerce.coerce_forced_unit( 666 self, 667 &cause, 668 &mut |mut err| { 669 self.suggest_mismatched_types_on_tail( 670 &mut err, expr, ty, e_ty, target_id, 671 ); 672 if let Some(val) = ty_kind_suggestion(ty) { 673 let label = destination 674 .label 675 .map(|l| format!(" {}", l.ident)) 676 .unwrap_or_else(String::new); 677 err.span_suggestion( 678 expr.span, 679 "give it a value of the expected type", 680 format!("break{label} {val}"), 681 Applicability::HasPlaceholders, 682 ); 683 } 684 }, 685 false, 686 ); 687 } 688 } else { 689 // If `ctxt.coerce` is `None`, we can just ignore 690 // the type of the expression. This is because 691 // either this was a break *without* a value, in 692 // which case it is always a legal type (`()`), or 693 // else an error would have been flagged by the 694 // `loops` pass for using break with an expression 695 // where you are not supposed to. 696 assert!(expr_opt.is_none() || self.tcx.sess.has_errors().is_some()); 697 } 698 699 // If we encountered a `break`, then (no surprise) it may be possible to break from the 700 // loop... unless the value being returned from the loop diverges itself, e.g. 701 // `break return 5` or `break loop {}`. 702 ctxt.may_break |= !self.diverges.get().is_always(); 703 704 // the type of a `break` is always `!`, since it diverges 705 tcx.types.never 706 } else { 707 // Otherwise, we failed to find the enclosing loop; 708 // this can only happen if the `break` was not 709 // inside a loop at all, which is caught by the 710 // loop-checking pass. 711 let err = Ty::new_error_with_message( 712 self.tcx, 713 expr.span, 714 "break was outside loop, but no error was emitted", 715 ); 716 717 // We still need to assign a type to the inner expression to 718 // prevent the ICE in #43162. 719 if let Some(e) = expr_opt { 720 self.check_expr_with_hint(e, err); 721 722 // ... except when we try to 'break rust;'. 723 // ICE this expression in particular (see #43162). 724 if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind { 725 if path.segments.len() == 1 && path.segments[0].ident.name == sym::rust { 726 fatally_break_rust(self.tcx); 727 } 728 } 729 } 730 731 // There was an error; make type-check fail. 732 err 733 } 734 } 735 check_expr_return( &self, expr_opt: Option<&'tcx hir::Expr<'tcx>>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx>736 fn check_expr_return( 737 &self, 738 expr_opt: Option<&'tcx hir::Expr<'tcx>>, 739 expr: &'tcx hir::Expr<'tcx>, 740 ) -> Ty<'tcx> { 741 if self.ret_coercion.is_none() { 742 self.emit_return_outside_of_fn_body(expr, ReturnLikeStatementKind::Return); 743 744 if let Some(e) = expr_opt { 745 // We still have to type-check `e` (issue #86188), but calling 746 // `check_return_expr` only works inside fn bodies. 747 self.check_expr(e); 748 } 749 } else if let Some(e) = expr_opt { 750 if self.ret_coercion_span.get().is_none() { 751 self.ret_coercion_span.set(Some(e.span)); 752 } 753 self.check_return_expr(e, true); 754 } else { 755 let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut(); 756 if self.ret_coercion_span.get().is_none() { 757 self.ret_coercion_span.set(Some(expr.span)); 758 } 759 let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression); 760 if let Some((_, fn_decl, _)) = self.get_fn_decl(expr.hir_id) { 761 coercion.coerce_forced_unit( 762 self, 763 &cause, 764 &mut |db| { 765 let span = fn_decl.output.span(); 766 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { 767 db.span_label( 768 span, 769 format!("expected `{snippet}` because of this return type"), 770 ); 771 } 772 }, 773 true, 774 ); 775 } else { 776 coercion.coerce_forced_unit(self, &cause, &mut |_| (), true); 777 } 778 } 779 self.tcx.types.never 780 } 781 check_expr_become( &self, call: &'tcx hir::Expr<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx>782 fn check_expr_become( 783 &self, 784 call: &'tcx hir::Expr<'tcx>, 785 expr: &'tcx hir::Expr<'tcx>, 786 ) -> Ty<'tcx> { 787 match &self.ret_coercion { 788 Some(ret_coercion) => { 789 let ret_ty = ret_coercion.borrow().expected_ty(); 790 let call_expr_ty = self.check_expr_with_hint(call, ret_ty); 791 792 // N.B. don't coerce here, as tail calls can't support most/all coercions 793 // FIXME(explicit_tail_calls): add a diagnostic note that `become` doesn't allow coercions 794 self.demand_suptype(expr.span, ret_ty, call_expr_ty); 795 } 796 None => { 797 self.emit_return_outside_of_fn_body(expr, ReturnLikeStatementKind::Become); 798 799 // Fallback to simply type checking `call` without hint/demanding the right types. 800 // Best effort to highlight more errors. 801 self.check_expr(call); 802 } 803 } 804 805 self.tcx.types.never 806 } 807 808 /// Check an expression that _is being returned_. 809 /// For example, this is called with `return_expr: $expr` when `return $expr` 810 /// is encountered. 811 /// 812 /// Note that this function must only be called in function bodies. 813 /// 814 /// `explicit_return` is `true` if we're checking an explicit `return expr`, 815 /// and `false` if we're checking a trailing expression. check_return_expr( &self, return_expr: &'tcx hir::Expr<'tcx>, explicit_return: bool, )816 pub(super) fn check_return_expr( 817 &self, 818 return_expr: &'tcx hir::Expr<'tcx>, 819 explicit_return: bool, 820 ) { 821 let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| { 822 span_bug!(return_expr.span, "check_return_expr called outside fn body") 823 }); 824 825 let ret_ty = ret_coercion.borrow().expected_ty(); 826 let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty); 827 let mut span = return_expr.span; 828 // Use the span of the trailing expression for our cause, 829 // not the span of the entire function 830 if !explicit_return 831 && let ExprKind::Block(body, _) = return_expr.kind 832 && let Some(last_expr) = body.expr 833 { 834 span = last_expr.span; 835 } 836 ret_coercion.borrow_mut().coerce( 837 self, 838 &self.cause(span, ObligationCauseCode::ReturnValue(return_expr.hir_id)), 839 return_expr, 840 return_expr_ty, 841 ); 842 843 if let Some(fn_sig) = self.body_fn_sig() 844 && fn_sig.output().has_opaque_types() 845 { 846 // Point any obligations that were registered due to opaque type 847 // inference at the return expression. 848 self.select_obligations_where_possible(|errors| { 849 self.point_at_return_for_opaque_ty_error(errors, span, return_expr_ty, return_expr.span); 850 }); 851 } 852 } 853 854 /// Emit an error because `return` or `become` is used outside of a function body. 855 /// 856 /// `expr` is the `return` (`become`) "statement", `kind` is the kind of the statement 857 /// either `Return` or `Become`. emit_return_outside_of_fn_body(&self, expr: &hir::Expr<'_>, kind: ReturnLikeStatementKind)858 fn emit_return_outside_of_fn_body(&self, expr: &hir::Expr<'_>, kind: ReturnLikeStatementKind) { 859 let mut err = ReturnStmtOutsideOfFnBody { 860 span: expr.span, 861 encl_body_span: None, 862 encl_fn_span: None, 863 statement_kind: kind, 864 }; 865 866 let encl_item_id = self.tcx.hir().get_parent_item(expr.hir_id); 867 868 if let Some(hir::Node::Item(hir::Item { 869 kind: hir::ItemKind::Fn(..), 870 span: encl_fn_span, 871 .. 872 })) 873 | Some(hir::Node::TraitItem(hir::TraitItem { 874 kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)), 875 span: encl_fn_span, 876 .. 877 })) 878 | Some(hir::Node::ImplItem(hir::ImplItem { 879 kind: hir::ImplItemKind::Fn(..), 880 span: encl_fn_span, 881 .. 882 })) = self.tcx.hir().find_by_def_id(encl_item_id.def_id) 883 { 884 // We are inside a function body, so reporting "return statement 885 // outside of function body" needs an explanation. 886 887 let encl_body_owner_id = self.tcx.hir().enclosing_body_owner(expr.hir_id); 888 889 // If this didn't hold, we would not have to report an error in 890 // the first place. 891 assert_ne!(encl_item_id.def_id, encl_body_owner_id); 892 893 let encl_body_id = self.tcx.hir().body_owned_by(encl_body_owner_id); 894 let encl_body = self.tcx.hir().body(encl_body_id); 895 896 err.encl_body_span = Some(encl_body.value.span); 897 err.encl_fn_span = Some(*encl_fn_span); 898 } 899 900 self.tcx.sess.emit_err(err); 901 } 902 point_at_return_for_opaque_ty_error( &self, errors: &mut Vec<traits::FulfillmentError<'tcx>>, span: Span, return_expr_ty: Ty<'tcx>, return_span: Span, )903 fn point_at_return_for_opaque_ty_error( 904 &self, 905 errors: &mut Vec<traits::FulfillmentError<'tcx>>, 906 span: Span, 907 return_expr_ty: Ty<'tcx>, 908 return_span: Span, 909 ) { 910 // Don't point at the whole block if it's empty 911 if span == return_span { 912 return; 913 } 914 for err in errors { 915 let cause = &mut err.obligation.cause; 916 if let ObligationCauseCode::OpaqueReturnType(None) = cause.code() { 917 let new_cause = ObligationCause::new( 918 cause.span, 919 cause.body_id, 920 ObligationCauseCode::OpaqueReturnType(Some((return_expr_ty, span))), 921 ); 922 *cause = new_cause; 923 } 924 } 925 } 926 check_lhs_assignable( &self, lhs: &'tcx hir::Expr<'tcx>, err_code: &'static str, op_span: Span, adjust_err: impl FnOnce(&mut Diagnostic), )927 pub(crate) fn check_lhs_assignable( 928 &self, 929 lhs: &'tcx hir::Expr<'tcx>, 930 err_code: &'static str, 931 op_span: Span, 932 adjust_err: impl FnOnce(&mut Diagnostic), 933 ) { 934 if lhs.is_syntactic_place_expr() { 935 return; 936 } 937 938 // FIXME: Make this use Diagnostic once error codes can be dynamically set. 939 let mut err = self.tcx.sess.struct_span_err_with_code( 940 op_span, 941 "invalid left-hand side of assignment", 942 DiagnosticId::Error(err_code.into()), 943 ); 944 err.span_label(lhs.span, "cannot assign to this expression"); 945 946 self.comes_from_while_condition(lhs.hir_id, |expr| { 947 err.span_suggestion_verbose( 948 expr.span.shrink_to_lo(), 949 "you might have meant to use pattern destructuring", 950 "let ", 951 Applicability::MachineApplicable, 952 ); 953 }); 954 955 adjust_err(&mut err); 956 957 err.emit(); 958 } 959 960 // Check if an expression `original_expr_id` comes from the condition of a while loop, 961 /// as opposed from the body of a while loop, which we can naively check by iterating 962 /// parents until we find a loop... comes_from_while_condition( &self, original_expr_id: HirId, then: impl FnOnce(&hir::Expr<'_>), )963 pub(super) fn comes_from_while_condition( 964 &self, 965 original_expr_id: HirId, 966 then: impl FnOnce(&hir::Expr<'_>), 967 ) { 968 let mut parent = self.tcx.hir().parent_id(original_expr_id); 969 while let Some(node) = self.tcx.hir().find(parent) { 970 match node { 971 hir::Node::Expr(hir::Expr { 972 kind: 973 hir::ExprKind::Loop( 974 hir::Block { 975 expr: 976 Some(hir::Expr { 977 kind: 978 hir::ExprKind::Match(expr, ..) | hir::ExprKind::If(expr, ..), 979 .. 980 }), 981 .. 982 }, 983 _, 984 hir::LoopSource::While, 985 _, 986 ), 987 .. 988 }) => { 989 // Check if our original expression is a child of the condition of a while loop 990 let expr_is_ancestor = std::iter::successors(Some(original_expr_id), |id| { 991 self.tcx.hir().opt_parent_id(*id) 992 }) 993 .take_while(|id| *id != parent) 994 .any(|id| id == expr.hir_id); 995 // if it is, then we have a situation like `while Some(0) = value.get(0) {`, 996 // where `while let` was more likely intended. 997 if expr_is_ancestor { 998 then(expr); 999 } 1000 break; 1001 } 1002 hir::Node::Item(_) 1003 | hir::Node::ImplItem(_) 1004 | hir::Node::TraitItem(_) 1005 | hir::Node::Crate(_) => break, 1006 _ => { 1007 parent = self.tcx.hir().parent_id(parent); 1008 } 1009 } 1010 } 1011 } 1012 1013 // A generic function for checking the 'then' and 'else' clauses in an 'if' 1014 // or 'if-else' expression. check_then_else( &self, cond_expr: &'tcx hir::Expr<'tcx>, then_expr: &'tcx hir::Expr<'tcx>, opt_else_expr: Option<&'tcx hir::Expr<'tcx>>, sp: Span, orig_expected: Expectation<'tcx>, ) -> Ty<'tcx>1015 fn check_then_else( 1016 &self, 1017 cond_expr: &'tcx hir::Expr<'tcx>, 1018 then_expr: &'tcx hir::Expr<'tcx>, 1019 opt_else_expr: Option<&'tcx hir::Expr<'tcx>>, 1020 sp: Span, 1021 orig_expected: Expectation<'tcx>, 1022 ) -> Ty<'tcx> { 1023 let cond_ty = self.check_expr_has_type_or_error(cond_expr, self.tcx.types.bool, |_| {}); 1024 1025 self.warn_if_unreachable( 1026 cond_expr.hir_id, 1027 then_expr.span, 1028 "block in `if` or `while` expression", 1029 ); 1030 1031 let cond_diverges = self.diverges.get(); 1032 self.diverges.set(Diverges::Maybe); 1033 1034 let expected = orig_expected.adjust_for_branches(self); 1035 let then_ty = self.check_expr_with_expectation(then_expr, expected); 1036 let then_diverges = self.diverges.get(); 1037 self.diverges.set(Diverges::Maybe); 1038 1039 // We've already taken the expected type's preferences 1040 // into account when typing the `then` branch. To figure 1041 // out the initial shot at a LUB, we thus only consider 1042 // `expected` if it represents a *hard* constraint 1043 // (`only_has_type`); otherwise, we just go with a 1044 // fresh type variable. 1045 let coerce_to_ty = expected.coercion_target_type(self, sp); 1046 let mut coerce: DynamicCoerceMany<'_> = CoerceMany::new(coerce_to_ty); 1047 1048 coerce.coerce(self, &self.misc(sp), then_expr, then_ty); 1049 1050 if let Some(else_expr) = opt_else_expr { 1051 let else_ty = self.check_expr_with_expectation(else_expr, expected); 1052 let else_diverges = self.diverges.get(); 1053 1054 let opt_suggest_box_span = self.opt_suggest_box_span(then_ty, else_ty, orig_expected); 1055 let if_cause = self.if_cause( 1056 sp, 1057 cond_expr.span, 1058 then_expr, 1059 else_expr, 1060 then_ty, 1061 else_ty, 1062 opt_suggest_box_span, 1063 ); 1064 1065 coerce.coerce(self, &if_cause, else_expr, else_ty); 1066 1067 // We won't diverge unless both branches do (or the condition does). 1068 self.diverges.set(cond_diverges | then_diverges & else_diverges); 1069 } else { 1070 self.if_fallback_coercion(sp, then_expr, &mut coerce); 1071 1072 // If the condition is false we can't diverge. 1073 self.diverges.set(cond_diverges); 1074 } 1075 1076 let result_ty = coerce.complete(self); 1077 if let Err(guar) = cond_ty.error_reported() { 1078 Ty::new_error(self.tcx, guar) 1079 } else { 1080 result_ty 1081 } 1082 } 1083 1084 /// Type check assignment expression `expr` of form `lhs = rhs`. 1085 /// The expected type is `()` and is passed to the function for the purposes of diagnostics. check_expr_assign( &self, expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, lhs: &'tcx hir::Expr<'tcx>, rhs: &'tcx hir::Expr<'tcx>, span: Span, ) -> Ty<'tcx>1086 fn check_expr_assign( 1087 &self, 1088 expr: &'tcx hir::Expr<'tcx>, 1089 expected: Expectation<'tcx>, 1090 lhs: &'tcx hir::Expr<'tcx>, 1091 rhs: &'tcx hir::Expr<'tcx>, 1092 span: Span, 1093 ) -> Ty<'tcx> { 1094 let expected_ty = expected.coercion_target_type(self, expr.span); 1095 if expected_ty == self.tcx.types.bool { 1096 // The expected type is `bool` but this will result in `()` so we can reasonably 1097 // say that the user intended to write `lhs == rhs` instead of `lhs = rhs`. 1098 // The likely cause of this is `if foo = bar { .. }`. 1099 let actual_ty = Ty::new_unit(self.tcx); 1100 let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap(); 1101 let lhs_ty = self.check_expr(&lhs); 1102 let rhs_ty = self.check_expr(&rhs); 1103 let (applicability, eq) = if self.can_coerce(rhs_ty, lhs_ty) { 1104 (Applicability::MachineApplicable, true) 1105 } else if let ExprKind::Binary( 1106 Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. }, 1107 _, 1108 rhs_expr, 1109 ) = lhs.kind 1110 { 1111 // if x == 1 && y == 2 { .. } 1112 // + 1113 let actual_lhs_ty = self.check_expr(&rhs_expr); 1114 (Applicability::MaybeIncorrect, self.can_coerce(rhs_ty, actual_lhs_ty)) 1115 } else if let ExprKind::Binary( 1116 Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. }, 1117 lhs_expr, 1118 _, 1119 ) = rhs.kind 1120 { 1121 // if x == 1 && y == 2 { .. } 1122 // + 1123 let actual_rhs_ty = self.check_expr(&lhs_expr); 1124 (Applicability::MaybeIncorrect, self.can_coerce(actual_rhs_ty, lhs_ty)) 1125 } else { 1126 (Applicability::MaybeIncorrect, false) 1127 }; 1128 if !lhs.is_syntactic_place_expr() 1129 && lhs.is_approximately_pattern() 1130 && !matches!(lhs.kind, hir::ExprKind::Lit(_)) 1131 { 1132 // Do not suggest `if let x = y` as `==` is way more likely to be the intention. 1133 let hir = self.tcx.hir(); 1134 if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) = 1135 hir.get_parent(hir.parent_id(expr.hir_id)) 1136 { 1137 err.span_suggestion_verbose( 1138 expr.span.shrink_to_lo(), 1139 "you might have meant to use pattern matching", 1140 "let ", 1141 applicability, 1142 ); 1143 }; 1144 } 1145 if eq { 1146 err.span_suggestion_verbose( 1147 span.shrink_to_hi(), 1148 "you might have meant to compare for equality", 1149 '=', 1150 applicability, 1151 ); 1152 } 1153 1154 // If the assignment expression itself is ill-formed, don't 1155 // bother emitting another error 1156 let reported = err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error()); 1157 return Ty::new_error(self.tcx, reported); 1158 } 1159 1160 let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); 1161 1162 let suggest_deref_binop = |err: &mut Diagnostic, rhs_ty: Ty<'tcx>| { 1163 if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) { 1164 // Can only assign if the type is sized, so if `DerefMut` yields a type that is 1165 // unsized, do not suggest dereferencing it. 1166 let lhs_deref_ty_is_sized = self 1167 .infcx 1168 .type_implements_trait( 1169 self.tcx.require_lang_item(LangItem::Sized, None), 1170 [lhs_deref_ty], 1171 self.param_env, 1172 ) 1173 .may_apply(); 1174 if lhs_deref_ty_is_sized && self.can_coerce(rhs_ty, lhs_deref_ty) { 1175 err.span_suggestion_verbose( 1176 lhs.span.shrink_to_lo(), 1177 "consider dereferencing here to assign to the mutably borrowed value", 1178 "*", 1179 Applicability::MachineApplicable, 1180 ); 1181 } 1182 } 1183 }; 1184 1185 // This is (basically) inlined `check_expr_coercible_to_type`, but we want 1186 // to suggest an additional fixup here in `suggest_deref_binop`. 1187 let rhs_ty = self.check_expr_with_hint(&rhs, lhs_ty); 1188 if let (_, Some(mut diag)) = 1189 self.demand_coerce_diag(rhs, rhs_ty, lhs_ty, Some(lhs), AllowTwoPhase::No) 1190 { 1191 suggest_deref_binop(&mut diag, rhs_ty); 1192 diag.emit(); 1193 } 1194 1195 self.check_lhs_assignable(lhs, "E0070", span, |err| { 1196 if let Some(rhs_ty) = self.typeck_results.borrow().expr_ty_opt(rhs) { 1197 suggest_deref_binop(err, rhs_ty); 1198 } 1199 }); 1200 1201 self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized); 1202 1203 if let Err(guar) = (lhs_ty, rhs_ty).error_reported() { 1204 Ty::new_error(self.tcx, guar) 1205 } else { 1206 Ty::new_unit(self.tcx) 1207 } 1208 } 1209 check_expr_let(&self, let_expr: &'tcx hir::Let<'tcx>) -> Ty<'tcx>1210 pub(super) fn check_expr_let(&self, let_expr: &'tcx hir::Let<'tcx>) -> Ty<'tcx> { 1211 // for let statements, this is done in check_stmt 1212 let init = let_expr.init; 1213 self.warn_if_unreachable(init.hir_id, init.span, "block in `let` expression"); 1214 // otherwise check exactly as a let statement 1215 self.check_decl(let_expr.into()); 1216 // but return a bool, for this is a boolean expression 1217 self.tcx.types.bool 1218 } 1219 check_expr_loop( &self, body: &'tcx hir::Block<'tcx>, source: hir::LoopSource, expected: Expectation<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx>1220 fn check_expr_loop( 1221 &self, 1222 body: &'tcx hir::Block<'tcx>, 1223 source: hir::LoopSource, 1224 expected: Expectation<'tcx>, 1225 expr: &'tcx hir::Expr<'tcx>, 1226 ) -> Ty<'tcx> { 1227 let coerce = match source { 1228 // you can only use break with a value from a normal `loop { }` 1229 hir::LoopSource::Loop => { 1230 let coerce_to = expected.coercion_target_type(self, body.span); 1231 Some(CoerceMany::new(coerce_to)) 1232 } 1233 1234 hir::LoopSource::While | hir::LoopSource::ForLoop => None, 1235 }; 1236 1237 let ctxt = BreakableCtxt { 1238 coerce, 1239 may_break: false, // Will get updated if/when we find a `break`. 1240 }; 1241 1242 let (ctxt, ()) = self.with_breakable_ctxt(expr.hir_id, ctxt, || { 1243 self.check_block_no_value(&body); 1244 }); 1245 1246 if ctxt.may_break { 1247 // No way to know whether it's diverging because 1248 // of a `break` or an outer `break` or `return`. 1249 self.diverges.set(Diverges::Maybe); 1250 } 1251 1252 // If we permit break with a value, then result type is 1253 // the LUB of the breaks (possibly ! if none); else, it 1254 // is nil. This makes sense because infinite loops 1255 // (which would have type !) are only possible iff we 1256 // permit break with a value [1]. 1257 if ctxt.coerce.is_none() && !ctxt.may_break { 1258 // [1] 1259 self.tcx.sess.delay_span_bug(body.span, "no coercion, but loop may not break"); 1260 } 1261 ctxt.coerce.map(|c| c.complete(self)).unwrap_or_else(|| Ty::new_unit(self.tcx)) 1262 } 1263 1264 /// Checks a method call. check_method_call( &self, expr: &'tcx hir::Expr<'tcx>, segment: &hir::PathSegment<'_>, rcvr: &'tcx hir::Expr<'tcx>, args: &'tcx [hir::Expr<'tcx>], expected: Expectation<'tcx>, ) -> Ty<'tcx>1265 fn check_method_call( 1266 &self, 1267 expr: &'tcx hir::Expr<'tcx>, 1268 segment: &hir::PathSegment<'_>, 1269 rcvr: &'tcx hir::Expr<'tcx>, 1270 args: &'tcx [hir::Expr<'tcx>], 1271 expected: Expectation<'tcx>, 1272 ) -> Ty<'tcx> { 1273 let rcvr_t = self.check_expr(&rcvr); 1274 // no need to check for bot/err -- callee does that 1275 let rcvr_t = self.structurally_resolve_type(rcvr.span, rcvr_t); 1276 let span = segment.ident.span; 1277 1278 let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr, args) { 1279 Ok(method) => { 1280 // We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to 1281 // trigger this codepath causing `structurally_resolve_type` to emit an error. 1282 1283 self.enforce_context_effects(expr.hir_id, expr.span, method.def_id, method.substs); 1284 self.write_method_call(expr.hir_id, method); 1285 Ok(method) 1286 } 1287 Err(error) => { 1288 if segment.ident.name != kw::Empty { 1289 if let Some(mut err) = self.report_method_error( 1290 span, 1291 rcvr_t, 1292 segment.ident, 1293 SelfSource::MethodCall(rcvr), 1294 error, 1295 Some((rcvr, args)), 1296 expected, 1297 false, 1298 ) { 1299 err.emit(); 1300 } 1301 } 1302 Err(()) 1303 } 1304 }; 1305 1306 // Call the generic checker. 1307 self.check_method_argument_types(span, expr, method, &args, DontTupleArguments, expected) 1308 } 1309 check_expr_cast( &self, e: &'tcx hir::Expr<'tcx>, t: &'tcx hir::Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx>1310 fn check_expr_cast( 1311 &self, 1312 e: &'tcx hir::Expr<'tcx>, 1313 t: &'tcx hir::Ty<'tcx>, 1314 expr: &'tcx hir::Expr<'tcx>, 1315 ) -> Ty<'tcx> { 1316 // Find the type of `e`. Supply hints based on the type we are casting to, 1317 // if appropriate. 1318 let t_cast = self.to_ty_saving_user_provided_ty(t); 1319 let t_cast = self.resolve_vars_if_possible(t_cast); 1320 let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast)); 1321 let t_expr = self.resolve_vars_if_possible(t_expr); 1322 1323 // Eagerly check for some obvious errors. 1324 if let Err(guar) = (t_expr, t_cast).error_reported() { 1325 Ty::new_error(self.tcx, guar) 1326 } else { 1327 // Defer other checks until we're done type checking. 1328 let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); 1329 match cast::CastCheck::new( 1330 self, 1331 e, 1332 t_expr, 1333 t_cast, 1334 t.span, 1335 expr.span, 1336 self.param_env.constness(), 1337 ) { 1338 Ok(cast_check) => { 1339 debug!( 1340 "check_expr_cast: deferring cast from {:?} to {:?}: {:?}", 1341 t_cast, t_expr, cast_check, 1342 ); 1343 deferred_cast_checks.push(cast_check); 1344 t_cast 1345 } 1346 Err(guar) => Ty::new_error(self.tcx, guar), 1347 } 1348 } 1349 } 1350 check_expr_array( &self, args: &'tcx [hir::Expr<'tcx>], expected: Expectation<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx>1351 fn check_expr_array( 1352 &self, 1353 args: &'tcx [hir::Expr<'tcx>], 1354 expected: Expectation<'tcx>, 1355 expr: &'tcx hir::Expr<'tcx>, 1356 ) -> Ty<'tcx> { 1357 let element_ty = if !args.is_empty() { 1358 let coerce_to = expected 1359 .to_option(self) 1360 .and_then(|uty| match *uty.kind() { 1361 ty::Array(ty, _) | ty::Slice(ty) => Some(ty), 1362 _ => None, 1363 }) 1364 .unwrap_or_else(|| { 1365 self.next_ty_var(TypeVariableOrigin { 1366 kind: TypeVariableOriginKind::TypeInference, 1367 span: expr.span, 1368 }) 1369 }); 1370 let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args); 1371 assert_eq!(self.diverges.get(), Diverges::Maybe); 1372 for e in args { 1373 let e_ty = self.check_expr_with_hint(e, coerce_to); 1374 let cause = self.misc(e.span); 1375 coerce.coerce(self, &cause, e, e_ty); 1376 } 1377 coerce.complete(self) 1378 } else { 1379 self.next_ty_var(TypeVariableOrigin { 1380 kind: TypeVariableOriginKind::TypeInference, 1381 span: expr.span, 1382 }) 1383 }; 1384 let array_len = args.len() as u64; 1385 self.suggest_array_len(expr, array_len); 1386 Ty::new_array(self.tcx, element_ty, array_len) 1387 } 1388 suggest_array_len(&self, expr: &'tcx hir::Expr<'tcx>, array_len: u64)1389 fn suggest_array_len(&self, expr: &'tcx hir::Expr<'tcx>, array_len: u64) { 1390 let parent_node = self.tcx.hir().parent_iter(expr.hir_id).find(|(_, node)| { 1391 !matches!(node, hir::Node::Expr(hir::Expr { kind: hir::ExprKind::AddrOf(..), .. })) 1392 }); 1393 let Some((_, 1394 hir::Node::Local(hir::Local { ty: Some(ty), .. }) 1395 | hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _), .. })) 1396 ) = parent_node else { 1397 return 1398 }; 1399 if let hir::TyKind::Array(_, length) = ty.peel_refs().kind 1400 && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length 1401 && let Some(span) = self.tcx.hir().opt_span(hir_id) 1402 { 1403 match self.tcx.sess.diagnostic().steal_diagnostic(span, StashKey::UnderscoreForArrayLengths) { 1404 Some(mut err) => { 1405 err.span_suggestion( 1406 span, 1407 "consider specifying the array length", 1408 array_len, 1409 Applicability::MaybeIncorrect, 1410 ); 1411 err.emit(); 1412 } 1413 None => () 1414 } 1415 } 1416 } 1417 check_expr_const_block( &self, block: &'tcx hir::ConstBlock, expected: Expectation<'tcx>, _expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx>1418 fn check_expr_const_block( 1419 &self, 1420 block: &'tcx hir::ConstBlock, 1421 expected: Expectation<'tcx>, 1422 _expr: &'tcx hir::Expr<'tcx>, 1423 ) -> Ty<'tcx> { 1424 let body = self.tcx.hir().body(block.body); 1425 1426 // Create a new function context. 1427 let def_id = block.def_id; 1428 let fcx = FnCtxt::new(self, self.param_env.with_const(), def_id); 1429 crate::GatherLocalsVisitor::new(&fcx).visit_body(body); 1430 1431 let ty = fcx.check_expr_with_expectation(&body.value, expected); 1432 fcx.require_type_is_sized(ty, body.value.span, traits::ConstSized); 1433 fcx.write_ty(block.hir_id, ty); 1434 ty 1435 } 1436 check_expr_repeat( &self, element: &'tcx hir::Expr<'tcx>, count: &'tcx hir::ArrayLen, expected: Expectation<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx>1437 fn check_expr_repeat( 1438 &self, 1439 element: &'tcx hir::Expr<'tcx>, 1440 count: &'tcx hir::ArrayLen, 1441 expected: Expectation<'tcx>, 1442 expr: &'tcx hir::Expr<'tcx>, 1443 ) -> Ty<'tcx> { 1444 let tcx = self.tcx; 1445 let count = self.array_length_to_const(count); 1446 if let Some(count) = count.try_eval_target_usize(tcx, self.param_env) { 1447 self.suggest_array_len(expr, count); 1448 } 1449 1450 let uty = match expected { 1451 ExpectHasType(uty) => match *uty.kind() { 1452 ty::Array(ty, _) | ty::Slice(ty) => Some(ty), 1453 _ => None, 1454 }, 1455 _ => None, 1456 }; 1457 1458 let (element_ty, t) = match uty { 1459 Some(uty) => { 1460 self.check_expr_coercible_to_type(&element, uty, None); 1461 (uty, uty) 1462 } 1463 None => { 1464 let ty = self.next_ty_var(TypeVariableOrigin { 1465 kind: TypeVariableOriginKind::MiscVariable, 1466 span: element.span, 1467 }); 1468 let element_ty = self.check_expr_has_type_or_error(&element, ty, |_| {}); 1469 (element_ty, ty) 1470 } 1471 }; 1472 1473 if let Err(guar) = element_ty.error_reported() { 1474 return Ty::new_error(tcx, guar); 1475 } 1476 1477 self.check_repeat_element_needs_copy_bound(element, count, element_ty); 1478 1479 self.register_wf_obligation( 1480 Ty::new_array_with_const_len(tcx, t, count).into(), 1481 expr.span, 1482 traits::WellFormed(None), 1483 ); 1484 1485 Ty::new_array_with_const_len(tcx, t, count) 1486 } 1487 check_repeat_element_needs_copy_bound( &self, element: &hir::Expr<'_>, count: ty::Const<'tcx>, element_ty: Ty<'tcx>, )1488 fn check_repeat_element_needs_copy_bound( 1489 &self, 1490 element: &hir::Expr<'_>, 1491 count: ty::Const<'tcx>, 1492 element_ty: Ty<'tcx>, 1493 ) { 1494 let tcx = self.tcx; 1495 // Actual constants as the repeat element get inserted repeatedly instead of getting copied via Copy. 1496 match &element.kind { 1497 hir::ExprKind::ConstBlock(..) => return, 1498 hir::ExprKind::Path(qpath) => { 1499 let res = self.typeck_results.borrow().qpath_res(qpath, element.hir_id); 1500 if let Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::AnonConst, _) = res 1501 { 1502 return; 1503 } 1504 } 1505 _ => {} 1506 } 1507 // If someone calls a const fn, they can extract that call out into a separate constant (or a const 1508 // block in the future), so we check that to tell them that in the diagnostic. Does not affect typeck. 1509 let is_const_fn = match element.kind { 1510 hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() { 1511 ty::FnDef(def_id, _) => tcx.is_const_fn(def_id), 1512 _ => false, 1513 }, 1514 _ => false, 1515 }; 1516 1517 // If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we 1518 // don't copy that one element, we move it. Only check for Copy if the length is larger. 1519 if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) { 1520 let lang_item = self.tcx.require_lang_item(LangItem::Copy, None); 1521 let code = traits::ObligationCauseCode::RepeatElementCopy { is_const_fn }; 1522 self.require_type_meets(element_ty, element.span, code, lang_item); 1523 } 1524 } 1525 check_expr_tuple( &self, elts: &'tcx [hir::Expr<'tcx>], expected: Expectation<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx>1526 fn check_expr_tuple( 1527 &self, 1528 elts: &'tcx [hir::Expr<'tcx>], 1529 expected: Expectation<'tcx>, 1530 expr: &'tcx hir::Expr<'tcx>, 1531 ) -> Ty<'tcx> { 1532 let flds = expected.only_has_type(self).and_then(|ty| { 1533 let ty = self.resolve_vars_with_obligations(ty); 1534 match ty.kind() { 1535 ty::Tuple(flds) => Some(&flds[..]), 1536 _ => None, 1537 } 1538 }); 1539 1540 let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| match flds { 1541 Some(fs) if i < fs.len() => { 1542 let ety = fs[i]; 1543 self.check_expr_coercible_to_type(&e, ety, None); 1544 ety 1545 } 1546 _ => self.check_expr_with_expectation(&e, NoExpectation), 1547 }); 1548 let tuple = Ty::new_tup_from_iter(self.tcx, elt_ts_iter); 1549 if let Err(guar) = tuple.error_reported() { 1550 Ty::new_error(self.tcx, guar) 1551 } else { 1552 self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized); 1553 tuple 1554 } 1555 } 1556 check_expr_struct( &self, expr: &hir::Expr<'_>, expected: Expectation<'tcx>, qpath: &QPath<'_>, fields: &'tcx [hir::ExprField<'tcx>], base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, ) -> Ty<'tcx>1557 fn check_expr_struct( 1558 &self, 1559 expr: &hir::Expr<'_>, 1560 expected: Expectation<'tcx>, 1561 qpath: &QPath<'_>, 1562 fields: &'tcx [hir::ExprField<'tcx>], 1563 base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, 1564 ) -> Ty<'tcx> { 1565 // Find the relevant variant 1566 let (variant, adt_ty) = match self.check_struct_path(qpath, expr.hir_id) { 1567 Ok(data) => data, 1568 Err(guar) => { 1569 self.check_struct_fields_on_error(fields, base_expr); 1570 return Ty::new_error(self.tcx, guar); 1571 } 1572 }; 1573 1574 // Prohibit struct expressions when non-exhaustive flag is set. 1575 let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type"); 1576 if !adt.did().is_local() && variant.is_field_list_non_exhaustive() { 1577 self.tcx 1578 .sess 1579 .emit_err(StructExprNonExhaustive { span: expr.span, what: adt.variant_descr() }); 1580 } 1581 1582 self.check_expr_struct_fields( 1583 adt_ty, 1584 expected, 1585 expr.hir_id, 1586 qpath.span(), 1587 variant, 1588 fields, 1589 base_expr, 1590 expr.span, 1591 ); 1592 1593 self.require_type_is_sized(adt_ty, expr.span, traits::StructInitializerSized); 1594 adt_ty 1595 } 1596 check_expr_struct_fields( &self, adt_ty: Ty<'tcx>, expected: Expectation<'tcx>, expr_id: hir::HirId, span: Span, variant: &'tcx ty::VariantDef, ast_fields: &'tcx [hir::ExprField<'tcx>], base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, expr_span: Span, )1597 fn check_expr_struct_fields( 1598 &self, 1599 adt_ty: Ty<'tcx>, 1600 expected: Expectation<'tcx>, 1601 expr_id: hir::HirId, 1602 span: Span, 1603 variant: &'tcx ty::VariantDef, 1604 ast_fields: &'tcx [hir::ExprField<'tcx>], 1605 base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, 1606 expr_span: Span, 1607 ) { 1608 let tcx = self.tcx; 1609 1610 let expected_inputs = 1611 self.expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty]); 1612 let adt_ty_hint = if let Some(expected_inputs) = expected_inputs { 1613 expected_inputs.get(0).cloned().unwrap_or(adt_ty) 1614 } else { 1615 adt_ty 1616 }; 1617 // re-link the regions that EIfEO can erase. 1618 self.demand_eqtype(span, adt_ty_hint, adt_ty); 1619 1620 let ty::Adt(adt, substs) = adt_ty.kind() else { 1621 span_bug!(span, "non-ADT passed to check_expr_struct_fields"); 1622 }; 1623 let adt_kind = adt.adt_kind(); 1624 1625 let mut remaining_fields = variant 1626 .fields 1627 .iter_enumerated() 1628 .map(|(i, field)| (field.ident(tcx).normalize_to_macros_2_0(), (i, field))) 1629 .collect::<FxHashMap<_, _>>(); 1630 1631 let mut seen_fields = FxHashMap::default(); 1632 1633 let mut error_happened = false; 1634 1635 // Type-check each field. 1636 for (idx, field) in ast_fields.iter().enumerate() { 1637 let ident = tcx.adjust_ident(field.ident, variant.def_id); 1638 let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) { 1639 seen_fields.insert(ident, field.span); 1640 self.write_field_index(field.hir_id, i); 1641 1642 // We don't look at stability attributes on 1643 // struct-like enums (yet...), but it's definitely not 1644 // a bug to have constructed one. 1645 if adt_kind != AdtKind::Enum { 1646 tcx.check_stability(v_field.did, Some(expr_id), field.span, None); 1647 } 1648 1649 self.field_ty(field.span, v_field, substs) 1650 } else { 1651 error_happened = true; 1652 let guar = if let Some(prev_span) = seen_fields.get(&ident) { 1653 tcx.sess.emit_err(FieldMultiplySpecifiedInInitializer { 1654 span: field.ident.span, 1655 prev_span: *prev_span, 1656 ident, 1657 }) 1658 } else { 1659 self.report_unknown_field( 1660 adt_ty, 1661 variant, 1662 field, 1663 ast_fields, 1664 adt.variant_descr(), 1665 expr_span, 1666 ) 1667 }; 1668 1669 Ty::new_error(tcx, guar) 1670 }; 1671 1672 // Make sure to give a type to the field even if there's 1673 // an error, so we can continue type-checking. 1674 let ty = self.check_expr_with_hint(&field.expr, field_type); 1675 let (_, diag) = 1676 self.demand_coerce_diag(&field.expr, ty, field_type, None, AllowTwoPhase::No); 1677 1678 if let Some(mut diag) = diag { 1679 if idx == ast_fields.len() - 1 { 1680 if remaining_fields.is_empty() { 1681 self.suggest_fru_from_range(field, variant, substs, &mut diag); 1682 diag.emit(); 1683 } else { 1684 diag.stash(field.span, StashKey::MaybeFruTypo); 1685 } 1686 } else { 1687 diag.emit(); 1688 } 1689 } 1690 } 1691 1692 // Make sure the programmer specified correct number of fields. 1693 if adt_kind == AdtKind::Union { 1694 if ast_fields.len() != 1 { 1695 struct_span_err!( 1696 tcx.sess, 1697 span, 1698 E0784, 1699 "union expressions should have exactly one field", 1700 ) 1701 .emit(); 1702 } 1703 } 1704 1705 // If check_expr_struct_fields hit an error, do not attempt to populate 1706 // the fields with the base_expr. This could cause us to hit errors later 1707 // when certain fields are assumed to exist that in fact do not. 1708 if error_happened { 1709 if let Some(base_expr) = base_expr { 1710 self.check_expr(base_expr); 1711 } 1712 return; 1713 } 1714 1715 if let Some(base_expr) = base_expr { 1716 // FIXME: We are currently creating two branches here in order to maintain 1717 // consistency. But they should be merged as much as possible. 1718 let fru_tys = if self.tcx.features().type_changing_struct_update { 1719 if adt.is_struct() { 1720 // Make some fresh substitutions for our ADT type. 1721 let fresh_substs = self.fresh_substs_for_item(base_expr.span, adt.did()); 1722 // We do subtyping on the FRU fields first, so we can 1723 // learn exactly what types we expect the base expr 1724 // needs constrained to be compatible with the struct 1725 // type we expect from the expectation value. 1726 let fru_tys = variant 1727 .fields 1728 .iter() 1729 .map(|f| { 1730 let fru_ty = self.normalize( 1731 expr_span, 1732 self.field_ty(base_expr.span, f, fresh_substs), 1733 ); 1734 let ident = self.tcx.adjust_ident(f.ident(self.tcx), variant.def_id); 1735 if let Some(_) = remaining_fields.remove(&ident) { 1736 let target_ty = self.field_ty(base_expr.span, f, substs); 1737 let cause = self.misc(base_expr.span); 1738 match self.at(&cause, self.param_env).sup( 1739 DefineOpaqueTypes::No, 1740 target_ty, 1741 fru_ty, 1742 ) { 1743 Ok(InferOk { obligations, value: () }) => { 1744 self.register_predicates(obligations) 1745 } 1746 Err(_) => { 1747 // This should never happen, since we're just subtyping the 1748 // remaining_fields, but it's fine to emit this, I guess. 1749 self.err_ctxt() 1750 .report_mismatched_types( 1751 &cause, 1752 target_ty, 1753 fru_ty, 1754 FieldMisMatch(variant.name, ident.name), 1755 ) 1756 .emit(); 1757 } 1758 } 1759 } 1760 self.resolve_vars_if_possible(fru_ty) 1761 }) 1762 .collect(); 1763 // The use of fresh substs that we have subtyped against 1764 // our base ADT type's fields allows us to guide inference 1765 // along so that, e.g. 1766 // ``` 1767 // MyStruct<'a, F1, F2, const C: usize> { 1768 // f: F1, 1769 // // Other fields that reference `'a`, `F2`, and `C` 1770 // } 1771 // 1772 // let x = MyStruct { 1773 // f: 1usize, 1774 // ..other_struct 1775 // }; 1776 // ``` 1777 // will have the `other_struct` expression constrained to 1778 // `MyStruct<'a, _, F2, C>`, as opposed to just `_`... 1779 // This is important to allow coercions to happen in 1780 // `other_struct` itself. See `coerce-in-base-expr.rs`. 1781 let fresh_base_ty = Ty::new_adt(self.tcx, *adt, fresh_substs); 1782 self.check_expr_has_type_or_error( 1783 base_expr, 1784 self.resolve_vars_if_possible(fresh_base_ty), 1785 |_| {}, 1786 ); 1787 fru_tys 1788 } else { 1789 // Check the base_expr, regardless of a bad expected adt_ty, so we can get 1790 // type errors on that expression, too. 1791 self.check_expr(base_expr); 1792 self.tcx 1793 .sess 1794 .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span }); 1795 return; 1796 } 1797 } else { 1798 self.check_expr_has_type_or_error(base_expr, adt_ty, |_| { 1799 let base_ty = self.typeck_results.borrow().expr_ty(*base_expr); 1800 let same_adt = matches!((adt_ty.kind(), base_ty.kind()), 1801 (ty::Adt(adt, _), ty::Adt(base_adt, _)) if adt == base_adt); 1802 if self.tcx.sess.is_nightly_build() && same_adt { 1803 feature_err( 1804 &self.tcx.sess.parse_sess, 1805 sym::type_changing_struct_update, 1806 base_expr.span, 1807 "type changing struct updating is experimental", 1808 ) 1809 .emit(); 1810 } 1811 }); 1812 match adt_ty.kind() { 1813 ty::Adt(adt, substs) if adt.is_struct() => variant 1814 .fields 1815 .iter() 1816 .map(|f| self.normalize(expr_span, f.ty(self.tcx, substs))) 1817 .collect(), 1818 _ => { 1819 self.tcx 1820 .sess 1821 .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span }); 1822 return; 1823 } 1824 } 1825 }; 1826 self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr_id, fru_tys); 1827 } else if adt_kind != AdtKind::Union && !remaining_fields.is_empty() { 1828 debug!(?remaining_fields); 1829 let private_fields: Vec<&ty::FieldDef> = variant 1830 .fields 1831 .iter() 1832 .filter(|field| !field.vis.is_accessible_from(tcx.parent_module(expr_id), tcx)) 1833 .collect(); 1834 1835 if !private_fields.is_empty() { 1836 self.report_private_fields(adt_ty, span, private_fields, ast_fields); 1837 } else { 1838 self.report_missing_fields( 1839 adt_ty, 1840 span, 1841 remaining_fields, 1842 variant, 1843 ast_fields, 1844 substs, 1845 ); 1846 } 1847 } 1848 } 1849 check_struct_fields_on_error( &self, fields: &'tcx [hir::ExprField<'tcx>], base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, )1850 fn check_struct_fields_on_error( 1851 &self, 1852 fields: &'tcx [hir::ExprField<'tcx>], 1853 base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, 1854 ) { 1855 for field in fields { 1856 self.check_expr(&field.expr); 1857 } 1858 if let Some(base) = *base_expr { 1859 self.check_expr(&base); 1860 } 1861 } 1862 1863 /// Report an error for a struct field expression when there are fields which aren't provided. 1864 /// 1865 /// ```text 1866 /// error: missing field `you_can_use_this_field` in initializer of `foo::Foo` 1867 /// --> src/main.rs:8:5 1868 /// | 1869 /// 8 | foo::Foo {}; 1870 /// | ^^^^^^^^ missing `you_can_use_this_field` 1871 /// 1872 /// error: aborting due to previous error 1873 /// ``` report_missing_fields( &self, adt_ty: Ty<'tcx>, span: Span, remaining_fields: FxHashMap<Ident, (FieldIdx, &ty::FieldDef)>, variant: &'tcx ty::VariantDef, ast_fields: &'tcx [hir::ExprField<'tcx>], substs: SubstsRef<'tcx>, )1874 fn report_missing_fields( 1875 &self, 1876 adt_ty: Ty<'tcx>, 1877 span: Span, 1878 remaining_fields: FxHashMap<Ident, (FieldIdx, &ty::FieldDef)>, 1879 variant: &'tcx ty::VariantDef, 1880 ast_fields: &'tcx [hir::ExprField<'tcx>], 1881 substs: SubstsRef<'tcx>, 1882 ) { 1883 let len = remaining_fields.len(); 1884 1885 let mut displayable_field_names: Vec<&str> = 1886 remaining_fields.keys().map(|ident| ident.as_str()).collect(); 1887 // sorting &str primitives here, sort_unstable is ok 1888 displayable_field_names.sort_unstable(); 1889 1890 let mut truncated_fields_error = String::new(); 1891 let remaining_fields_names = match &displayable_field_names[..] { 1892 [field1] => format!("`{}`", field1), 1893 [field1, field2] => format!("`{field1}` and `{field2}`"), 1894 [field1, field2, field3] => format!("`{field1}`, `{field2}` and `{field3}`"), 1895 _ => { 1896 truncated_fields_error = 1897 format!(" and {} other field{}", len - 3, pluralize!(len - 3)); 1898 displayable_field_names 1899 .iter() 1900 .take(3) 1901 .map(|n| format!("`{n}`")) 1902 .collect::<Vec<_>>() 1903 .join(", ") 1904 } 1905 }; 1906 1907 let mut err = struct_span_err!( 1908 self.tcx.sess, 1909 span, 1910 E0063, 1911 "missing field{} {}{} in initializer of `{}`", 1912 pluralize!(len), 1913 remaining_fields_names, 1914 truncated_fields_error, 1915 adt_ty 1916 ); 1917 err.span_label(span, format!("missing {remaining_fields_names}{truncated_fields_error}")); 1918 1919 if let Some(last) = ast_fields.last() { 1920 self.suggest_fru_from_range(last, variant, substs, &mut err); 1921 } 1922 1923 err.emit(); 1924 } 1925 1926 /// If the last field is a range literal, but it isn't supposed to be, then they probably 1927 /// meant to use functional update syntax. suggest_fru_from_range( &self, last_expr_field: &hir::ExprField<'tcx>, variant: &ty::VariantDef, substs: SubstsRef<'tcx>, err: &mut Diagnostic, )1928 fn suggest_fru_from_range( 1929 &self, 1930 last_expr_field: &hir::ExprField<'tcx>, 1931 variant: &ty::VariantDef, 1932 substs: SubstsRef<'tcx>, 1933 err: &mut Diagnostic, 1934 ) { 1935 // I don't use 'is_range_literal' because only double-sided, half-open ranges count. 1936 if let ExprKind::Struct( 1937 QPath::LangItem(LangItem::Range, ..), 1938 [range_start, range_end], 1939 _, 1940 ) = last_expr_field.expr.kind 1941 && let variant_field = 1942 variant.fields.iter().find(|field| field.ident(self.tcx) == last_expr_field.ident) 1943 && let range_def_id = self.tcx.lang_items().range_struct() 1944 && variant_field 1945 .and_then(|field| field.ty(self.tcx, substs).ty_adt_def()) 1946 .map(|adt| adt.did()) 1947 != range_def_id 1948 { 1949 // Suppress any range expr type mismatches 1950 if let Some(mut diag) = self 1951 .tcx 1952 .sess 1953 .diagnostic() 1954 .steal_diagnostic(last_expr_field.span, StashKey::MaybeFruTypo) 1955 { 1956 diag.delay_as_bug(); 1957 } 1958 1959 // Use a (somewhat arbitrary) filtering heuristic to avoid printing 1960 // expressions that are either too long, or have control character 1961 //such as newlines in them. 1962 let expr = self 1963 .tcx 1964 .sess 1965 .source_map() 1966 .span_to_snippet(range_end.expr.span) 1967 .ok() 1968 .filter(|s| s.len() < 25 && !s.contains(|c: char| c.is_control())); 1969 1970 let fru_span = self 1971 .tcx 1972 .sess 1973 .source_map() 1974 .span_extend_while(range_start.span, |c| c.is_whitespace()) 1975 .unwrap_or(range_start.span).shrink_to_hi().to(range_end.span); 1976 1977 err.subdiagnostic(TypeMismatchFruTypo { 1978 expr_span: range_start.span, 1979 fru_span, 1980 expr, 1981 }); 1982 } 1983 } 1984 1985 /// Report an error for a struct field expression when there are invisible fields. 1986 /// 1987 /// ```text 1988 /// error: cannot construct `Foo` with struct literal syntax due to private fields 1989 /// --> src/main.rs:8:5 1990 /// | 1991 /// 8 | foo::Foo {}; 1992 /// | ^^^^^^^^ 1993 /// 1994 /// error: aborting due to previous error 1995 /// ``` report_private_fields( &self, adt_ty: Ty<'tcx>, span: Span, private_fields: Vec<&ty::FieldDef>, used_fields: &'tcx [hir::ExprField<'tcx>], )1996 fn report_private_fields( 1997 &self, 1998 adt_ty: Ty<'tcx>, 1999 span: Span, 2000 private_fields: Vec<&ty::FieldDef>, 2001 used_fields: &'tcx [hir::ExprField<'tcx>], 2002 ) { 2003 let mut err = 2004 self.tcx.sess.struct_span_err( 2005 span, 2006 format!( 2007 "cannot construct `{adt_ty}` with struct literal syntax due to private fields", 2008 ), 2009 ); 2010 let (used_private_fields, remaining_private_fields): ( 2011 Vec<(Symbol, Span, bool)>, 2012 Vec<(Symbol, Span, bool)>, 2013 ) = private_fields 2014 .iter() 2015 .map(|field| { 2016 match used_fields.iter().find(|used_field| field.name == used_field.ident.name) { 2017 Some(used_field) => (field.name, used_field.span, true), 2018 None => (field.name, self.tcx.def_span(field.did), false), 2019 } 2020 }) 2021 .partition(|field| field.2); 2022 err.span_labels(used_private_fields.iter().map(|(_, span, _)| *span), "private field"); 2023 if !remaining_private_fields.is_empty() { 2024 let remaining_private_fields_len = remaining_private_fields.len(); 2025 let names = match &remaining_private_fields 2026 .iter() 2027 .map(|(name, _, _)| name) 2028 .collect::<Vec<_>>()[..] 2029 { 2030 _ if remaining_private_fields_len > 6 => String::new(), 2031 [name] => format!("`{name}` "), 2032 [names @ .., last] => { 2033 let names = names.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>(); 2034 format!("{} and `{last}` ", names.join(", ")) 2035 } 2036 [] => unreachable!(), 2037 }; 2038 err.note(format!( 2039 "... and other private field{s} {names}that {were} not provided", 2040 s = pluralize!(remaining_private_fields_len), 2041 were = pluralize!("was", remaining_private_fields_len), 2042 )); 2043 } 2044 err.emit(); 2045 } 2046 report_unknown_field( &self, ty: Ty<'tcx>, variant: &'tcx ty::VariantDef, field: &hir::ExprField<'_>, skip_fields: &[hir::ExprField<'_>], kind_name: &str, expr_span: Span, ) -> ErrorGuaranteed2047 fn report_unknown_field( 2048 &self, 2049 ty: Ty<'tcx>, 2050 variant: &'tcx ty::VariantDef, 2051 field: &hir::ExprField<'_>, 2052 skip_fields: &[hir::ExprField<'_>], 2053 kind_name: &str, 2054 expr_span: Span, 2055 ) -> ErrorGuaranteed { 2056 if variant.is_recovered() { 2057 let guar = self 2058 .tcx 2059 .sess 2060 .delay_span_bug(expr_span, "parser recovered but no error was emitted"); 2061 self.set_tainted_by_errors(guar); 2062 return guar; 2063 } 2064 let mut err = self.err_ctxt().type_error_struct_with_diag( 2065 field.ident.span, 2066 |actual| match ty.kind() { 2067 ty::Adt(adt, ..) if adt.is_enum() => struct_span_err!( 2068 self.tcx.sess, 2069 field.ident.span, 2070 E0559, 2071 "{} `{}::{}` has no field named `{}`", 2072 kind_name, 2073 actual, 2074 variant.name, 2075 field.ident 2076 ), 2077 _ => struct_span_err!( 2078 self.tcx.sess, 2079 field.ident.span, 2080 E0560, 2081 "{} `{}` has no field named `{}`", 2082 kind_name, 2083 actual, 2084 field.ident 2085 ), 2086 }, 2087 ty, 2088 ); 2089 2090 let variant_ident_span = self.tcx.def_ident_span(variant.def_id).unwrap(); 2091 match variant.ctor_kind() { 2092 Some(CtorKind::Fn) => match ty.kind() { 2093 ty::Adt(adt, ..) if adt.is_enum() => { 2094 err.span_label( 2095 variant_ident_span, 2096 format!( 2097 "`{adt}::{variant}` defined here", 2098 adt = ty, 2099 variant = variant.name, 2100 ), 2101 ); 2102 err.span_label(field.ident.span, "field does not exist"); 2103 err.span_suggestion_verbose( 2104 expr_span, 2105 format!( 2106 "`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax", 2107 adt = ty, 2108 variant = variant.name, 2109 ), 2110 format!( 2111 "{adt}::{variant}(/* fields */)", 2112 adt = ty, 2113 variant = variant.name, 2114 ), 2115 Applicability::HasPlaceholders, 2116 ); 2117 } 2118 _ => { 2119 err.span_label(variant_ident_span, format!("`{adt}` defined here", adt = ty)); 2120 err.span_label(field.ident.span, "field does not exist"); 2121 err.span_suggestion_verbose( 2122 expr_span, 2123 format!( 2124 "`{adt}` is a tuple {kind_name}, use the appropriate syntax", 2125 adt = ty, 2126 kind_name = kind_name, 2127 ), 2128 format!("{adt}(/* fields */)", adt = ty), 2129 Applicability::HasPlaceholders, 2130 ); 2131 } 2132 }, 2133 _ => { 2134 // prevent all specified fields from being suggested 2135 let skip_fields: Vec<_> = skip_fields.iter().map(|x| x.ident.name).collect(); 2136 if let Some(field_name) = 2137 self.suggest_field_name(variant, field.ident.name, &skip_fields, expr_span) 2138 { 2139 err.span_suggestion( 2140 field.ident.span, 2141 "a field with a similar name exists", 2142 field_name, 2143 Applicability::MaybeIncorrect, 2144 ); 2145 } else { 2146 match ty.kind() { 2147 ty::Adt(adt, ..) => { 2148 if adt.is_enum() { 2149 err.span_label( 2150 field.ident.span, 2151 format!("`{}::{}` does not have this field", ty, variant.name), 2152 ); 2153 } else { 2154 err.span_label( 2155 field.ident.span, 2156 format!("`{ty}` does not have this field"), 2157 ); 2158 } 2159 let mut available_field_names = 2160 self.available_field_names(variant, expr_span); 2161 available_field_names 2162 .retain(|name| skip_fields.iter().all(|skip| name != skip)); 2163 if available_field_names.is_empty() { 2164 err.note("all struct fields are already assigned"); 2165 } else { 2166 err.note(format!( 2167 "available fields are: {}", 2168 self.name_series_display(available_field_names) 2169 )); 2170 } 2171 } 2172 _ => bug!("non-ADT passed to report_unknown_field"), 2173 } 2174 }; 2175 } 2176 } 2177 err.emit() 2178 } 2179 2180 // Return a hint about the closest match in field names suggest_field_name( &self, variant: &'tcx ty::VariantDef, field: Symbol, skip: &[Symbol], span: Span, ) -> Option<Symbol>2181 fn suggest_field_name( 2182 &self, 2183 variant: &'tcx ty::VariantDef, 2184 field: Symbol, 2185 skip: &[Symbol], 2186 // The span where stability will be checked 2187 span: Span, 2188 ) -> Option<Symbol> { 2189 let names = variant 2190 .fields 2191 .iter() 2192 .filter_map(|field| { 2193 // ignore already set fields and private fields from non-local crates 2194 // and unstable fields. 2195 if skip.iter().any(|&x| x == field.name) 2196 || (!variant.def_id.is_local() && !field.vis.is_public()) 2197 || matches!( 2198 self.tcx.eval_stability(field.did, None, span, None), 2199 stability::EvalResult::Deny { .. } 2200 ) 2201 { 2202 None 2203 } else { 2204 Some(field.name) 2205 } 2206 }) 2207 .collect::<Vec<Symbol>>(); 2208 2209 find_best_match_for_name(&names, field, None) 2210 } 2211 available_field_names( &self, variant: &'tcx ty::VariantDef, access_span: Span, ) -> Vec<Symbol>2212 fn available_field_names( 2213 &self, 2214 variant: &'tcx ty::VariantDef, 2215 access_span: Span, 2216 ) -> Vec<Symbol> { 2217 let body_owner_hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id); 2218 variant 2219 .fields 2220 .iter() 2221 .filter(|field| { 2222 let def_scope = self 2223 .tcx 2224 .adjust_ident_and_get_scope( 2225 field.ident(self.tcx), 2226 variant.def_id, 2227 body_owner_hir_id, 2228 ) 2229 .1; 2230 field.vis.is_accessible_from(def_scope, self.tcx) 2231 && !matches!( 2232 self.tcx.eval_stability(field.did, None, access_span, None), 2233 stability::EvalResult::Deny { .. } 2234 ) 2235 }) 2236 .filter(|field| !self.tcx.is_doc_hidden(field.did)) 2237 .map(|field| field.name) 2238 .collect() 2239 } 2240 name_series_display(&self, names: Vec<Symbol>) -> String2241 fn name_series_display(&self, names: Vec<Symbol>) -> String { 2242 // dynamic limit, to never omit just one field 2243 let limit = if names.len() == 6 { 6 } else { 5 }; 2244 let mut display = 2245 names.iter().take(limit).map(|n| format!("`{}`", n)).collect::<Vec<_>>().join(", "); 2246 if names.len() > limit { 2247 display = format!("{} ... and {} others", display, names.len() - limit); 2248 } 2249 display 2250 } 2251 2252 // Check field access expressions check_field( &self, expr: &'tcx hir::Expr<'tcx>, base: &'tcx hir::Expr<'tcx>, field: Ident, expected: Expectation<'tcx>, ) -> Ty<'tcx>2253 fn check_field( 2254 &self, 2255 expr: &'tcx hir::Expr<'tcx>, 2256 base: &'tcx hir::Expr<'tcx>, 2257 field: Ident, 2258 expected: Expectation<'tcx>, 2259 ) -> Ty<'tcx> { 2260 debug!("check_field(expr: {:?}, base: {:?}, field: {:?})", expr, base, field); 2261 let base_ty = self.check_expr(base); 2262 let base_ty = self.structurally_resolve_type(base.span, base_ty); 2263 let mut private_candidate = None; 2264 let mut autoderef = self.autoderef(expr.span, base_ty); 2265 while let Some((deref_base_ty, _)) = autoderef.next() { 2266 debug!("deref_base_ty: {:?}", deref_base_ty); 2267 match deref_base_ty.kind() { 2268 ty::Adt(base_def, substs) if !base_def.is_enum() => { 2269 debug!("struct named {:?}", deref_base_ty); 2270 let body_hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id); 2271 let (ident, def_scope) = 2272 self.tcx.adjust_ident_and_get_scope(field, base_def.did(), body_hir_id); 2273 let fields = &base_def.non_enum_variant().fields; 2274 if let Some((index, field)) = fields 2275 .iter_enumerated() 2276 .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == ident) 2277 { 2278 let field_ty = self.field_ty(expr.span, field, substs); 2279 // Save the index of all fields regardless of their visibility in case 2280 // of error recovery. 2281 self.write_field_index(expr.hir_id, index); 2282 let adjustments = self.adjust_steps(&autoderef); 2283 if field.vis.is_accessible_from(def_scope, self.tcx) { 2284 self.apply_adjustments(base, adjustments); 2285 self.register_predicates(autoderef.into_obligations()); 2286 2287 self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None); 2288 return field_ty; 2289 } 2290 private_candidate = Some((adjustments, base_def.did())); 2291 } 2292 } 2293 ty::Tuple(tys) => { 2294 if let Ok(index) = field.as_str().parse::<usize>() { 2295 if field.name == sym::integer(index) { 2296 if let Some(&field_ty) = tys.get(index) { 2297 let adjustments = self.adjust_steps(&autoderef); 2298 self.apply_adjustments(base, adjustments); 2299 self.register_predicates(autoderef.into_obligations()); 2300 2301 self.write_field_index(expr.hir_id, FieldIdx::from_usize(index)); 2302 return field_ty; 2303 } 2304 } 2305 } 2306 } 2307 _ => {} 2308 } 2309 } 2310 self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); 2311 2312 if let Some((adjustments, did)) = private_candidate { 2313 // (#90483) apply adjustments to avoid ExprUseVisitor from 2314 // creating erroneous projection. 2315 self.apply_adjustments(base, adjustments); 2316 let guar = self.ban_private_field_access( 2317 expr, 2318 base_ty, 2319 field, 2320 did, 2321 expected.only_has_type(self), 2322 ); 2323 return Ty::new_error(self.tcx(), guar); 2324 } 2325 2326 let guar = if field.name == kw::Empty { 2327 self.tcx.sess.delay_span_bug(field.span, "field name with no name") 2328 } else if self.method_exists( 2329 field, 2330 base_ty, 2331 expr.hir_id, 2332 true, 2333 expected.only_has_type(self), 2334 ) { 2335 self.ban_take_value_of_method(expr, base_ty, field) 2336 } else if !base_ty.is_primitive_ty() { 2337 self.ban_nonexisting_field(field, base, expr, base_ty) 2338 } else { 2339 let field_name = field.to_string(); 2340 let mut err = type_error_struct!( 2341 self.tcx().sess, 2342 field.span, 2343 base_ty, 2344 E0610, 2345 "`{base_ty}` is a primitive type and therefore doesn't have fields", 2346 ); 2347 let is_valid_suffix = |field: &str| { 2348 if field == "f32" || field == "f64" { 2349 return true; 2350 } 2351 let mut chars = field.chars().peekable(); 2352 match chars.peek() { 2353 Some('e') | Some('E') => { 2354 chars.next(); 2355 if let Some(c) = chars.peek() 2356 && !c.is_numeric() && *c != '-' && *c != '+' 2357 { 2358 return false; 2359 } 2360 while let Some(c) = chars.peek() { 2361 if !c.is_numeric() { 2362 break; 2363 } 2364 chars.next(); 2365 } 2366 } 2367 _ => (), 2368 } 2369 let suffix = chars.collect::<String>(); 2370 suffix.is_empty() || suffix == "f32" || suffix == "f64" 2371 }; 2372 let maybe_partial_suffix = |field: &str| -> Option<&str> { 2373 let first_chars = ['f', 'l']; 2374 if field.len() >= 1 2375 && field.to_lowercase().starts_with(first_chars) 2376 && field[1..].chars().all(|c| c.is_ascii_digit()) 2377 { 2378 if field.to_lowercase().starts_with(['f']) { Some("f32") } else { Some("f64") } 2379 } else { 2380 None 2381 } 2382 }; 2383 if let ty::Infer(ty::IntVar(_)) = base_ty.kind() 2384 && let ExprKind::Lit(Spanned { 2385 node: ast::LitKind::Int(_, ast::LitIntType::Unsuffixed), 2386 .. 2387 }) = base.kind 2388 && !base.span.from_expansion() 2389 { 2390 if is_valid_suffix(&field_name) { 2391 err.span_suggestion_verbose( 2392 field.span.shrink_to_lo(), 2393 "if intended to be a floating point literal, consider adding a `0` after the period", 2394 '0', 2395 Applicability::MaybeIncorrect, 2396 ); 2397 } else if let Some(correct_suffix) = maybe_partial_suffix(&field_name) { 2398 err.span_suggestion_verbose( 2399 field.span, 2400 format!("if intended to be a floating point literal, consider adding a `0` after the period and a `{correct_suffix}` suffix"), 2401 format!("0{correct_suffix}"), 2402 Applicability::MaybeIncorrect, 2403 ); 2404 } 2405 } 2406 err.emit() 2407 }; 2408 2409 Ty::new_error(self.tcx(), guar) 2410 } 2411 suggest_await_on_field_access( &self, err: &mut Diagnostic, field_ident: Ident, base: &'tcx hir::Expr<'tcx>, ty: Ty<'tcx>, )2412 fn suggest_await_on_field_access( 2413 &self, 2414 err: &mut Diagnostic, 2415 field_ident: Ident, 2416 base: &'tcx hir::Expr<'tcx>, 2417 ty: Ty<'tcx>, 2418 ) { 2419 let Some(output_ty) = self.get_impl_future_output_ty(ty) else { return; }; 2420 let mut add_label = true; 2421 if let ty::Adt(def, _) = output_ty.kind() { 2422 // no field access on enum type 2423 if !def.is_enum() { 2424 if def 2425 .non_enum_variant() 2426 .fields 2427 .iter() 2428 .any(|field| field.ident(self.tcx) == field_ident) 2429 { 2430 add_label = false; 2431 err.span_label( 2432 field_ident.span, 2433 "field not available in `impl Future`, but it is available in its `Output`", 2434 ); 2435 err.span_suggestion_verbose( 2436 base.span.shrink_to_hi(), 2437 "consider `await`ing on the `Future` and access the field of its `Output`", 2438 ".await", 2439 Applicability::MaybeIncorrect, 2440 ); 2441 } 2442 } 2443 } 2444 if add_label { 2445 err.span_label(field_ident.span, format!("field not found in `{ty}`")); 2446 } 2447 } 2448 ban_nonexisting_field( &self, ident: Ident, base: &'tcx hir::Expr<'tcx>, expr: &'tcx hir::Expr<'tcx>, base_ty: Ty<'tcx>, ) -> ErrorGuaranteed2449 fn ban_nonexisting_field( 2450 &self, 2451 ident: Ident, 2452 base: &'tcx hir::Expr<'tcx>, 2453 expr: &'tcx hir::Expr<'tcx>, 2454 base_ty: Ty<'tcx>, 2455 ) -> ErrorGuaranteed { 2456 debug!( 2457 "ban_nonexisting_field: field={:?}, base={:?}, expr={:?}, base_ty={:?}", 2458 ident, base, expr, base_ty 2459 ); 2460 let mut err = self.no_such_field_err(ident, base_ty, base.hir_id); 2461 2462 match *base_ty.peel_refs().kind() { 2463 ty::Array(_, len) => { 2464 self.maybe_suggest_array_indexing(&mut err, expr, base, ident, len); 2465 } 2466 ty::RawPtr(..) => { 2467 self.suggest_first_deref_field(&mut err, expr, base, ident); 2468 } 2469 ty::Adt(def, _) if !def.is_enum() => { 2470 self.suggest_fields_on_recordish(&mut err, def, ident, expr.span); 2471 } 2472 ty::Param(param_ty) => { 2473 self.point_at_param_definition(&mut err, param_ty); 2474 } 2475 ty::Alias(ty::Opaque, _) => { 2476 self.suggest_await_on_field_access(&mut err, ident, base, base_ty.peel_refs()); 2477 } 2478 _ => {} 2479 } 2480 2481 self.suggest_fn_call(&mut err, base, base_ty, |output_ty| { 2482 if let ty::Adt(def, _) = output_ty.kind() && !def.is_enum() { 2483 def.non_enum_variant().fields.iter().any(|field| { 2484 field.ident(self.tcx) == ident 2485 && field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx) 2486 }) 2487 } else if let ty::Tuple(tys) = output_ty.kind() 2488 && let Ok(idx) = ident.as_str().parse::<usize>() 2489 { 2490 idx < tys.len() 2491 } else { 2492 false 2493 } 2494 }); 2495 2496 if ident.name == kw::Await { 2497 // We know by construction that `<expr>.await` is either on Rust 2015 2498 // or results in `ExprKind::Await`. Suggest switching the edition to 2018. 2499 err.note("to `.await` a `Future`, switch to Rust 2018 or later"); 2500 HelpUseLatestEdition::new().add_to_diagnostic(&mut err); 2501 } 2502 2503 err.emit() 2504 } 2505 ban_private_field_access( &self, expr: &hir::Expr<'tcx>, expr_t: Ty<'tcx>, field: Ident, base_did: DefId, return_ty: Option<Ty<'tcx>>, ) -> ErrorGuaranteed2506 fn ban_private_field_access( 2507 &self, 2508 expr: &hir::Expr<'tcx>, 2509 expr_t: Ty<'tcx>, 2510 field: Ident, 2511 base_did: DefId, 2512 return_ty: Option<Ty<'tcx>>, 2513 ) -> ErrorGuaranteed { 2514 let mut err = self.private_field_err(field, base_did); 2515 2516 // Also check if an accessible method exists, which is often what is meant. 2517 if self.method_exists(field, expr_t, expr.hir_id, false, return_ty) 2518 && !self.expr_in_place(expr.hir_id) 2519 { 2520 self.suggest_method_call( 2521 &mut err, 2522 format!("a method `{field}` also exists, call it with parentheses"), 2523 field, 2524 expr_t, 2525 expr, 2526 None, 2527 ); 2528 } 2529 err.emit() 2530 } 2531 ban_take_value_of_method( &self, expr: &hir::Expr<'tcx>, expr_t: Ty<'tcx>, field: Ident, ) -> ErrorGuaranteed2532 fn ban_take_value_of_method( 2533 &self, 2534 expr: &hir::Expr<'tcx>, 2535 expr_t: Ty<'tcx>, 2536 field: Ident, 2537 ) -> ErrorGuaranteed { 2538 let mut err = type_error_struct!( 2539 self.tcx().sess, 2540 field.span, 2541 expr_t, 2542 E0615, 2543 "attempted to take value of method `{field}` on type `{expr_t}`", 2544 ); 2545 err.span_label(field.span, "method, not a field"); 2546 let expr_is_call = 2547 if let hir::Node::Expr(hir::Expr { kind: ExprKind::Call(callee, _args), .. }) = 2548 self.tcx.hir().get_parent(expr.hir_id) 2549 { 2550 expr.hir_id == callee.hir_id 2551 } else { 2552 false 2553 }; 2554 let expr_snippet = 2555 self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap_or_default(); 2556 let is_wrapped = expr_snippet.starts_with('(') && expr_snippet.ends_with(')'); 2557 let after_open = expr.span.lo() + rustc_span::BytePos(1); 2558 let before_close = expr.span.hi() - rustc_span::BytePos(1); 2559 2560 if expr_is_call && is_wrapped { 2561 err.multipart_suggestion( 2562 "remove wrapping parentheses to call the method", 2563 vec![ 2564 (expr.span.with_hi(after_open), String::new()), 2565 (expr.span.with_lo(before_close), String::new()), 2566 ], 2567 Applicability::MachineApplicable, 2568 ); 2569 } else if !self.expr_in_place(expr.hir_id) { 2570 // Suggest call parentheses inside the wrapping parentheses 2571 let span = if is_wrapped { 2572 expr.span.with_lo(after_open).with_hi(before_close) 2573 } else { 2574 expr.span 2575 }; 2576 self.suggest_method_call( 2577 &mut err, 2578 "use parentheses to call the method", 2579 field, 2580 expr_t, 2581 expr, 2582 Some(span), 2583 ); 2584 } else if let ty::RawPtr(ty_and_mut) = expr_t.kind() 2585 && let ty::Adt(adt_def, _) = ty_and_mut.ty.kind() 2586 && let ExprKind::Field(base_expr, _) = expr.kind 2587 && adt_def.variants().len() == 1 2588 && adt_def 2589 .variants() 2590 .iter() 2591 .next() 2592 .unwrap() 2593 .fields 2594 .iter() 2595 .any(|f| f.ident(self.tcx) == field) 2596 { 2597 err.multipart_suggestion( 2598 "to access the field, dereference first", 2599 vec![ 2600 (base_expr.span.shrink_to_lo(), "(*".to_string()), 2601 (base_expr.span.shrink_to_hi(), ")".to_string()), 2602 ], 2603 Applicability::MaybeIncorrect, 2604 ); 2605 } else { 2606 err.help("methods are immutable and cannot be assigned to"); 2607 } 2608 2609 err.emit() 2610 } 2611 point_at_param_definition(&self, err: &mut Diagnostic, param: ty::ParamTy)2612 fn point_at_param_definition(&self, err: &mut Diagnostic, param: ty::ParamTy) { 2613 let generics = self.tcx.generics_of(self.body_id); 2614 let generic_param = generics.type_param(¶m, self.tcx); 2615 if let ty::GenericParamDefKind::Type { synthetic: true, .. } = generic_param.kind { 2616 return; 2617 } 2618 let param_def_id = generic_param.def_id; 2619 let param_hir_id = match param_def_id.as_local() { 2620 Some(x) => self.tcx.hir().local_def_id_to_hir_id(x), 2621 None => return, 2622 }; 2623 let param_span = self.tcx.hir().span(param_hir_id); 2624 let param_name = self.tcx.hir().ty_param_name(param_def_id.expect_local()); 2625 2626 err.span_label(param_span, format!("type parameter '{param_name}' declared here")); 2627 } 2628 suggest_fields_on_recordish( &self, err: &mut Diagnostic, def: ty::AdtDef<'tcx>, field: Ident, access_span: Span, )2629 fn suggest_fields_on_recordish( 2630 &self, 2631 err: &mut Diagnostic, 2632 def: ty::AdtDef<'tcx>, 2633 field: Ident, 2634 access_span: Span, 2635 ) { 2636 if let Some(suggested_field_name) = 2637 self.suggest_field_name(def.non_enum_variant(), field.name, &[], access_span) 2638 { 2639 err.span_suggestion( 2640 field.span, 2641 "a field with a similar name exists", 2642 suggested_field_name, 2643 Applicability::MaybeIncorrect, 2644 ); 2645 } else { 2646 err.span_label(field.span, "unknown field"); 2647 let struct_variant_def = def.non_enum_variant(); 2648 let field_names = self.available_field_names(struct_variant_def, access_span); 2649 if !field_names.is_empty() { 2650 err.note(format!( 2651 "available fields are: {}", 2652 self.name_series_display(field_names), 2653 )); 2654 } 2655 } 2656 } 2657 maybe_suggest_array_indexing( &self, err: &mut Diagnostic, expr: &hir::Expr<'_>, base: &hir::Expr<'_>, field: Ident, len: ty::Const<'tcx>, )2658 fn maybe_suggest_array_indexing( 2659 &self, 2660 err: &mut Diagnostic, 2661 expr: &hir::Expr<'_>, 2662 base: &hir::Expr<'_>, 2663 field: Ident, 2664 len: ty::Const<'tcx>, 2665 ) { 2666 if let (Some(len), Ok(user_index)) = 2667 (len.try_eval_target_usize(self.tcx, self.param_env), field.as_str().parse::<u64>()) 2668 && let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) 2669 { 2670 let help = "instead of using tuple indexing, use array indexing"; 2671 let suggestion = format!("{base}[{field}]"); 2672 let applicability = if len < user_index { 2673 Applicability::MachineApplicable 2674 } else { 2675 Applicability::MaybeIncorrect 2676 }; 2677 err.span_suggestion(expr.span, help, suggestion, applicability); 2678 } 2679 } 2680 suggest_first_deref_field( &self, err: &mut Diagnostic, expr: &hir::Expr<'_>, base: &hir::Expr<'_>, field: Ident, )2681 fn suggest_first_deref_field( 2682 &self, 2683 err: &mut Diagnostic, 2684 expr: &hir::Expr<'_>, 2685 base: &hir::Expr<'_>, 2686 field: Ident, 2687 ) { 2688 if let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) { 2689 let msg = format!("`{base}` is a raw pointer; try dereferencing it"); 2690 let suggestion = format!("(*{base}).{field}"); 2691 err.span_suggestion(expr.span, msg, suggestion, Applicability::MaybeIncorrect); 2692 } 2693 } 2694 no_such_field_err( &self, field: Ident, expr_t: Ty<'tcx>, id: HirId, ) -> DiagnosticBuilder<'_, ErrorGuaranteed>2695 fn no_such_field_err( 2696 &self, 2697 field: Ident, 2698 expr_t: Ty<'tcx>, 2699 id: HirId, 2700 ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { 2701 let span = field.span; 2702 debug!("no_such_field_err(span: {:?}, field: {:?}, expr_t: {:?})", span, field, expr_t); 2703 2704 let mut err = type_error_struct!( 2705 self.tcx().sess, 2706 field.span, 2707 expr_t, 2708 E0609, 2709 "no field `{field}` on type `{expr_t}`", 2710 ); 2711 2712 // try to add a suggestion in case the field is a nested field of a field of the Adt 2713 let mod_id = self.tcx.parent_module(id).to_def_id(); 2714 if let Some((fields, substs)) = 2715 self.get_field_candidates_considering_privacy(span, expr_t, mod_id) 2716 { 2717 let candidate_fields: Vec<_> = fields 2718 .filter_map(|candidate_field| { 2719 self.check_for_nested_field_satisfying( 2720 span, 2721 &|candidate_field, _| candidate_field.ident(self.tcx()) == field, 2722 candidate_field, 2723 substs, 2724 vec![], 2725 mod_id, 2726 ) 2727 }) 2728 .map(|mut field_path| { 2729 field_path.pop(); 2730 field_path 2731 .iter() 2732 .map(|id| id.name.to_ident_string()) 2733 .collect::<Vec<String>>() 2734 .join(".") 2735 }) 2736 .collect::<Vec<_>>(); 2737 2738 let len = candidate_fields.len(); 2739 if len > 0 { 2740 err.span_suggestions( 2741 field.span.shrink_to_lo(), 2742 format!( 2743 "{} of the expressions' fields {} a field of the same name", 2744 if len > 1 { "some" } else { "one" }, 2745 if len > 1 { "have" } else { "has" }, 2746 ), 2747 candidate_fields.iter().map(|path| format!("{path}.")), 2748 Applicability::MaybeIncorrect, 2749 ); 2750 } 2751 } 2752 err 2753 } 2754 private_field_err( &self, field: Ident, base_did: DefId, ) -> DiagnosticBuilder<'_, ErrorGuaranteed>2755 fn private_field_err( 2756 &self, 2757 field: Ident, 2758 base_did: DefId, 2759 ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { 2760 let struct_path = self.tcx().def_path_str(base_did); 2761 let kind_name = self.tcx().def_descr(base_did); 2762 let mut err = struct_span_err!( 2763 self.tcx().sess, 2764 field.span, 2765 E0616, 2766 "field `{field}` of {kind_name} `{struct_path}` is private", 2767 ); 2768 err.span_label(field.span, "private field"); 2769 2770 err 2771 } 2772 get_field_candidates_considering_privacy( &self, span: Span, base_ty: Ty<'tcx>, mod_id: DefId, ) -> Option<(impl Iterator<Item = &'tcx ty::FieldDef> + 'tcx, SubstsRef<'tcx>)>2773 pub(crate) fn get_field_candidates_considering_privacy( 2774 &self, 2775 span: Span, 2776 base_ty: Ty<'tcx>, 2777 mod_id: DefId, 2778 ) -> Option<(impl Iterator<Item = &'tcx ty::FieldDef> + 'tcx, SubstsRef<'tcx>)> { 2779 debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty); 2780 2781 for (base_t, _) in self.autoderef(span, base_ty) { 2782 match base_t.kind() { 2783 ty::Adt(base_def, substs) if !base_def.is_enum() => { 2784 let tcx = self.tcx; 2785 let fields = &base_def.non_enum_variant().fields; 2786 // Some struct, e.g. some that impl `Deref`, have all private fields 2787 // because you're expected to deref them to access the _real_ fields. 2788 // This, for example, will help us suggest accessing a field through a `Box<T>`. 2789 if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) { 2790 continue; 2791 } 2792 return Some(( 2793 fields 2794 .iter() 2795 .filter(move |field| field.vis.is_accessible_from(mod_id, tcx)) 2796 // For compile-time reasons put a limit on number of fields we search 2797 .take(100), 2798 substs, 2799 )); 2800 } 2801 _ => {} 2802 } 2803 } 2804 None 2805 } 2806 2807 /// This method is called after we have encountered a missing field error to recursively 2808 /// search for the field check_for_nested_field_satisfying( &self, span: Span, matches: &impl Fn(&ty::FieldDef, Ty<'tcx>) -> bool, candidate_field: &ty::FieldDef, subst: SubstsRef<'tcx>, mut field_path: Vec<Ident>, mod_id: DefId, ) -> Option<Vec<Ident>>2809 pub(crate) fn check_for_nested_field_satisfying( 2810 &self, 2811 span: Span, 2812 matches: &impl Fn(&ty::FieldDef, Ty<'tcx>) -> bool, 2813 candidate_field: &ty::FieldDef, 2814 subst: SubstsRef<'tcx>, 2815 mut field_path: Vec<Ident>, 2816 mod_id: DefId, 2817 ) -> Option<Vec<Ident>> { 2818 debug!( 2819 "check_for_nested_field_satisfying(span: {:?}, candidate_field: {:?}, field_path: {:?}", 2820 span, candidate_field, field_path 2821 ); 2822 2823 if field_path.len() > 3 { 2824 // For compile-time reasons and to avoid infinite recursion we only check for fields 2825 // up to a depth of three 2826 None 2827 } else { 2828 field_path.push(candidate_field.ident(self.tcx).normalize_to_macros_2_0()); 2829 let field_ty = candidate_field.ty(self.tcx, subst); 2830 if matches(candidate_field, field_ty) { 2831 return Some(field_path); 2832 } else if let Some((nested_fields, subst)) = 2833 self.get_field_candidates_considering_privacy(span, field_ty, mod_id) 2834 { 2835 // recursively search fields of `candidate_field` if it's a ty::Adt 2836 for field in nested_fields { 2837 if let Some(field_path) = self.check_for_nested_field_satisfying( 2838 span, 2839 matches, 2840 field, 2841 subst, 2842 field_path.clone(), 2843 mod_id, 2844 ) { 2845 return Some(field_path); 2846 } 2847 } 2848 } 2849 None 2850 } 2851 } 2852 check_expr_index( &self, base: &'tcx hir::Expr<'tcx>, idx: &'tcx hir::Expr<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx>2853 fn check_expr_index( 2854 &self, 2855 base: &'tcx hir::Expr<'tcx>, 2856 idx: &'tcx hir::Expr<'tcx>, 2857 expr: &'tcx hir::Expr<'tcx>, 2858 ) -> Ty<'tcx> { 2859 let base_t = self.check_expr(&base); 2860 let idx_t = self.check_expr(&idx); 2861 2862 if base_t.references_error() { 2863 base_t 2864 } else if idx_t.references_error() { 2865 idx_t 2866 } else { 2867 let base_t = self.structurally_resolve_type(base.span, base_t); 2868 match self.lookup_indexing(expr, base, base_t, idx, idx_t) { 2869 Some((index_ty, element_ty)) => { 2870 // two-phase not needed because index_ty is never mutable 2871 self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No); 2872 self.select_obligations_where_possible(|errors| { 2873 self.point_at_index_if_possible(errors, idx.span) 2874 }); 2875 element_ty 2876 } 2877 None => { 2878 // Attempt to *shallowly* search for an impl which matches, 2879 // but has nested obligations which are unsatisfied. 2880 for (base_t, _) in self.autoderef(base.span, base_t).silence_errors() { 2881 if let Some((_, index_ty, element_ty)) = 2882 self.find_and_report_unsatisfied_index_impl(base, base_t) 2883 { 2884 self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No); 2885 return element_ty; 2886 } 2887 } 2888 2889 let mut err = type_error_struct!( 2890 self.tcx.sess, 2891 expr.span, 2892 base_t, 2893 E0608, 2894 "cannot index into a value of type `{base_t}`", 2895 ); 2896 // Try to give some advice about indexing tuples. 2897 if let ty::Tuple(types) = base_t.kind() { 2898 let mut needs_note = true; 2899 // If the index is an integer, we can show the actual 2900 // fixed expression: 2901 if let ExprKind::Lit(ref lit) = idx.kind 2902 && let ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) = lit.node 2903 && i < types.len().try_into().expect("expected tuple index to be < usize length") 2904 { 2905 let snip = self.tcx.sess.source_map().span_to_snippet(base.span); 2906 if let Ok(snip) = snip { 2907 err.span_suggestion( 2908 expr.span, 2909 "to access tuple elements, use", 2910 format!("{snip}.{i}"), 2911 Applicability::MachineApplicable, 2912 ); 2913 needs_note = false; 2914 } 2915 } else if let ExprKind::Path(..) = idx.peel_borrows().kind { 2916 err.span_label(idx.span, "cannot access tuple elements at a variable index"); 2917 } 2918 if needs_note { 2919 err.help( 2920 "to access tuple elements, use tuple indexing \ 2921 syntax (e.g., `tuple.0`)", 2922 ); 2923 } 2924 } 2925 2926 if base_t.is_unsafe_ptr() && idx_t.is_integral() { 2927 err.multipart_suggestion( 2928 "consider using `wrapping_add` or `add` for indexing into raw pointer", 2929 vec![ 2930 (base.span.between(idx.span), ".wrapping_add(".to_owned()), 2931 ( 2932 idx.span.shrink_to_hi().until(expr.span.shrink_to_hi()), 2933 ")".to_owned(), 2934 ), 2935 ], 2936 Applicability::MaybeIncorrect, 2937 ); 2938 } 2939 2940 let reported = err.emit(); 2941 Ty::new_error(self.tcx, reported) 2942 } 2943 } 2944 } 2945 } 2946 2947 /// Try to match an implementation of `Index` against a self type, and report 2948 /// the unsatisfied predicates that result from confirming this impl. 2949 /// 2950 /// Given an index expression, sometimes the `Self` type shallowly but does not 2951 /// deeply satisfy an impl predicate. Instead of simply saying that the type 2952 /// does not support being indexed, we want to point out exactly what nested 2953 /// predicates cause this to be, so that the user can add them to fix their code. find_and_report_unsatisfied_index_impl( &self, base_expr: &hir::Expr<'_>, base_ty: Ty<'tcx>, ) -> Option<(ErrorGuaranteed, Ty<'tcx>, Ty<'tcx>)>2954 fn find_and_report_unsatisfied_index_impl( 2955 &self, 2956 base_expr: &hir::Expr<'_>, 2957 base_ty: Ty<'tcx>, 2958 ) -> Option<(ErrorGuaranteed, Ty<'tcx>, Ty<'tcx>)> { 2959 let index_trait_def_id = self.tcx.lang_items().index_trait()?; 2960 let index_trait_output_def_id = self.tcx.get_diagnostic_item(sym::IndexOutput)?; 2961 2962 let mut relevant_impls = vec![]; 2963 self.tcx.for_each_relevant_impl(index_trait_def_id, base_ty, |impl_def_id| { 2964 relevant_impls.push(impl_def_id); 2965 }); 2966 let [impl_def_id] = relevant_impls[..] else { 2967 // Only report unsatisfied impl predicates if there's one impl 2968 return None; 2969 }; 2970 2971 self.commit_if_ok(|_| { 2972 let ocx = ObligationCtxt::new(self); 2973 let impl_substs = self.fresh_substs_for_item(base_expr.span, impl_def_id); 2974 let impl_trait_ref = 2975 self.tcx.impl_trait_ref(impl_def_id).unwrap().subst(self.tcx, impl_substs); 2976 let cause = self.misc(base_expr.span); 2977 2978 // Match the impl self type against the base ty. If this fails, 2979 // we just skip this impl, since it's not particularly useful. 2980 let impl_trait_ref = ocx.normalize(&cause, self.param_env, impl_trait_ref); 2981 ocx.eq(&cause, self.param_env, impl_trait_ref.self_ty(), base_ty)?; 2982 2983 // Register the impl's predicates. One of these predicates 2984 // must be unsatisfied, or else we wouldn't have gotten here 2985 // in the first place. 2986 ocx.register_obligations(traits::predicates_for_generics( 2987 |idx, span| { 2988 cause.clone().derived_cause( 2989 ty::Binder::dummy(ty::TraitPredicate { 2990 trait_ref: impl_trait_ref, 2991 polarity: ty::ImplPolarity::Positive, 2992 constness: ty::BoundConstness::NotConst, 2993 }), 2994 |derived| { 2995 traits::ImplDerivedObligation(Box::new( 2996 traits::ImplDerivedObligationCause { 2997 derived, 2998 impl_or_alias_def_id: impl_def_id, 2999 impl_def_predicate_index: Some(idx), 3000 span, 3001 }, 3002 )) 3003 }, 3004 ) 3005 }, 3006 self.param_env, 3007 self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_substs), 3008 )); 3009 3010 // Normalize the output type, which we can use later on as the 3011 // return type of the index expression... 3012 let element_ty = ocx.normalize( 3013 &cause, 3014 self.param_env, 3015 Ty::new_projection(self.tcx, index_trait_output_def_id, impl_trait_ref.substs), 3016 ); 3017 3018 let errors = ocx.select_where_possible(); 3019 // There should be at least one error reported. If not, we 3020 // will still delay a span bug in `report_fulfillment_errors`. 3021 Ok::<_, NoSolution>(( 3022 self.err_ctxt().report_fulfillment_errors(&errors), 3023 impl_trait_ref.substs.type_at(1), 3024 element_ty, 3025 )) 3026 }) 3027 .ok() 3028 } 3029 point_at_index_if_possible( &self, errors: &mut Vec<traits::FulfillmentError<'tcx>>, span: Span, )3030 fn point_at_index_if_possible( 3031 &self, 3032 errors: &mut Vec<traits::FulfillmentError<'tcx>>, 3033 span: Span, 3034 ) { 3035 for error in errors { 3036 match error.obligation.predicate.kind().skip_binder() { 3037 ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) 3038 if self.tcx.is_diagnostic_item(sym::SliceIndex, predicate.trait_ref.def_id) => { 3039 } 3040 _ => continue, 3041 } 3042 error.obligation.cause.span = span; 3043 } 3044 } 3045 check_expr_yield( &self, value: &'tcx hir::Expr<'tcx>, expr: &'tcx hir::Expr<'tcx>, src: &'tcx hir::YieldSource, ) -> Ty<'tcx>3046 fn check_expr_yield( 3047 &self, 3048 value: &'tcx hir::Expr<'tcx>, 3049 expr: &'tcx hir::Expr<'tcx>, 3050 src: &'tcx hir::YieldSource, 3051 ) -> Ty<'tcx> { 3052 match self.resume_yield_tys { 3053 Some((resume_ty, yield_ty)) => { 3054 self.check_expr_coercible_to_type(&value, yield_ty, None); 3055 3056 resume_ty 3057 } 3058 // Given that this `yield` expression was generated as a result of lowering a `.await`, 3059 // we know that the yield type must be `()`; however, the context won't contain this 3060 // information. Hence, we check the source of the yield expression here and check its 3061 // value's type against `()` (this check should always hold). 3062 None if src.is_await() => { 3063 self.check_expr_coercible_to_type(&value, Ty::new_unit(self.tcx), None); 3064 Ty::new_unit(self.tcx) 3065 } 3066 _ => { 3067 self.tcx.sess.emit_err(YieldExprOutsideOfGenerator { span: expr.span }); 3068 // Avoid expressions without types during writeback (#78653). 3069 self.check_expr(value); 3070 Ty::new_unit(self.tcx) 3071 } 3072 } 3073 } 3074 check_expr_asm_operand(&self, expr: &'tcx hir::Expr<'tcx>, is_input: bool)3075 fn check_expr_asm_operand(&self, expr: &'tcx hir::Expr<'tcx>, is_input: bool) { 3076 let needs = if is_input { Needs::None } else { Needs::MutPlace }; 3077 let ty = self.check_expr_with_needs(expr, needs); 3078 self.require_type_is_sized(ty, expr.span, traits::InlineAsmSized); 3079 3080 if !is_input && !expr.is_syntactic_place_expr() { 3081 let mut err = self.tcx.sess.struct_span_err(expr.span, "invalid asm output"); 3082 err.span_label(expr.span, "cannot assign to this expression"); 3083 err.emit(); 3084 } 3085 3086 // If this is an input value, we require its type to be fully resolved 3087 // at this point. This allows us to provide helpful coercions which help 3088 // pass the type candidate list in a later pass. 3089 // 3090 // We don't require output types to be resolved at this point, which 3091 // allows them to be inferred based on how they are used later in the 3092 // function. 3093 if is_input { 3094 let ty = self.structurally_resolve_type(expr.span, ty); 3095 match *ty.kind() { 3096 ty::FnDef(..) => { 3097 let fnptr_ty = Ty::new_fn_ptr(self.tcx, ty.fn_sig(self.tcx)); 3098 self.demand_coerce(expr, ty, fnptr_ty, None, AllowTwoPhase::No); 3099 } 3100 ty::Ref(_, base_ty, mutbl) => { 3101 let ptr_ty = Ty::new_ptr(self.tcx, ty::TypeAndMut { ty: base_ty, mutbl }); 3102 self.demand_coerce(expr, ty, ptr_ty, None, AllowTwoPhase::No); 3103 } 3104 _ => {} 3105 } 3106 } 3107 } 3108 check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx>3109 fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> { 3110 for (op, _op_sp) in asm.operands { 3111 match op { 3112 hir::InlineAsmOperand::In { expr, .. } => { 3113 self.check_expr_asm_operand(expr, true); 3114 } 3115 hir::InlineAsmOperand::Out { expr: Some(expr), .. } 3116 | hir::InlineAsmOperand::InOut { expr, .. } => { 3117 self.check_expr_asm_operand(expr, false); 3118 } 3119 hir::InlineAsmOperand::Out { expr: None, .. } => {} 3120 hir::InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => { 3121 self.check_expr_asm_operand(in_expr, true); 3122 if let Some(out_expr) = out_expr { 3123 self.check_expr_asm_operand(out_expr, false); 3124 } 3125 } 3126 // `AnonConst`s have their own body and is type-checked separately. 3127 // As they don't flow into the type system we don't need them to 3128 // be well-formed. 3129 hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {} 3130 hir::InlineAsmOperand::SymStatic { .. } => {} 3131 } 3132 } 3133 if asm.options.contains(ast::InlineAsmOptions::NORETURN) { 3134 self.tcx.types.never 3135 } else { 3136 Ty::new_unit(self.tcx) 3137 } 3138 } 3139 check_offset_of( &self, container: &'tcx hir::Ty<'tcx>, fields: &[Ident], expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx>3140 fn check_offset_of( 3141 &self, 3142 container: &'tcx hir::Ty<'tcx>, 3143 fields: &[Ident], 3144 expr: &'tcx hir::Expr<'tcx>, 3145 ) -> Ty<'tcx> { 3146 let container = self.to_ty(container).normalized; 3147 3148 let mut field_indices = Vec::with_capacity(fields.len()); 3149 let mut current_container = container; 3150 3151 for &field in fields { 3152 let container = self.structurally_resolve_type(expr.span, current_container); 3153 3154 match container.kind() { 3155 ty::Adt(container_def, substs) if !container_def.is_enum() => { 3156 let block = self.tcx.hir().local_def_id_to_hir_id(self.body_id); 3157 let (ident, def_scope) = 3158 self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block); 3159 3160 let fields = &container_def.non_enum_variant().fields; 3161 if let Some((index, field)) = fields 3162 .iter_enumerated() 3163 .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == ident) 3164 { 3165 let field_ty = self.field_ty(expr.span, field, substs); 3166 3167 // FIXME: DSTs with static alignment should be allowed 3168 self.require_type_is_sized(field_ty, expr.span, traits::MiscObligation); 3169 3170 if field.vis.is_accessible_from(def_scope, self.tcx) { 3171 self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None); 3172 } else { 3173 self.private_field_err(ident, container_def.did()).emit(); 3174 } 3175 3176 // Save the index of all fields regardless of their visibility in case 3177 // of error recovery. 3178 field_indices.push(index); 3179 current_container = field_ty; 3180 3181 continue; 3182 } 3183 } 3184 ty::Tuple(tys) => { 3185 if let Ok(index) = field.as_str().parse::<usize>() 3186 && field.name == sym::integer(index) 3187 { 3188 for ty in tys.iter().take(index + 1) { 3189 self.require_type_is_sized(ty, expr.span, traits::MiscObligation); 3190 } 3191 if let Some(&field_ty) = tys.get(index) { 3192 field_indices.push(index.into()); 3193 current_container = field_ty; 3194 3195 continue; 3196 } 3197 } 3198 } 3199 _ => (), 3200 }; 3201 3202 self.no_such_field_err(field, container, expr.hir_id).emit(); 3203 3204 break; 3205 } 3206 3207 self.typeck_results 3208 .borrow_mut() 3209 .offset_of_data_mut() 3210 .insert(expr.hir_id, (container, field_indices)); 3211 3212 self.tcx.types.usize 3213 } 3214 } 3215