compiler/rustc_hir_typeck/src/expr.rs RUST 3,989 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 3,989.
1// ignore-tidy-file-filelength2// FIXME: we should move the field error reporting code somewhere else.34//! Type checking expressions.5//!6//! See [`rustc_hir_analysis::check`] for more context on type checking in general.78use std::borrow::Cow;910use rustc_abi::{FIRST_VARIANT, FieldIdx};11use rustc_ast as ast;12use rustc_ast::util::parser::ExprPrecedence;13use rustc_attr_ir::find_attr;14use rustc_attr_ir::lang_items::LangItem;15use rustc_data_structures::fx::{FxHashMap, FxHashSet};16use rustc_data_structures::thin_vec::ThinVec;17use rustc_data_structures::unord::UnordMap;18use rustc_errors::codes::*;19use rustc_errors::{20    Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, Subdiagnostic, listify, pluralize,21    struct_span_code_err,22};23use rustc_hir as hir;24use rustc_hir::def::{CtorKind, DefKind, Res};25use rustc_hir::def_id::DefId;26use rustc_hir::{ExprKind, HirId, QPath, is_range_literal};27use rustc_hir_analysis::diagnostics::{NoFieldOnType, NoVariantNamed};28use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _;29use rustc_infer::infer::{self, RegionVariableOrigin};30use rustc_infer::traits::WellFormedLoc;31use rustc_infer::traits::query::NoSolution;32use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};33use rustc_middle::ty::error::{ExpectedFound, TypeError};34use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TypeVisitableExt, Unnormalized};35use rustc_session::diagnostics::feature_err;36use rustc_span::edit_distance::find_best_match_for_name;37use rustc_span::hygiene::DesugaringKind;38use rustc_span::{Ident, Span, Spanned, Symbol, bug, kw, span_bug, sym};39use rustc_trait_selection::infer::InferCtxtExt;40use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};41use tracing::{debug, instrument, trace};4243use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};44use crate::callee::SplatLoweringInfo;45use crate::coercion::CoerceMany;46use crate::diagnostics::{47    AddressOfTemporaryTaken, BaseExpressionDoubleDot, BaseExpressionDoubleDotAddExpr,48    BaseExpressionDoubleDotRemove, CantDereference, ExprParenthesesNeeded,49    FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, HelpUseLatestEdition,50    NakedAsmOutsideNakedFn, NoFieldOnVariant, ReturnLikeStatementKind, ReturnStmtOutsideOfFnBody,51    StructExprNonExhaustive, TypeMismatchFruTypo, YieldExprOutsideOfCoroutine,52};53use crate::op::contains_let_in_chain;54use crate::{55    BreakableCtxt, CoroutineTypes, Diverges, FnCtxt, GatherLocalsVisitor, Needs,56    TupleArgumentsFlag, cast, fatally_break_rust, type_error_struct,57};5859impl<'a, 'tcx> FnCtxt<'a, 'tcx> {60    pub(crate) fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence {61        let has_attr = |id: HirId| -> bool {62            self.tcx63                .hir_attrs(id)64                .iter()65                .any(rustc_attr_ir::Attribute::is_prefix_attr_for_suggestions)66        };6768        // Special case: range expressions are desugared to struct literals in HIR,69        // so they would normally return `Unambiguous` precedence in expr.precedence.70        // we should return `Range` precedence for correct parenthesization in suggestions.71        if is_range_literal(expr) {72            return ExprPrecedence::Range;73        }7475        expr.precedence(&has_attr)76    }7778    /// Check an expr with an expectation type, and also demand that the expr's79    /// evaluated type is a subtype of the expectation at the end. This is a80    /// *hard* requirement.81    pub(crate) fn check_expr_has_type_or_error(82        &self,83        expr: &'tcx hir::Expr<'tcx>,84        expected_ty: Ty<'tcx>,85        extend_err: impl FnOnce(&mut Diag<'_>),86    ) -> Ty<'tcx> {87        let mut ty = self.check_expr_with_expectation(expr, ExpectHasType(expected_ty));8889        // While we don't allow *arbitrary* coercions here, we *do* allow90        // coercions from ! to `expected`.91        if self.deeply_resolve_ignoring_regions_with_obligations(ty).is_never()92            && self.tcx.expr_guaranteed_to_constitute_read_for_never(expr)93        {94            if let Some(adjustments) = self.typeck_results.borrow().adjustments().get(expr.hir_id) {95                let reported = self.dcx().span_delayed_bug(96                    expr.span,97                    "expression with never type wound up being adjusted",98                );99100                return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &adjustments[..] {101                    target.to_owned()102                } else {103                    Ty::new_error(self.tcx(), reported)104                };105            }106107            let adj_ty = self.next_ty_var(expr.span);108            self.apply_adjustments(109                expr,110                vec![Adjustment { kind: Adjust::NeverToAny, target: adj_ty }],111            );112            ty = adj_ty;113        }114115        if let Err(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {116            let _ = self.emit_type_mismatch_suggestions(117                &mut err,118                expr.peel_drop_temps(),119                ty,120                expected_ty,121                None,122                None,123            );124            extend_err(&mut err);125            err.emit();126        }127        ty128    }129130    /// Check an expr with an expectation type, and also demand that the expr's131    /// evaluated type is a coercible to the expectation at the end. This is a132    /// *hard* requirement.133    pub(super) fn check_expr_coercible_to_type(134        &self,135        expr: &'tcx hir::Expr<'tcx>,136        expected: Ty<'tcx>,137        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,138    ) -> Ty<'tcx> {139        self.check_expr_coercible_to_type_or_error(expr, expected, expected_ty_expr, |_, _| {})140    }141142    pub(crate) fn check_expr_coercible_to_type_or_error(143        &self,144        expr: &'tcx hir::Expr<'tcx>,145        expected: Ty<'tcx>,146        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,147        extend_err: impl FnOnce(&mut Diag<'_>, Ty<'tcx>),148    ) -> Ty<'tcx> {149        let ty = self.check_expr_with_hint(expr, expected);150        // checks don't need two phase151        match self.demand_coerce_diag(expr, ty, expected, expected_ty_expr, AllowTwoPhase::No) {152            Ok(ty) => ty,153            Err(mut err) => {154                extend_err(&mut err, ty);155                err.emit();156                // Return the original type instead of an error type here, otherwise the type of `x` in157                // `let x: u32 = ();` will be a type error, causing all subsequent usages of `x` to not158                // report errors, even though `x` is definitely `u32`.159                expected160            }161        }162    }163164    /// Check an expr with an expectation type. Don't actually enforce that expectation165    /// is related to the expr's evaluated type via subtyping or coercion. This is166    /// usually called because we want to do that subtype/coerce call manually for better167    /// diagnostics.168    pub(super) fn check_expr_with_hint(169        &self,170        expr: &'tcx hir::Expr<'tcx>,171        expected: Ty<'tcx>,172    ) -> Ty<'tcx> {173        self.check_expr_with_expectation(expr, ExpectHasType(expected))174    }175176    /// Check an expr with an expectation type, and also [`Needs`] which will177    /// prompt typeck to convert any implicit immutable derefs to mutable derefs.178    fn check_expr_with_expectation_and_needs(179        &self,180        expr: &'tcx hir::Expr<'tcx>,181        expected: Expectation<'tcx>,182        needs: Needs,183    ) -> Ty<'tcx> {184        let ty = self.check_expr_with_expectation(expr, expected);185186        // If the expression is used in a place whether mutable place is required187        // e.g. LHS of assignment, perform the conversion.188        if let Needs::MutPlace = needs {189            self.convert_place_derefs_to_mutable(expr);190        }191192        ty193    }194195    /// Check an expr with no expectations.196    pub(super) fn check_expr(&self, expr: &'tcx hir::Expr<'tcx>) -> Ty<'tcx> {197        self.check_expr_with_expectation(expr, NoExpectation)198    }199200    /// Check an expr with no expectations, but with [`Needs`] which will201    /// prompt typeck to convert any implicit immutable derefs to mutable derefs.202    pub(super) fn check_expr_with_needs(203        &self,204        expr: &'tcx hir::Expr<'tcx>,205        needs: Needs,206    ) -> Ty<'tcx> {207        self.check_expr_with_expectation_and_needs(expr, NoExpectation, needs)208    }209210    /// Check an expr with an expectation type which may be used to eagerly211    /// guide inference when evaluating that expr.212    #[instrument(skip(self, expr), level = "debug")]213    pub(super) fn check_expr_with_expectation(214        &self,215        expr: &'tcx hir::Expr<'tcx>,216        expected: Expectation<'tcx>,217    ) -> Ty<'tcx> {218        self.check_expr_with_expectation_and_args(expr, expected, None)219    }220221    /// Same as [`Self::check_expr_with_expectation`], but allows us to pass in222    /// the arguments of a [`ExprKind::Call`] when evaluating its callee that223    /// is an [`ExprKind::Path`]. We use this to refine the spans for certain224    /// well-formedness guarantees for the path expr.225    pub(super) fn check_expr_with_expectation_and_args(226        &self,227        expr: &'tcx hir::Expr<'tcx>,228        expected: Expectation<'tcx>,229        call_expr_and_args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,230    ) -> Ty<'tcx> {231        if self.tcx().sess.verbose_internals() {232            // make this code only run with -Zverbose-internals because it is probably slow233            if let Ok(lint_str) = self.tcx.sess.source_map().span_to_snippet(expr.span) {234                if !lint_str.contains('\n') {235                    debug!("expr text: {lint_str}");236                } else {237                    let mut lines = lint_str.lines();238                    if let Some(line0) = lines.next() {239                        let remaining_lines = lines.count();240                        debug!("expr text: {line0}");241                        debug!("expr text: ...(and {remaining_lines} more lines)");242                    }243                }244            }245        }246247        // True if `expr` is a `Try::from_ok(())` that is a result of desugaring a try block248        // without the final expr (e.g. `try { return; }`). We don't want to generate an249        // unreachable_code lint for it since warnings for autogenerated code are confusing.250        let is_try_block_generated_unit_expr = match expr.kind {251            ExprKind::Call(_, [arg]) => {252                expr.span.is_desugaring(DesugaringKind::TryBlock)253                    && arg.span.is_desugaring(DesugaringKind::TryBlock)254            }255            _ => false,256        };257258        // Warn for expressions after diverging siblings.259        if !is_try_block_generated_unit_expr {260            self.warn_if_unreachable(expr.hir_id, expr.span, "expression");261        }262263        // Whether a past expression diverges doesn't affect typechecking of this expression, so we264        // reset `diverges` while checking `expr`.265        let old_diverges = self.diverges.replace(Diverges::Maybe);266267        if self.is_whole_body.replace(false) {268            // If this expression is the whole body and the function diverges because of its269            // arguments, we check this here to ensure the body is considered to diverge.270            self.diverges.set(self.function_diverges_because_of_empty_arguments.get())271        };272273        let ty = match &expr.kind {274            // Intercept the callee path expr and give it better spans.275            hir::ExprKind::Path(276                qpath @ (hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)),277            ) => self.check_expr_path(qpath, expr, call_expr_and_args),278            _ => self.check_expr_kind(expr, expected),279        };280        let ty = self.deeply_resolve_ignoring_regions(ty);281282        // Warn for non-block expressions with diverging children.283        match expr.kind {284            ExprKind::Block(..)285            | ExprKind::If(..)286            | ExprKind::Let(..)287            | ExprKind::Loop(..)288            | ExprKind::Match(..) => {}289            // Do not warn on `as` casts from never to any,290            // they are sometimes required to appeal typeck.291            ExprKind::Cast(_, _) => {}292            // If `expr` is a result of desugaring the try block and is an ok-wrapped293            // diverging expression (e.g. it arose from desugaring of `try { return }`),294            // we skip issuing a warning because it is autogenerated code.295            ExprKind::Call(..) if expr.span.is_desugaring(DesugaringKind::TryBlock) => {}296            // Likewise, do not lint unreachable code injected via contracts desugaring.297            ExprKind::Call(..) if expr.span.is_desugaring(DesugaringKind::Contract) => {}298            ExprKind::Call(callee, _) => self.warn_if_unreachable(expr.hir_id, callee.span, "call"),299            ExprKind::MethodCall(segment, ..) => {300                self.warn_if_unreachable(expr.hir_id, segment.ident.span, "call")301            }302            _ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression"),303        }304305        // Any expression that produces a value of type `!` must have diverged,306        // unless it's a place expression that isn't being read from, in which case307        // diverging would be unsound since we may never actually read the `!`.308        // e.g. `let _ = *never_ptr;` with `never_ptr: *const !`.309        if self.deeply_resolve_ignoring_regions_with_obligations(ty).is_never()310            && self.tcx.expr_guaranteed_to_constitute_read_for_never(expr)311        {312            self.diverges.set(self.diverges.get() | Diverges::always(expr.span));313        }314315        // Record the type, which applies it effects.316        // We need to do this after the warning above, so that317        // we don't warn for the diverging expression itself.318        self.write_ty(expr.hir_id, ty);319320        // Combine the diverging and has_error flags.321        self.diverges.set(self.diverges.get() | old_diverges);322323        debug!("type of {} is...", self.tcx.hir_id_to_string(expr.hir_id));324        debug!("... {:?}, expected is {:?}", ty, expected);325326        ty327    }328329    #[instrument(skip(self, expr), level = "debug")]330    fn check_expr_kind(331        &self,332        expr: &'tcx hir::Expr<'tcx>,333        expected: Expectation<'tcx>,334    ) -> Ty<'tcx> {335        trace!("expr={:#?}", expr);336337        let tcx = self.tcx;338        match expr.kind {339            ExprKind::Lit(ref lit) => self.check_expr_lit(lit, expr.hir_id, expected),340            ExprKind::Binary(op, lhs, rhs) => self.check_expr_binop(expr, op, lhs, rhs, expected),341            ExprKind::Assign(lhs, rhs, span) => {342                self.check_expr_assign(expr, expected, lhs, rhs, span)343            }344            ExprKind::AssignOp(op, lhs, rhs) => {345                self.check_expr_assign_op(expr, op, lhs, rhs, expected)346            }347            ExprKind::Unary(unop, oprnd) => self.check_expr_unop(unop, oprnd, expected, expr),348            ExprKind::AddrOf(kind, mutbl, oprnd) => {349                self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr)350            }351            ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, None),352            ExprKind::InlineAsm(asm) => {353                // We defer some asm checks as we may not have resolved the input and output types yet (they may still be infer vars).354                self.deferred_asm_checks.borrow_mut().push((asm, expr.hir_id));355                self.check_expr_asm(asm, expr.span)356            }357            ExprKind::OffsetOf(container, fields) => {358                self.check_expr_offset_of(container, fields, expr)359            }360            ExprKind::Break(destination, ref expr_opt) => {361                self.check_expr_break(destination, expr_opt.as_deref(), expr)362            }363            ExprKind::Continue(destination) => self.check_expr_continue(destination, expr),364            ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr),365            ExprKind::Become(call) => self.check_expr_become(call, expr),366            ExprKind::Let(let_expr) => self.check_expr_let(let_expr, expr.hir_id),367            ExprKind::Loop(body, _, source, _) => {368                self.check_expr_loop(body, source, expected, expr)369            }370            ExprKind::Match(discrim, arms, match_src) => {371                self.check_expr_match(expr, discrim, arms, expected, match_src)372            }373            ExprKind::Closure(closure) => self.check_expr_closure(closure, expr.span, expected),374            ExprKind::Block(body, _) => self.check_expr_block(body, expected),375            ExprKind::Call(callee, args) => self.check_expr_call(expr, callee, args, expected),376            ExprKind::Use(used_expr, _) => self.check_expr_use(used_expr, expected),377            ExprKind::MethodCall(segment, receiver, args, _) => {378                self.check_expr_method_call(expr, segment, receiver, args, expected)379            }380            ExprKind::Cast(e, t) => self.check_expr_cast(e, t, expr),381            ExprKind::Type(e, t) => {382                let ascribed_ty = self.lower_ty_saving_user_provided_ty(t);383                let ty = self.check_expr_with_hint(e, ascribed_ty);384                self.demand_eqtype(e.span, ascribed_ty, ty);385                ascribed_ty386            }387            ExprKind::If(cond, then_expr, opt_else_expr) => {388                self.check_expr_if(expr.hir_id, cond, then_expr, opt_else_expr, expr.span, expected)389            }390            ExprKind::DropTemps(e) => self.check_expr_with_expectation(e, expected),391            ExprKind::Array(args) => self.check_expr_array(args, expected, expr),392            ExprKind::ConstBlock(ref block) => self.check_expr_const_block(block, expected),393            ExprKind::Repeat(element, ref count) => {394                self.check_expr_repeat(element, count, expected, expr)395            }396            ExprKind::Tup(elts) => self.check_expr_tuple(elts, expected, expr),397            ExprKind::Struct(qpath, fields, ref base_expr) => {398                self.check_expr_struct(expr, expected, qpath, fields, base_expr)399            }400            ExprKind::Field(base, field) => self.check_expr_field(expr, base, field, expected),401            ExprKind::Index(base, idx, brackets_span) => {402                self.check_expr_index(base, idx, expr, brackets_span)403            }404            ExprKind::Yield(value, _) => self.check_expr_yield(value, expr),405            ExprKind::UnsafeBinderCast(kind, inner_expr, ty) => {406                self.check_expr_unsafe_binder_cast(expr.span, kind, inner_expr, ty, expected)407            }408            ExprKind::Err(guar) => Ty::new_error(tcx, guar),409        }410    }411412    fn check_expr_unop(413        &self,414        unop: hir::UnOp,415        oprnd: &'tcx hir::Expr<'tcx>,416        expected: Expectation<'tcx>,417        expr: &'tcx hir::Expr<'tcx>,418    ) -> Ty<'tcx> {419        let tcx = self.tcx;420        let expected_inner = match unop {421            hir::UnOp::Not | hir::UnOp::Neg => expected,422            hir::UnOp::Deref => NoExpectation,423        };424        let oprnd_t = self.check_expr_with_expectation(oprnd, expected_inner);425426        if let Err(guar) = oprnd_t.error_reported() {427            return Ty::new_error(tcx, guar);428        }429430        // Resolve what we can for `Not` and `Neg`, but allow later constraints431        // to determine an unresolved operand type,432        // so we call `deeply_resolve_ignoring_regions_with_obligations` for them.433        match unop {434            hir::UnOp::Deref => {435                // Dereferencing must distinguish builtin pointers from436                // overloaded `Deref`, so it still requires a structurally resolved type.437                //438                // This is necessary as raw pointers do not implement `Deref`.439                let oprnd_t = self.structurally_resolve_type(expr.span, oprnd_t);440                self.lookup_derefing(expr, oprnd, oprnd_t).unwrap_or_else(|| {441                    let mut err =442                        self.dcx().create_err(CantDereference { span: expr.span, ty: oprnd_t });443                    let sp = tcx.sess.source_map().start_point(expr.span).with_parent(None);444                    if let Some(sp) =445                        tcx.sess.psess.complete_stmt_exprs_before_bin_op_lookalike.borrow().get(&sp)446                    {447                        err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));448                    }449                    // The operand may be an uncalled function, in which case it is its return type450                    // the user meant to dereference. Only suggest the call when that return type is451                    // itself dereferenceable, mirroring the checks `lookup_derefing` just failed.452                    self.suggest_fn_call(&mut err, oprnd, oprnd_t, |output| {453                        output.builtin_deref(true).is_some()454                            || self.tcx.lang_items().deref_trait().is_some_and(|deref_trait| {455                                self.type_implements_trait(deref_trait, [output], self.param_env)456                                    .may_apply()457                            })458                    });459                    Ty::new_error(tcx, err.emit_err())460                })461            }462            hir::UnOp::Not => {463                let oprnd_t = self.deeply_resolve_ignoring_regions_with_obligations(oprnd_t);464                let result = self.check_user_unop(expr, oprnd_t, unop, expected_inner);465                // If it's builtin, we can reuse the type, this helps inference.466                if oprnd_t.is_integral() || *oprnd_t.kind() == ty::Bool { oprnd_t } else { result }467            }468            hir::UnOp::Neg => {469                let oprnd_t = self.deeply_resolve_ignoring_regions_with_obligations(oprnd_t);470                let result = self.check_user_unop(expr, oprnd_t, unop, expected_inner);471                // If it's builtin, we can reuse the type, this helps inference.472                if oprnd_t.is_numeric() { oprnd_t } else { result }473            }474        }475    }476477    fn check_expr_addr_of(478        &self,479        kind: hir::BorrowKind,480        mutbl: hir::Mutability,481        oprnd: &'tcx hir::Expr<'tcx>,482        expected: Expectation<'tcx>,483        expr: &'tcx hir::Expr<'tcx>,484    ) -> Ty<'tcx> {485        let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {486            match self.deeply_resolve_ignoring_regions_with_obligations(ty).kind() {487                ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {488                    if oprnd.is_syntactic_place_expr() {489                        // Places may legitimately have unsized types.490                        // For example, dereferences of a wide pointer and491                        // the last field of a struct can be unsized.492                        ExpectHasType(*ty)493                    } else {494                        Expectation::rvalue_hint(self, *ty)495                    }496                }497                _ => NoExpectation,498            }499        });500        let ty =501            self.check_expr_with_expectation_and_needs(oprnd, hint, Needs::maybe_mut_place(mutbl));502        if let Err(guar) = ty.error_reported() {503            return Ty::new_error(self.tcx, guar);504        }505506        match kind {507            hir::BorrowKind::Raw => {508                self.check_named_place_expr(oprnd);509                Ty::new_ptr(self.tcx, ty, mutbl)510            }511            hir::BorrowKind::Ref | hir::BorrowKind::Pin => {512                // Note: at this point, we cannot say what the best lifetime513                // is to use for resulting pointer. We want to use the514                // shortest lifetime possible so as to avoid spurious borrowck515                // errors. Moreover, the longest lifetime will depend on the516                // precise details of the value whose address is being taken517                // (and how long it is valid), which we don't know yet until518                // type inference is complete.519                //520                // Therefore, here we simply generate a region variable. The521                // region inferencer will then select a suitable value.522                // Finally, borrowck will infer the value of the region again,523                // this time with enough precision to check that the value524                // whose address was taken can actually be made to live as long525                // as it needs to live.526                let region = self.next_region_var(RegionVariableOrigin::BorrowRegion(expr.span));527                match kind {528                    hir::BorrowKind::Ref => Ty::new_ref(self.tcx, region, ty, mutbl),529                    hir::BorrowKind::Pin => Ty::new_pinned_ref(self.tcx, region, ty, mutbl),530                    _ => unreachable!(),531                }532            }533        }534    }535536    /// Does this expression refer to a place that either:537    /// * Is based on a local or static.538    /// * Contains a dereference539    /// Note that the adjustments for the children of `expr` should already540    /// have been resolved.541    fn check_named_place_expr(&self, oprnd: &'tcx hir::Expr<'tcx>) {542        let is_named = oprnd.is_place_expr(|base| {543            // Allow raw borrows if there are any deref adjustments.544            //545            // const VAL: (i32,) = (0,);546            // const REF: &(i32,) = &(0,);547            //548            // &raw const VAL.0;            // ERROR549            // &raw const REF.0;            // OK, same as &raw const (*REF).0;550            //551            // This is maybe too permissive, since it allows552            // `let u = &raw const Box::new((1,)).0`, which creates an553            // immediately dangling raw pointer.554            self.typeck_results555                .borrow()556                .adjustments()557                .get(base.hir_id)558                .is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))559        });560        if !is_named {561            self.dcx().emit_err(AddressOfTemporaryTaken { span: oprnd.span });562        }563    }564565    pub(crate) fn check_expr_path(566        &self,567        qpath: &'tcx hir::QPath<'tcx>,568        expr: &'tcx hir::Expr<'tcx>,569        call_expr_and_args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,570    ) -> Ty<'tcx> {571        let tcx = self.tcx;572573        if let Some((_, [arg])) = call_expr_and_args574            && let QPath::Resolved(_, path) = qpath575            && let Res::Def(_, def_id) = path.res576            && let Some(lang_item) = tcx.lang_items().from_def_id(def_id)577        {578            let code = match lang_item {579                LangItem::IntoFutureIntoFuture580                    if expr.span.is_desugaring(DesugaringKind::Await) =>581                {582                    Some(ObligationCauseCode::AwaitableExpr(arg.hir_id))583                }584                LangItem::IntoIterIntoIter | LangItem::IteratorNext585                    if expr.span.is_desugaring(DesugaringKind::ForLoop) =>586                {587                    Some(ObligationCauseCode::ForLoopIterator(arg.hir_id))588                }589                LangItem::TryTraitFromOutput590                    if expr.span.is_desugaring(DesugaringKind::TryBlock) =>591                {592                    // FIXME it's a try block, not a question mark593                    Some(ObligationCauseCode::QuestionMark)594                }595                LangItem::TryTraitBranch | LangItem::TryTraitFromResidual596                    if expr.span.is_desugaring(DesugaringKind::QuestionMark) =>597                {598                    Some(ObligationCauseCode::QuestionMark)599                }600                _ => None,601            };602            if let Some(code) = code {603                let args = self.fresh_args_for_item(expr.span, def_id);604                self.add_required_obligations_with_code(expr.span, def_id, args, |_, _| {605                    code.clone()606                });607                return tcx.type_of(def_id).instantiate(tcx, args).skip_norm_wip();608            }609        }610611        let (res, opt_ty, segs) =612            self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span);613        let ty = match res {614            Res::Err => {615                self.suggest_assoc_method_call(segs);616                let e =617                    self.dcx().span_delayed_bug(qpath.span(), "`Res::Err` but no error emitted");618                Ty::new_error(tcx, e)619            }620            Res::Def(DefKind::Variant, _) => {621                let e = self.report_unexpected_variant_res(622                    res,623                    Some(expr),624                    &[],625                    qpath,626                    expr.span,627                    E0533,628                    "value",629                );630                Ty::new_error(tcx, e)631            }632            _ => {633                self.instantiate_value_path(634                    segs,635                    opt_ty,636                    res,637                    call_expr_and_args.map_or(expr.span, |(e, _)| e.span),638                    expr.span,639                    expr.hir_id,640                    call_expr_and_args.map(|(_, args)| args),641                )642                .0643            }644        };645646        if let ty::FnDef(did, args) = *ty.kind() {647            let fn_sig = ty.fn_sig(tcx);648649            if tcx.is_intrinsic(did, sym::transmute) {650                let Some(from) = fn_sig.inputs().skip_binder().get(0) else {651                    span_bug!(652                        tcx.def_span(did),653                        "intrinsic fn `transmute` defined with no parameters"654                    );655                };656                let to = fn_sig.output().skip_binder();657                // We defer the transmute to the end of typeck, once all inference vars have658                // been resolved or we errored. This is important as we can only check transmute659                // on concrete types, but the output type may not be known yet (it would only660                // be known if explicitly specified via turbofish).661                self.deferred_transmute_checks.borrow_mut().push((*from, to, expr.hir_id));662            }663            if !tcx.sess.opts.unstable_opts.offload.is_empty()664                && tcx.is_intrinsic(did, sym::offload)665            {666                let args = args.skip_binder();667                let f = args.type_at(0);668                let t = args.type_at(1);669                let r = args.type_at(2);670                // Defer offload checks to check generics later once types are fully inferred.671                self.deferred_offload_checks.borrow_mut().push((f, t, r, expr.hir_id));672            }673            if !tcx.features().unsized_fn_params() {674                // We want to remove some Sized bounds from std functions,675                // but don't want to expose the removal to stable Rust.676                // i.e., we don't want to allow677                //678                // ```rust679                // drop as fn(str);680                // ```681                //682                // to work in stable even if the Sized bound on `drop` is relaxed.683                for i in 0..fn_sig.inputs().skip_binder().len() {684                    // We just want to check sizedness, so instead of introducing685                    // placeholder lifetimes with probing, we just replace higher lifetimes686                    // with fresh vars.687                    let span = call_expr_and_args688                        .and_then(|(_, args)| args.get(i))689                        .map_or(expr.span, |arg| arg.span);690                    let input = self.instantiate_binder_with_fresh_vars(691                        span,692                        infer::BoundRegionConversionTime::FnCall,693                        fn_sig.input(i),694                    );695                    self.require_type_is_sized_deferred(696                        input,697                        span,698                        ObligationCauseCode::SizedArgumentType(None),699                    );700                }701            }702            // Here we want to prevent struct constructors from returning unsized types,703            // which can happen with fn pointer coercion on stable.704            // Also, as we just want to check sizedness, instead of introducing705            // placeholder lifetimes with probing, we just replace higher lifetimes706            // with fresh vars.707            let output = self.instantiate_binder_with_fresh_vars(708                expr.span,709                infer::BoundRegionConversionTime::FnCall,710                fn_sig.output(),711            );712            self.require_type_is_sized_deferred(713                output,714                call_expr_and_args.map_or(expr.span, |(e, _)| e.span),715                ObligationCauseCode::SizedCallReturnType(expr.hir_id),716            );717        }718719        // We always require that the type provided as the value for720        // a type parameter outlives the moment of instantiation.721        let args = self.typeck_results.borrow().node_args(expr.hir_id);722        self.add_wf_bounds(args, expr.span, expr.hir_id);723724        ty725    }726727    fn check_expr_break(728        &self,729        destination: hir::Destination,730        expr_opt: Option<&'tcx hir::Expr<'tcx>>,731        expr: &'tcx hir::Expr<'tcx>,732    ) -> Ty<'tcx> {733        let tcx = self.tcx;734        if let Ok(target_id) = destination.target_id {735            let (e_ty, cause);736            if let Some(e) = expr_opt {737                // If this is a break with a value, we need to type-check738                // the expression. Get an expected type from the loop context.739                let opt_coerce_to = {740                    // We should release `enclosing_breakables` before the `check_expr_with_hint`741                    // below, so can't move this block of code to the enclosing scope and share742                    // `ctxt` with the second `enclosing_breakables` borrow below.743                    let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();744                    match enclosing_breakables.opt_find_breakable(target_id) {745                        Some(ctxt) => ctxt.coerce.as_ref().map(|coerce| coerce.expected_ty()),746                        None => {747                            // Avoid ICE when `break` is inside a closure (#65383).748                            return Ty::new_error_with_message(749                                tcx,750                                expr.span,751                                "break was outside loop, but no error was emitted",752                            );753                        }754                    }755                };756757                // If the loop context is not a `loop { }`, then break with758                // a value is illegal, and `opt_coerce_to` will be `None`.759                // Set expectation to error in that case and set tainted760                // by error (#114529)761                let coerce_to = opt_coerce_to.unwrap_or_else(|| {762                    let guar = self.dcx().span_delayed_bug(763                        expr.span,764                        "illegal break with value found but no error reported",765                    );766                    self.set_tainted_by_errors(guar);767                    Ty::new_error(tcx, guar)768                });769770                // Recurse without `enclosing_breakables` borrowed.771                e_ty = self.check_expr_with_hint(e, coerce_to);772                cause = self.misc(e.span);773            } else {774                // Otherwise, this is a break *without* a value. That's775                // always legal, and is equivalent to `break ()`.776                e_ty = tcx.types.unit;777                cause = self.misc(expr.span);778            }779780            // Now that we have type-checked `expr_opt`, borrow781            // the `enclosing_loops` field and let's coerce the782            // type of `expr_opt` into what is expected.783            let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();784            let Some(ctxt) = enclosing_breakables.opt_find_breakable(target_id) else {785                // Avoid ICE when `break` is inside a closure (#65383).786                return Ty::new_error_with_message(787                    tcx,788                    expr.span,789                    "break was outside loop, but no error was emitted",790                );791            };792793            if let Some(ref mut coerce) = ctxt.coerce {794                if let Some(e) = expr_opt {795                    coerce.coerce(self, &cause, e, e_ty);796                } else {797                    assert!(e_ty.is_unit());798                    let ty = coerce.expected_ty();799                    coerce.coerce_forced_unit(800                        self,801                        &cause,802                        |mut err| {803                            self.suggest_missing_semicolon(&mut err, expr, e_ty, false, false);804                            self.suggest_mismatched_types_on_tail(805                                &mut err, expr, ty, e_ty, target_id,806                            );807                            let error =808                                Some(TypeError::Sorts(ExpectedFound { expected: ty, found: e_ty }));809                            self.annotate_loop_expected_due_to_inference(err, expr, error);810                            if let Some(val) =811                                self.err_ctxt().ty_kind_suggestion(self.param_env, ty)812                            {813                                err.span_suggestion_verbose(814                                    expr.span.shrink_to_hi(),815                                    "give the `break` a value of the expected type",816                                    format!(" {val}"),817                                    Applicability::HasPlaceholders,818                                );819                            }820                        },821                        false,822                    );823                }824            } else {825                // If `ctxt.coerce` is `None`, we can just ignore826                // the type of the expression. This is because827                // either this was a break *without* a value, in828                // which case it is always a legal type (`()`), or829                // else an error would have been flagged by the830                // `loops` pass for using break with an expression831                // where you are not supposed to.832                assert!(expr_opt.is_none() || self.tainted_by_errors().is_some());833            }834835            // If we encountered a `break`, then (no surprise) it may be possible to break from the836            // loop... unless the value being returned from the loop diverges itself, e.g.837            // `break return 5` or `break loop {}`.838            ctxt.may_break |= !self.diverges.get().is_always();839840            // the type of a `break` is always `!`, since it diverges841            tcx.types.never842        } else {843            // Otherwise, we failed to find the enclosing loop;844            // this can only happen if the `break` was not845            // inside a loop at all, which is caught by the846            // loop-checking pass.847            let err = Ty::new_error_with_message(848                self.tcx,849                expr.span,850                "break was outside loop, but no error was emitted",851            );852853            // We still need to assign a type to the inner expression to854            // prevent the ICE in #43162.855            if let Some(e) = expr_opt {856                self.check_expr_with_hint(e, err);857858                // ... except when we try to 'break rust;'.859                // ICE this expression in particular (see #43162).860                if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind {861                    if let [segment] = path.segments862                        && segment.ident.name == sym::rust863                    {864                        fatally_break_rust(self.tcx, expr.span);865                    }866                }867            }868869            // There was an error; make type-check fail.870            err871        }872    }873874    fn check_expr_continue(875        &self,876        destination: hir::Destination,877        expr: &'tcx hir::Expr<'tcx>,878    ) -> Ty<'tcx> {879        if let Ok(target_id) = destination.target_id {880            if let hir::Node::Expr(hir::Expr { kind: ExprKind::Loop(..), .. }) =881                self.tcx.hir_node(target_id)882            {883                self.tcx.types.never884            } else {885                // Liveness linting assumes `continue`s all point to loops. We'll report an error886                // in `check_mod_loops`, but make sure we don't run liveness (#113379, #121623).887                let guar = self.dcx().span_delayed_bug(888                    expr.span,889                    "found `continue` not pointing to loop, but no error reported",890                );891                Ty::new_error(self.tcx, guar)892            }893        } else {894            // There was an error; make type-check fail.895            Ty::new_misc_error(self.tcx)896        }897    }898899    fn check_expr_return(900        &self,901        expr_opt: Option<&'tcx hir::Expr<'tcx>>,902        expr: &'tcx hir::Expr<'tcx>,903    ) -> Ty<'tcx> {904        if self.ret_coercion.is_none() {905            self.emit_return_outside_of_fn_body(expr, ReturnLikeStatementKind::Return);906907            if let Some(e) = expr_opt {908                // We still have to type-check `e` (issue #86188), but calling909                // `check_return_expr` only works inside fn bodies.910                self.check_expr(e);911            }912        } else if let Some(e) = expr_opt {913            if self.ret_coercion_span.get().is_none() {914                self.ret_coercion_span.set(Some(e.span));915            }916            self.check_return_or_body_tail(e, true);917        } else {918            let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();919            if self.ret_coercion_span.get().is_none() {920                self.ret_coercion_span.set(Some(expr.span));921            }922            let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);923            if let Some((_, fn_decl)) = self.get_fn_decl(expr.hir_id) {924                coercion.coerce_forced_unit(925                    self,926                    &cause,927                    |db| {928                        let span = fn_decl.output.span();929                        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {930                            db.span_label(931                                span,932                                format!("expected `{snippet}` because of this return type"),933                            );934                        }935                    },936                    true,937                );938            } else {939                coercion.coerce_forced_unit(self, &cause, |_| (), true);940            }941        }942        self.tcx.types.never943    }944945    fn check_expr_become(946        &self,947        call: &'tcx hir::Expr<'tcx>,948        expr: &'tcx hir::Expr<'tcx>,949    ) -> Ty<'tcx> {950        match &self.ret_coercion {951            Some(ret_coercion) => {952                let ret_ty = ret_coercion.borrow().expected_ty();953                let call_expr_ty = self.check_expr_with_hint(call, ret_ty);954955                // N.B. don't coerce here, as tail calls can't support most/all coercions956                // FIXME(explicit_tail_calls): add a diagnostic note that `become` doesn't allow coercions957                self.demand_suptype(expr.span, ret_ty, call_expr_ty);958            }959            None => {960                self.emit_return_outside_of_fn_body(expr, ReturnLikeStatementKind::Become);961962                // Fallback to simply type checking `call` without hint/demanding the right types.963                // Best effort to highlight more errors.964                self.check_expr(call);965            }966        }967968        self.tcx.types.never969    }970971    /// Check an expression that _is being returned_.972    /// For example, this is called with `return_expr: $expr` when `return $expr`973    /// is encountered.974    ///975    /// Note that this function must only be called in function bodies.976    ///977    /// `explicit_return` is `true` if we're checking an explicit `return expr`,978    /// and `false` if we're checking a trailing expression.979    pub(super) fn check_return_or_body_tail(980        &self,981        return_expr: &'tcx hir::Expr<'tcx>,982        explicit_return: bool,983    ) {984        let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| {985            span_bug!(return_expr.span, "check_return_expr called outside fn body")986        });987988        let ret_ty = ret_coercion.borrow().expected_ty();989        let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty);990        let mut span = return_expr.span;991        let mut hir_id = return_expr.hir_id;992        // Use the span of the trailing expression for our cause,993        // not the span of the entire function994        if !explicit_return995            && let ExprKind::Block(body, _) = return_expr.kind996            && let Some(last_expr) = body.expr997        {998            span = last_expr.span;999            hir_id = last_expr.hir_id;1000        }1001        ret_coercion.borrow_mut().coerce(1002            self,1003            &self.cause(span, ObligationCauseCode::ReturnValue(return_expr.hir_id)),1004            return_expr,1005            return_expr_ty,1006        );10071008        if let Some(fn_sig) = self.fn_sig()1009            && fn_sig.output().has_opaque_types()1010        {1011            // Point any obligations that were registered due to opaque type1012            // inference at the return expression.1013            self.select_obligations_where_possible(|errors| {1014                self.point_at_return_for_opaque_ty_error(1015                    errors,1016                    hir_id,1017                    span,1018                    return_expr_ty,1019                    return_expr.span,1020                );1021            });1022        }1023    }10241025    /// Emit an error because `return` or `become` is used outside of a function body.1026    ///1027    /// `expr` is the `return` (`become`) "statement", `kind` is the kind of the statement1028    /// either `Return` or `Become`.1029    fn emit_return_outside_of_fn_body(&self, expr: &hir::Expr<'_>, kind: ReturnLikeStatementKind) {1030        let mut err = ReturnStmtOutsideOfFnBody {1031            span: expr.span,1032            encl_body_span: None,1033            encl_fn_span: None,1034            statement_kind: kind,1035        };10361037        let encl_item_id = self.tcx.hir_get_parent_item(expr.hir_id);10381039        if let hir::Node::Item(hir::Item {1040            kind: hir::ItemKind::Fn { .. },1041            span: encl_fn_span,1042            ..1043        })1044        | hir::Node::TraitItem(hir::TraitItem {1045            kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),1046            span: encl_fn_span,1047            ..1048        })1049        | hir::Node::ImplItem(hir::ImplItem {1050            kind: hir::ImplItemKind::Fn(..),1051            span: encl_fn_span,1052            ..1053        }) = self.tcx.hir_node_by_def_id(encl_item_id.def_id)1054        {1055            // We are inside a function body, so reporting "return statement1056            // outside of function body" needs an explanation.10571058            let encl_body_owner_id = self.tcx.hir_enclosing_body_owner(expr.hir_id);10591060            // If this didn't hold, we would not have to report an error in1061            // the first place.1062            assert_ne!(encl_item_id.def_id, encl_body_owner_id);10631064            let encl_body = self.tcx.hir_body_owned_by(encl_body_owner_id);10651066            err.encl_body_span = Some(encl_body.value.span);1067            err.encl_fn_span = Some(*encl_fn_span);1068        }10691070        self.dcx().emit_err(err);1071    }10721073    fn point_at_return_for_opaque_ty_error(1074        &self,1075        errors: &mut ThinVec<traits::FulfillmentError<'tcx>>,1076        hir_id: HirId,1077        span: Span,1078        return_expr_ty: Ty<'tcx>,1079        return_span: Span,1080    ) {1081        // Don't point at the whole block if it's empty1082        if span == return_span {1083            return;1084        }1085        for err in errors {1086            let cause = &mut err.obligation.cause;1087            if let ObligationCauseCode::OpaqueReturnType(None) = cause.code() {1088                let new_cause = self.cause(1089                    cause.span,1090                    ObligationCauseCode::OpaqueReturnType(Some((return_expr_ty, hir_id))),1091                );1092                *cause = new_cause;1093            }1094        }1095    }10961097    pub(crate) fn check_lhs_assignable(1098        &self,1099        lhs: &'tcx hir::Expr<'tcx>,1100        code: ErrCode,1101        op_span: Span,1102        adjust_err: impl FnOnce(&mut Diag<'_>),1103    ) {1104        if lhs.is_syntactic_place_expr() {1105            return;1106        }11071108        // Skip suggestion if LHS contains a let-chain at this would likely be spurious1109        // cc: https://github.com/rust-lang/rust/issues/1476641110        if contains_let_in_chain(lhs) {1111            return;1112        }11131114        let mut err = self.dcx().struct_span_err(op_span, "invalid left-hand side of assignment");1115        err.code(code);1116        err.span_label(lhs.span, "cannot assign to this expression");11171118        self.comes_from_while_condition(lhs.hir_id, |expr| {1119            err.span_suggestion_verbose(1120                expr.span.shrink_to_lo(),1121                "you might have meant to use pattern destructuring",1122                "let ",1123                Applicability::MachineApplicable,1124            );1125        });1126        self.check_for_missing_semi(lhs, &mut err);11271128        adjust_err(&mut err);11291130        err.emit();1131    }11321133    /// Check if the expression that could not be assigned to was a typoed expression that1134    pub(crate) fn check_for_missing_semi(1135        &self,1136        expr: &'tcx hir::Expr<'tcx>,1137        err: &mut Diag<'_>,1138    ) -> bool {1139        if let hir::ExprKind::Binary(binop, lhs, rhs) = expr.kind1140            && let hir::BinOpKind::Mul = binop.node1141            && self.tcx.sess.source_map().is_multiline(lhs.span.between(rhs.span))1142            && rhs.is_syntactic_place_expr()1143        {1144            //      v missing semicolon here1145            // foo()1146            // *bar = baz;1147            // (#80446).1148            err.span_suggestion_verbose(1149                lhs.span.shrink_to_hi(),1150                "you might have meant to write a semicolon here",1151                ";",1152                Applicability::MachineApplicable,1153            );1154            return true;1155        }1156        false1157    }11581159    // Check if an expression `original_expr_id` comes from the condition of a while loop,1160    /// as opposed from the body of a while loop, which we can naively check by iterating1161    /// parents until we find a loop...1162    pub(super) fn comes_from_while_condition(1163        &self,1164        original_expr_id: HirId,1165        then: impl FnOnce(&hir::Expr<'_>),1166    ) {1167        let mut parent = self.tcx.parent_hir_id(original_expr_id);1168        loop {1169            let node = self.tcx.hir_node(parent);1170            match node {1171                hir::Node::Expr(hir::Expr {1172                    kind:1173                        hir::ExprKind::Loop(1174                            hir::Block {1175                                expr:1176                                    Some(hir::Expr {1177                                        kind:1178                                            hir::ExprKind::Match(expr, ..) | hir::ExprKind::If(expr, ..),1179                                        ..1180                                    }),1181                                ..1182                            },1183                            _,1184                            hir::LoopSource::While,1185                            _,1186                        ),1187                    ..1188                }) => {1189                    // Check if our original expression is a child of the condition of a while loop.1190                    // If it is, then we have a situation like `while Some(0) = value.get(0) {`,1191                    // where `while let` was more likely intended.1192                    if self.tcx.hir_parent_id_iter(original_expr_id).any(|id| id == expr.hir_id) {1193                        then(expr);1194                    }1195                    break;1196                }1197                hir::Node::Item(_)1198                | hir::Node::ImplItem(_)1199                | hir::Node::TraitItem(_)1200                | hir::Node::Crate(_) => break,1201                _ => {1202                    parent = self.tcx.parent_hir_id(parent);1203                }1204            }1205        }1206    }12071208    // A generic function for checking the 'then' and 'else' clauses in an 'if'1209    // or 'if-else' expression.1210    fn check_expr_if(1211        &self,1212        expr_id: HirId,1213        cond_expr: &'tcx hir::Expr<'tcx>,1214        then_expr: &'tcx hir::Expr<'tcx>,1215        opt_else_expr: Option<&'tcx hir::Expr<'tcx>>,1216        sp: Span,1217        orig_expected: Expectation<'tcx>,1218    ) -> Ty<'tcx> {1219        let cond_ty = self.check_expr_has_type_or_error(cond_expr, self.tcx.types.bool, |_| {});12201221        self.warn_if_unreachable(1222            cond_expr.hir_id,1223            then_expr.span,1224            "block in `if` or `while` expression",1225        );12261227        let cond_diverges = self.diverges.get();1228        self.diverges.set(Diverges::Maybe);12291230        let expected = orig_expected.try_structurally_resolve_and_adjust_for_branches(self);1231        let then_ty = self.check_expr_with_expectation(then_expr, expected);1232        let then_diverges = self.diverges.get();1233        self.diverges.set(Diverges::Maybe);12341235        // We've already taken the expected type's preferences1236        // into account when typing the `then` branch. To figure1237        // out the initial shot at a LUB, we thus only consider1238        // `expected` if it represents a *hard* constraint1239        // (`only_has_type`); otherwise, we just go with a1240        // fresh type variable.1241        let coerce_to_ty = expected.coercion_target_type(self, sp);1242        let mut coerce = CoerceMany::with_capacity(coerce_to_ty, 2);12431244        coerce.coerce(self, &self.misc(sp), then_expr, then_ty);12451246        if let Some(else_expr) = opt_else_expr {1247            let else_ty = self.check_expr_with_expectation(else_expr, expected);1248            let else_diverges = self.diverges.get();12491250            let tail_defines_return_position_impl_trait =1251                self.return_position_impl_trait_from_match_expectation(orig_expected);1252            let if_cause =1253                self.if_cause(expr_id, else_expr, tail_defines_return_position_impl_trait);12541255            coerce.coerce(self, &if_cause, else_expr, else_ty);12561257            // We won't diverge unless both branches do (or the condition does).1258            self.diverges.set(cond_diverges | then_diverges & else_diverges);1259        } else {1260            self.if_fallback_coercion(sp, cond_expr, then_expr, &mut coerce);12611262            // If the condition is false we can't diverge.1263            self.diverges.set(cond_diverges);1264        }12651266        let result_ty = coerce.complete(self);1267        if let Err(guar) = cond_ty.error_reported() {1268            Ty::new_error(self.tcx, guar)1269        } else {1270            result_ty1271        }1272    }12731274    /// Type check assignment expression `expr` of form `lhs = rhs`.1275    /// The expected type is `()` and is passed to the function for the purposes of diagnostics.1276    fn check_expr_assign(1277        &self,1278        expr: &'tcx hir::Expr<'tcx>,1279        expected: Expectation<'tcx>,1280        lhs: &'tcx hir::Expr<'tcx>,1281        rhs: &'tcx hir::Expr<'tcx>,1282        span: Span,1283    ) -> Ty<'tcx> {1284        let expected_ty = expected.only_has_type(self);1285        if expected_ty == Some(self.tcx.types.bool) {1286            let guar = self.expr_assign_expected_bool_error(expr, lhs, rhs, span);1287            return Ty::new_error(self.tcx, guar);1288        }12891290        let lhs_ty = self.check_expr_with_needs(lhs, Needs::MutPlace);12911292        let suggest_deref_binop = |err: &mut Diag<'_>, rhs_ty: Ty<'tcx>| {1293            if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) {1294                // Can only assign if the type is sized, so if `DerefMut` yields a type that is1295                // unsized, do not suggest dereferencing it.1296                let lhs_deref_ty_is_sized = self1297                    .infcx1298                    .type_implements_trait(1299                        self.tcx.require_lang_item(LangItem::Sized, span),1300                        [lhs_deref_ty],1301                        self.param_env,1302                    )1303                    .may_apply();1304                if lhs_deref_ty_is_sized && self.may_coerce(rhs_ty, lhs_deref_ty) {1305                    err.span_suggestion_verbose(1306                        lhs.span.shrink_to_lo(),1307                        "consider dereferencing here to assign to the mutably borrowed value",1308                        "*",1309                        Applicability::MachineApplicable,1310                    );1311                }1312            }1313        };13141315        // This is (basically) inlined `check_expr_coercible_to_type`, but we want1316        // to suggest an additional fixup here in `suggest_deref_binop`.1317        let rhs_ty = self.check_expr_with_hint(rhs, lhs_ty);1318        if let Err(mut diag) =1319            self.demand_coerce_diag(rhs, rhs_ty, lhs_ty, Some(lhs), AllowTwoPhase::No)1320        {1321            suggest_deref_binop(&mut diag, rhs_ty);1322            diag.emit();1323        }13241325        self.check_lhs_assignable(lhs, E0070, span, |err| {1326            if let Some(rhs_ty) = self.typeck_results.borrow().expr_ty_opt(rhs) {1327                suggest_deref_binop(err, rhs_ty);1328            }1329        });13301331        self.require_type_is_sized(lhs_ty, lhs.span, ObligationCauseCode::AssignmentLhsSized);13321333        if let Err(guar) = (lhs_ty, rhs_ty).error_reported() {1334            Ty::new_error(self.tcx, guar)1335        } else {1336            self.tcx.types.unit1337        }1338    }13391340    /// The expected type is `bool` but this will result in `()` so we can reasonably1341    /// say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.1342    /// The likely cause of this is `if foo = bar { .. }`.1343    fn expr_assign_expected_bool_error(1344        &self,1345        expr: &'tcx hir::Expr<'tcx>,1346        lhs: &'tcx hir::Expr<'tcx>,1347        rhs: &'tcx hir::Expr<'tcx>,1348        span: Span,1349    ) -> ErrorGuaranteed {1350        let actual_ty = self.tcx.types.unit;1351        let expected_ty = self.tcx.types.bool;1352        let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap_err();1353        let lhs_ty = self.check_expr(lhs);1354        let rhs_ty = self.check_expr(rhs);1355        let refs_can_coerce = |lhs: Ty<'tcx>, rhs: Ty<'tcx>| {1356            let lhs = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, lhs.peel_refs());1357            let rhs = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rhs.peel_refs());1358            self.may_coerce(rhs, lhs)1359        };1360        // Never-to-any coercions do not imply that the operands can be compared, e.g. `String == !`.1361        let (applicability, eq) = if self.may_coerce_except_never(rhs_ty, lhs_ty) {1362            (Applicability::MachineApplicable, true)1363        } else if refs_can_coerce(rhs_ty, lhs_ty) {1364            // The lhs and rhs are likely missing some references in either side. Subsequent1365            // suggestions will show up.1366            (Applicability::MaybeIncorrect, true)1367        } else if let ExprKind::Binary(1368            Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },1369            _,1370            rhs_expr,1371        ) = lhs.kind1372        {1373            // if x == 1 && y == 2 { .. }1374            //                 +1375            let actual_lhs = self.check_expr(rhs_expr);1376            let may_eq = self.may_coerce_except_never(rhs_ty, actual_lhs)1377                || refs_can_coerce(rhs_ty, actual_lhs);1378            (Applicability::MaybeIncorrect, may_eq)1379        } else if let ExprKind::Binary(1380            Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },1381            lhs_expr,1382            _,1383        ) = rhs.kind1384        {1385            // if x == 1 && y == 2 { .. }1386            //       +1387            let actual_rhs = self.check_expr(lhs_expr);1388            let may_eq = self.may_coerce_except_never(actual_rhs, lhs_ty)1389                || refs_can_coerce(actual_rhs, lhs_ty);1390            (Applicability::MaybeIncorrect, may_eq)1391        } else {1392            (Applicability::MaybeIncorrect, false)1393        };13941395        if !lhs.is_syntactic_place_expr()1396            && lhs.is_approximately_pattern()1397            && !matches!(lhs.kind, hir::ExprKind::Lit(_))1398        {1399            // Do not suggest `if let x = y` as `==` is way more likely to be the intention.1400            if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) =1401                self.tcx.parent_hir_node(expr.hir_id)1402            {1403                err.span_suggestion_verbose(1404                    expr.span.shrink_to_lo(),1405                    "you might have meant to use pattern matching",1406                    "let ",1407                    applicability,1408                );1409            };1410        }1411        if eq {1412            err.span_suggestion_verbose(1413                span.shrink_to_hi(),1414                "you might have meant to compare for equality",1415                '=',1416                applicability,1417            );1418        }14191420        // If the assignment expression itself is ill-formed, don't1421        // bother emitting another error1422        err.emit_err_unless_delay(lhs_ty.references_error() || rhs_ty.references_error())1423    }14241425    pub(super) fn check_expr_let(1426        &self,1427        let_expr: &'tcx hir::LetExpr<'tcx>,1428        hir_id: HirId,1429    ) -> Ty<'tcx> {1430        GatherLocalsVisitor::gather_from_let_expr(self, let_expr, hir_id);14311432        // for let statements, this is done in check_stmt1433        let init = let_expr.init;1434        self.warn_if_unreachable(init.hir_id, init.span, "block in `let` expression");14351436        // otherwise check exactly as a let statement1437        self.check_decl((let_expr, hir_id).into());14381439        // but return a bool, for this is a boolean expression1440        if let ast::Recovered::Yes(error_guaranteed) = let_expr.recovered {1441            self.set_tainted_by_errors(error_guaranteed);1442            Ty::new_error(self.tcx, error_guaranteed)1443        } else {1444            self.tcx.types.bool1445        }1446    }14471448    fn check_expr_loop(1449        &self,1450        body: &'tcx hir::Block<'tcx>,1451        source: hir::LoopSource,1452        expected: Expectation<'tcx>,1453        expr: &'tcx hir::Expr<'tcx>,1454    ) -> Ty<'tcx> {1455        let coerce = match source {1456            // you can only use break with a value from a normal `loop { }`1457            hir::LoopSource::Loop => {1458                let coerce_to = expected.coercion_target_type(self, body.span);1459                Some(CoerceMany::new(coerce_to))1460            }14611462            hir::LoopSource::While | hir::LoopSource::ForLoop => None,1463        };14641465        let ctxt = BreakableCtxt {1466            coerce,1467            may_break: false, // Will get updated if/when we find a `break`.1468        };14691470        let (ctxt, ()) = self.with_breakable_ctxt(expr.hir_id, ctxt, || {1471            self.check_block_no_value(body);1472        });14731474        if ctxt.may_break {1475            // No way to know whether it's diverging because1476            // of a `break` or an outer `break` or `return`.1477            self.diverges.set(Diverges::Maybe);1478        } else {1479            self.diverges.set(self.diverges.get() | Diverges::always(expr.span));1480        }14811482        // If we permit break with a value, then result type is1483        // the LUB of the breaks (possibly ! if none); else, it1484        // is nil. This makes sense because infinite loops1485        // (which would have type !) are only possible iff we1486        // permit break with a value.1487        if ctxt.coerce.is_none() && !ctxt.may_break {1488            self.dcx().span_bug(body.span, "no coercion, but loop may not break");1489        }1490        ctxt.coerce.map(|c| c.complete(self)).unwrap_or_else(|| self.tcx.types.unit)1491    }14921493    /// Checks a method call.1494    fn check_expr_method_call(1495        &self,1496        expr: &'tcx hir::Expr<'tcx>,1497        segment: &'tcx hir::PathSegment<'tcx>,1498        rcvr: &'tcx hir::Expr<'tcx>,1499        args: &'tcx [hir::Expr<'tcx>],1500        expected: Expectation<'tcx>,1501    ) -> Ty<'tcx> {1502        let rcvr_t = self.check_expr(rcvr);1503        let rcvr_t = self.deeply_resolve_ignoring_regions_with_obligations(rcvr_t);15041505        match self.lookup_method(rcvr_t, segment, segment.ident.span, expr, rcvr, args) {1506            Ok(method) => {1507                self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);15081509                // Handle splatted method arguments1510                // self is already handled as `rcvr`, so it's never splatted here1511                let mut method_inputs = Cow::Borrowed(&method.sig.inputs()[1..]);1512                for (param, pos) in self.tcx.generics_of(method.def_id).own_arg_pos_consts() {1513                    let ty = self1514                        .tcx1515                        .type_of(param.def_id)1516                        .instantiate(self.tcx, method.args)1517                        .skip_norm_wip();1518                    // Insert function argument const param types back into the inputs.1519                    // We use pos - 1 since method_inputs skips self, but arg_pos counts it.1520                    method_inputs.to_mut().insert(pos as usize - 1, ty);1521                }15221523                let method_tuple_args_flag =1524                    TupleArgumentsFlag::with_fn_sig_kind(method.sig.fn_sig_kind, true);15251526                self.check_argument_types(1527                    segment.ident.span,1528                    expr,1529                    &method_inputs,1530                    method.sig.output(),1531                    expected,1532                    args,1533                    method.sig.fn_sig_kind.c_variadic(),1534                    method_tuple_args_flag,1535                    SplatLoweringInfo::FnDef(method.def_id),1536                    Some(method.args),1537                );15381539                self.check_call_abi(method.sig.abi(), expr.span);15401541                method.sig.output()1542            }1543            Err(error) => {1544                let guar = self.report_method_error(expr.hir_id, rcvr_t, error, expected, false);15451546                let err_inputs = self.err_args(args.len(), guar);1547                let err_ty = Ty::new_error(self.tcx, guar);15481549                self.check_argument_types(1550                    segment.ident.span,1551                    expr,1552                    &err_inputs,1553                    err_ty,1554                    NoExpectation,1555                    args,1556                    false,1557                    TupleArgumentsFlag::DontTupleArguments,1558                    SplatLoweringInfo::Error(guar),1559                    Some(GenericArgsRef::default()),1560                );15611562                err_ty1563            }1564        }1565    }15661567    /// Checks use `x.use`.1568    fn check_expr_use(1569        &self,1570        used_expr: &'tcx hir::Expr<'tcx>,1571        expected: Expectation<'tcx>,1572    ) -> Ty<'tcx> {1573        self.check_expr_with_expectation(used_expr, expected)1574    }15751576    fn check_expr_cast(1577        &self,1578        e: &'tcx hir::Expr<'tcx>,1579        t: &'tcx hir::Ty<'tcx>,1580        expr: &'tcx hir::Expr<'tcx>,1581    ) -> Ty<'tcx> {1582        // Find the type of `e`. Supply hints based on the type we are casting to,1583        // if appropriate.1584        let t_cast = self.lower_ty_saving_user_provided_ty(t);1585        let t_cast = self.deeply_resolve_ignoring_regions(t_cast);1586        let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));1587        let t_expr = self.deeply_resolve_ignoring_regions(t_expr);15881589        // Eagerly check for some obvious errors.1590        if let Err(guar) = (t_expr, t_cast).error_reported() {1591            Ty::new_error(self.tcx, guar)1592        } else {1593            // Defer other checks until we're done type checking.1594            let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();1595            match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) {1596                Ok(cast_check) => {1597                    debug!(1598                        "check_expr_cast: deferring cast from {:?} to {:?}: {:?}",1599                        t_cast, t_expr, cast_check,1600                    );1601                    deferred_cast_checks.push(cast_check);1602                    t_cast1603                }1604                Err(guar) => Ty::new_error(self.tcx, guar),1605            }1606        }1607    }16081609    fn check_expr_unsafe_binder_cast(1610        &self,1611        span: Span,1612        kind: ast::UnsafeBinderCastKind,1613        inner_expr: &'tcx hir::Expr<'tcx>,1614        hir_ty: Option<&'tcx hir::Ty<'tcx>>,1615        expected: Expectation<'tcx>,1616    ) -> Ty<'tcx> {1617        match kind {1618            ast::UnsafeBinderCastKind::Wrap => {1619                let ascribed_ty =1620                    hir_ty.map(|hir_ty| self.lower_ty_saving_user_provided_ty(hir_ty));1621                let expected_ty = expected.only_has_type(self);1622                let binder_ty = match (ascribed_ty, expected_ty) {1623                    (Some(ascribed_ty), Some(expected_ty)) => {1624                        self.demand_eqtype(inner_expr.span, expected_ty, ascribed_ty);1625                        expected_ty1626                    }1627                    (Some(ty), None) | (None, Some(ty)) => ty,1628                    // This will always cause a structural resolve error, but we do it1629                    // so we don't need to manually report an E0282 both on this codepath1630                    // and in the others; it all happens in `structurally_resolve_type`.1631                    (None, None) => self.next_ty_var(inner_expr.span),1632                };16331634                let binder_ty = self.structurally_resolve_type(inner_expr.span, binder_ty);1635                let hint_ty = match *binder_ty.kind() {1636                    ty::UnsafeBinder(binder) => self.instantiate_binder_with_fresh_vars(1637                        inner_expr.span,1638                        infer::BoundRegionConversionTime::HigherRankedType,1639                        binder.into(),1640                    ),1641                    ty::Error(e) => Ty::new_error(self.tcx, e),1642                    _ => {1643                        let guar = self1644                            .dcx()1645                            .struct_span_err(1646                                hir_ty.map_or(span, |hir_ty| hir_ty.span),1647                                format!(1648                                    "`wrap_binder!()` can only wrap into unsafe binder, not {}",1649                                    binder_ty.sort_string(self.tcx)1650                                ),1651                            )1652                            .with_note("unsafe binders are the only valid output of wrap")1653                            .emit_err();1654                        Ty::new_error(self.tcx, guar)1655                    }1656                };16571658                self.check_expr_has_type_or_error(inner_expr, hint_ty, |_| {});16591660                binder_ty1661            }1662            ast::UnsafeBinderCastKind::Unwrap => {1663                let ascribed_ty =1664                    hir_ty.map(|hir_ty| self.lower_ty_saving_user_provided_ty(hir_ty));1665                let hint_ty = ascribed_ty.unwrap_or_else(|| self.next_ty_var(inner_expr.span));1666                // FIXME(unsafe_binders): coerce here if needed?1667                let binder_ty = self.check_expr_has_type_or_error(inner_expr, hint_ty, |_| {});16681669                // Unwrap the binder. This will be ambiguous if it's an infer var, and will error1670                // if it's not an unsafe binder.1671                let binder_ty = self.structurally_resolve_type(inner_expr.span, binder_ty);1672                match *binder_ty.kind() {1673                    ty::UnsafeBinder(binder) => self.instantiate_binder_with_fresh_vars(1674                        inner_expr.span,1675                        infer::BoundRegionConversionTime::HigherRankedType,1676                        binder.into(),1677                    ),1678                    ty::Error(e) => Ty::new_error(self.tcx, e),1679                    _ => {1680                        let guar = self1681                            .dcx()1682                            .struct_span_err(1683                                hir_ty.map_or(inner_expr.span, |hir_ty| hir_ty.span),1684                                format!(1685                                    "expected unsafe binder, found {} as input of \1686                                    `unwrap_binder!()`",1687                                    binder_ty.sort_string(self.tcx)1688                                ),1689                            )1690                            .with_note("only an unsafe binder type can be unwrapped")1691                            .emit_err();1692                        Ty::new_error(self.tcx, guar)1693                    }1694                }1695            }1696        }1697    }16981699    fn check_expr_array(1700        &self,1701        args: &'tcx [hir::Expr<'tcx>],1702        expected: Expectation<'tcx>,1703        expr: &'tcx hir::Expr<'tcx>,1704    ) -> Ty<'tcx> {1705        let element_ty = if !args.is_empty() {1706            let coerce_to = expected1707                .to_option(self)1708                .and_then(|uty| {1709                    self.deeply_resolve_ignoring_regions_with_obligations(uty)1710                        .builtin_index()1711                        // Avoid using the original type variable as the coerce_to type, as it may resolve1712                        // during the first coercion instead of being the LUB type.1713                        .filter(|t| {1714                            !self.deeply_resolve_ignoring_regions_with_obligations(*t).is_ty_var()1715                        })1716                })1717                .unwrap_or_else(|| self.next_ty_var(expr.span));1718            let mut coerce = CoerceMany::with_capacity(coerce_to, args.len());17191720            for e in args {1721                // FIXME: the element expectation should use1722                // `try_structurally_resolve_and_adjust_for_branches` just like in `if` and `match`.1723                // While that fixes nested coercion, it will break [some1724                // code like this](https://github.com/rust-lang/rust/pull/140283#issuecomment-2958776528).1725                // If we find a way to support recursive tuple coercion, this break can be avoided.1726                let e_ty = self.check_expr_with_hint(e, coerce_to);1727                let cause = self.misc(e.span);1728                coerce.coerce(self, &cause, e, e_ty);1729            }1730            coerce.complete(self)1731        } else {1732            self.next_ty_var(expr.span)1733        };1734        let array_len = args.len() as u64;1735        Ty::new_array(self.tcx, element_ty, array_len)1736    }17371738    pub(super) fn check_expr_const_block(1739        &self,1740        block: &'tcx hir::ConstBlock,1741        expected: Expectation<'tcx>,1742    ) -> Ty<'tcx> {1743        let body = self.tcx.hir_body(block.body);17441745        // Create a new function context.1746        let def_id = block.def_id;1747        let fcx = FnCtxt::new(self, self.param_env, def_id);17481749        let ty = fcx.check_expr_with_expectation(&body.value, expected);1750        fcx.require_type_is_sized(ty, body.value.span, ObligationCauseCode::SizedConstOrStatic);1751        fcx.write_ty(block.hir_id, ty);1752        ty1753    }17541755    fn check_expr_repeat(1756        &self,1757        element: &'tcx hir::Expr<'tcx>,1758        count: &'tcx hir::ConstArg<'tcx>,1759        expected: Expectation<'tcx>,1760        expr: &'tcx hir::Expr<'tcx>,1761    ) -> Ty<'tcx> {1762        let tcx = self.tcx;1763        let count_span = count.span;1764        let count = self.try_structurally_resolve_const(1765            count_span,1766            self.normalize(1767                count_span,1768                Unnormalized::new_wip(self.lower_const_arg(count, tcx.types.usize)),1769            ),1770        );17711772        let uty = match expected {1773            ExpectHasType(uty) => uty.builtin_index(),1774            _ => None,1775        };17761777        let (element_ty, t) = match uty {1778            Some(uty) => {1779                self.check_expr_coercible_to_type(element, uty, None);1780                (uty, uty)1781            }1782            None => {1783                let ty = self.next_ty_var(element.span);1784                let element_ty = self.check_expr_has_type_or_error(element, ty, |_| {});1785                (element_ty, ty)1786            }1787        };17881789        if let Err(guar) = element_ty.error_reported() {1790            return Ty::new_error(tcx, guar);1791        }17921793        // We defer checking whether the element type is `Copy` as it is possible to have1794        // an inference variable as a repeat count and it seems unlikely that `Copy` would1795        // have inference side effects required for type checking to succeed.1796        self.deferred_repeat_expr_checks.borrow_mut().push((element, element_ty, count));17971798        let ty = Ty::new_array_with_const_len(tcx, t, count);1799        self.register_wf_obligation(1800            ty.into(),1801            expr.span,1802            ObligationCauseCode::WellFormed(WellFormedLoc::HirId(expr.hir_id)),1803        );1804        ty1805    }18061807    fn check_expr_tuple(1808        &self,1809        elements: &'tcx [hir::Expr<'tcx>],1810        expected: Expectation<'tcx>,1811        expr: &'tcx hir::Expr<'tcx>,1812    ) -> Ty<'tcx> {1813        let mut expectations = expected1814            .only_has_type(self)1815            .and_then(|ty| {1816                self.deeply_resolve_ignoring_regions_with_obligations(ty).opt_tuple_fields()1817            })1818            .unwrap_or_default()1819            .iter();18201821        let elements = elements.iter().map(|e| {1822            let ty = expectations.next().unwrap_or_else(|| self.next_ty_var(e.span));1823            self.check_expr_coercible_to_type(e, ty, None);1824            ty1825        });18261827        let tuple = Ty::new_tup_from_iter(self.tcx, elements);18281829        if let Err(guar) = tuple.error_reported() {1830            Ty::new_error(self.tcx, guar)1831        } else {1832            self.require_type_is_sized(1833                tuple,1834                expr.span,1835                ObligationCauseCode::TupleInitializerSized,1836            );1837            tuple1838        }1839    }18401841    fn check_expr_struct(1842        &self,1843        expr: &hir::Expr<'tcx>,1844        expected: Expectation<'tcx>,1845        qpath: &'tcx QPath<'tcx>,1846        fields: &'tcx [hir::ExprField<'tcx>],1847        base_expr: &'tcx hir::StructTailExpr<'tcx>,1848    ) -> Ty<'tcx> {1849        // Find the relevant variant1850        let (variant, adt_ty) = match self.check_struct_path(qpath, expr.hir_id) {1851            Ok(data) => data,1852            Err(guar) => {1853                self.check_struct_fields_on_error(fields, base_expr);1854                return Ty::new_error(self.tcx, guar);1855            }1856        };18571858        // Prohibit struct expressions when non-exhaustive flag is set.1859        let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type");1860        if variant.field_list_has_applicable_non_exhaustive() {1861            self.dcx()1862                .emit_err(StructExprNonExhaustive { span: expr.span, what: adt.variant_descr() });1863        }18641865        self.check_expr_struct_fields(1866            adt_ty,1867            expected,1868            expr,1869            qpath.span(),1870            variant,1871            fields,1872            base_expr,1873        );18741875        self.require_type_is_sized(adt_ty, expr.span, ObligationCauseCode::StructInitializerSized);1876        adt_ty1877    }18781879    fn check_expr_struct_fields(1880        &self,1881        adt_ty: Ty<'tcx>,1882        expected: Expectation<'tcx>,1883        expr: &hir::Expr<'_>,1884        path_span: Span,1885        variant: &'tcx ty::VariantDef,1886        hir_fields: &'tcx [hir::ExprField<'tcx>],1887        base_expr: &'tcx hir::StructTailExpr<'tcx>,1888    ) {1889        let tcx = self.tcx;18901891        let adt_ty = self.deeply_resolve_ignoring_regions_with_obligations(adt_ty);1892        let adt_ty_hint = expected.only_has_type(self).and_then(|expected| {1893            self.fudge_inference_if_ok(|| {1894                let ocx = ObligationCtxt::new(self);1895                ocx.sup(&self.misc(path_span), self.param_env, expected, adt_ty)?;1896                if !ocx.try_evaluate_obligations().no_errors() {1897                    return Err(TypeError::Mismatch);1898                }1899                Ok(self.deeply_resolve_ignoring_regions(adt_ty))1900            })1901            .ok()1902        });1903        if let Some(adt_ty_hint) = adt_ty_hint {1904            // re-link the variables that the fudging above can create.1905            self.demand_eqtype(path_span, adt_ty_hint, adt_ty);1906        }19071908        let ty::Adt(adt, args) = adt_ty.kind() else {1909            span_bug!(path_span, "non-ADT passed to check_expr_struct_fields");1910        };1911        let adt_kind = adt.adt_kind();19121913        let get_field_ident = |field: &ty::FieldDef| field.ident(tcx).normalize_to_macros_2_0();1914        let mut remaining_fields = variant1915            .fields1916            .iter_enumerated()1917            .map(|(i, field)| (get_field_ident(field), (i, field)))1918            .collect::<UnordMap<_, _>>();19191920        let mut seen_fields = FxHashMap::default();19211922        let mut error_happened = false;19231924        if variant.fields.len() != remaining_fields.len() {1925            // Some field is defined more than once. Make sure we don't try to1926            // instantiate this struct in static/const context.1927            let guar =1928                self.dcx().span_delayed_bug(expr.span, "struct fields have non-unique names");1929            self.set_tainted_by_errors(guar);1930            error_happened = true;1931        }19321933        // Type-check each field.1934        for (idx, field) in hir_fields.iter().enumerate() {1935            let ident = if field.ident.name == kw::Underscore {1936                // We are processing delegation `Self` mapping field, we expect that it is a struct1937                // with one field, so if it is not true we emit an error as we can't infer1938                // what field to use to initialize the struct.1939                // The `_` is a keyword so if user uses it during struct initialization as a field name1940                // it will be error anyway.1941                if let [v_field] = &variant.fields[..] {1942                    Ok(get_field_ident(v_field))1943                } else {1944                    Err(tcx.dcx().span_delayed_bug(1945                        field.ident.span,1946                        format!(1947                            "can not infer the delegation `Self` mapping field for {:?}",1948                            self.body_def_id1949                        ),1950                    ))1951                }1952            } else {1953                Ok(tcx.adjust_ident(field.ident, variant.def_id))1954            };19551956            let field_type = ident1957                .and_then(|ident| {1958                    if let Some((i, v_field)) = remaining_fields.remove(&ident) {1959                        seen_fields.insert(ident, field.span);1960                        self.write_field_index(field.hir_id, i);19611962                        // We don't look at stability attributes on1963                        // struct-like enums (yet...), but it's definitely not1964                        // a bug to have constructed one.1965                        if adt_kind != AdtKind::Enum {1966                            tcx.check_stability(v_field.did, Some(field.hir_id), field.span, None);1967                        }19681969                        Ok(self.field_ty(field.span, v_field, args))1970                    } else {1971                        error_happened = true;1972                        let guar = if let Some(prev_span) = seen_fields.get(&ident) {1973                            self.dcx().emit_err(FieldMultiplySpecifiedInInitializer {1974                                span: field.ident.span,1975                                prev_span: *prev_span,1976                                ident,1977                            })1978                        } else {1979                            self.report_unknown_field(1980                                adt_ty,1981                                variant,1982                                expr,1983                                field,1984                                hir_fields,1985                                adt.variant_descr(),1986                            )1987                        };19881989                        Err(guar)1990                    }1991                })1992                .unwrap_or_else(|err| Ty::new_error(tcx, err));19931994            // Check that the expected field type is WF. Otherwise, we emit no use-site error1995            // in the case of coercions for non-WF fields, which leads to incorrect error1996            // tainting. See issue #126272.1997            self.register_wf_obligation(1998                field_type.into(),1999                field.expr.span,2000                ObligationCauseCode::WellFormed(WellFormedLoc::HirId(field.expr.hir_id)),

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.

Generated by searchcode.com · powered by code_get_file + code_get_findings