1 //! Type checking expressions.
3 //! See `mod.rs` for more context on type checking in general.
5 use crate::astconv
::AstConv
as _
;
6 use crate::check
::cast
;
7 use crate::check
::coercion
::CoerceMany
;
8 use crate::check
::fatally_break_rust
;
9 use crate::check
::method
::SelfSource
;
10 use crate::check
::report_unexpected_variant_res
;
11 use crate::check
::BreakableCtxt
;
12 use crate::check
::Diverges
;
13 use crate::check
::DynamicCoerceMany
;
14 use crate::check
::Expectation
::{self, ExpectCastableToType, ExpectHasType, NoExpectation}
;
15 use crate::check
::FnCtxt
;
16 use crate::check
::Needs
;
17 use crate::check
::TupleArgumentsFlag
::DontTupleArguments
;
19 FieldMultiplySpecifiedInInitializer
, FunctionalRecordUpdateOnNonStruct
,
20 YieldExprOutsideOfGenerator
,
22 use crate::type_error_struct
;
24 use super::suggest_call_constructor
;
25 use crate::errors
::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive}
;
27 use rustc_data_structures
::fx
::FxHashMap
;
28 use rustc_data_structures
::stack
::ensure_sufficient_stack
;
30 pluralize
, struct_span_err
, Applicability
, Diagnostic
, DiagnosticBuilder
, DiagnosticId
,
31 EmissionGuarantee
, ErrorGuaranteed
,
34 use rustc_hir
::def
::{CtorKind, DefKind, Res}
;
35 use rustc_hir
::def_id
::DefId
;
36 use rustc_hir
::intravisit
::Visitor
;
37 use rustc_hir
::lang_items
::LangItem
;
38 use rustc_hir
::{ExprKind, HirId, QPath}
;
39 use rustc_infer
::infer
;
40 use rustc_infer
::infer
::type_variable
::{TypeVariableOrigin, TypeVariableOriginKind}
;
41 use rustc_infer
::infer
::InferOk
;
42 use rustc_infer
::traits
::ObligationCause
;
43 use rustc_middle
::middle
::stability
;
44 use rustc_middle
::ty
::adjustment
::{Adjust, Adjustment, AllowTwoPhase}
;
45 use rustc_middle
::ty
::error
::TypeError
::FieldMisMatch
;
46 use rustc_middle
::ty
::subst
::SubstsRef
;
47 use rustc_middle
::ty
::{self, AdtKind, DefIdTree, Ty, TypeFoldable}
;
48 use rustc_session
::parse
::feature_err
;
49 use rustc_span
::hygiene
::DesugaringKind
;
50 use rustc_span
::lev_distance
::find_best_match_for_name
;
51 use rustc_span
::source_map
::Span
;
52 use rustc_span
::symbol
::{kw, sym, Ident, Symbol}
;
53 use rustc_span
::{BytePos, Pos}
;
54 use rustc_target
::spec
::abi
::Abi
::RustIntrinsic
;
55 use rustc_trait_selection
::infer
::InferCtxtExt
;
56 use rustc_trait_selection
::traits
::{self, ObligationCauseCode}
;
58 impl<'a
, 'tcx
> FnCtxt
<'a
, 'tcx
> {
59 fn check_expr_eq_type(&self, expr
: &'tcx hir
::Expr
<'tcx
>, expected
: Ty
<'tcx
>) {
60 let ty
= self.check_expr_with_hint(expr
, expected
);
61 self.demand_eqtype(expr
.span
, expected
, ty
);
64 pub fn check_expr_has_type_or_error(
66 expr
: &'tcx hir
::Expr
<'tcx
>,
68 extend_err
: impl FnMut(&mut Diagnostic
),
70 self.check_expr_meets_expectation_or_error(expr
, ExpectHasType(expected
), extend_err
)
73 fn check_expr_meets_expectation_or_error(
75 expr
: &'tcx hir
::Expr
<'tcx
>,
76 expected
: Expectation
<'tcx
>,
77 mut extend_err
: impl FnMut(&mut Diagnostic
),
79 let expected_ty
= expected
.to_option(&self).unwrap_or(self.tcx
.types
.bool
);
80 let mut ty
= self.check_expr_with_expectation(expr
, expected
);
82 // While we don't allow *arbitrary* coercions here, we *do* allow
83 // coercions from ! to `expected`.
85 if let Some(adjustments
) = self.typeck_results
.borrow().adjustments().get(expr
.hir_id
) {
86 self.tcx().sess
.delay_span_bug(
88 "expression with never type wound up being adjusted",
90 return if let [Adjustment { kind: Adjust::NeverToAny, target }
] = &adjustments
[..] {
97 let adj_ty
= self.next_ty_var(TypeVariableOrigin
{
98 kind
: TypeVariableOriginKind
::AdjustmentType
,
101 self.apply_adjustments(
103 vec
![Adjustment { kind: Adjust::NeverToAny, target: adj_ty }
],
108 if let Some(mut err
) = self.demand_suptype_diag(expr
.span
, expected_ty
, ty
) {
109 let expr
= expr
.peel_drop_temps();
110 self.suggest_deref_ref_or_into(&mut err
, expr
, expected_ty
, ty
, None
);
111 extend_err(&mut err
);
117 pub(super) fn check_expr_coercable_to_type(
119 expr
: &'tcx hir
::Expr
<'tcx
>,
121 expected_ty_expr
: Option
<&'tcx hir
::Expr
<'tcx
>>,
123 let ty
= self.check_expr_with_hint(expr
, expected
);
124 // checks don't need two phase
125 self.demand_coerce(expr
, ty
, expected
, expected_ty_expr
, AllowTwoPhase
::No
)
128 pub(super) fn check_expr_with_hint(
130 expr
: &'tcx hir
::Expr
<'tcx
>,
133 self.check_expr_with_expectation(expr
, ExpectHasType(expected
))
136 fn check_expr_with_expectation_and_needs(
138 expr
: &'tcx hir
::Expr
<'tcx
>,
139 expected
: Expectation
<'tcx
>,
142 let ty
= self.check_expr_with_expectation(expr
, expected
);
144 // If the expression is used in a place whether mutable place is required
145 // e.g. LHS of assignment, perform the conversion.
146 if let Needs
::MutPlace
= needs
{
147 self.convert_place_derefs_to_mutable(expr
);
153 pub(super) fn check_expr(&self, expr
: &'tcx hir
::Expr
<'tcx
>) -> Ty
<'tcx
> {
154 self.check_expr_with_expectation(expr
, NoExpectation
)
157 pub(super) fn check_expr_with_needs(
159 expr
: &'tcx hir
::Expr
<'tcx
>,
162 self.check_expr_with_expectation_and_needs(expr
, NoExpectation
, needs
)
166 /// If an expression has any sub-expressions that result in a type error,
167 /// inspecting that expression's type with `ty.references_error()` will return
168 /// true. Likewise, if an expression is known to diverge, inspecting its
169 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
170 /// strict, _|_ can appear in the type of an expression that does not,
171 /// itself, diverge: for example, fn() -> _|_.)
172 /// Note that inspecting a type's structure *directly* may expose the fact
173 /// that there are actually multiple representations for `Error`, so avoid
174 /// that when err needs to be handled differently.
175 #[instrument(skip(self, expr), level = "debug")]
176 pub(super) fn check_expr_with_expectation(
178 expr
: &'tcx hir
::Expr
<'tcx
>,
179 expected
: Expectation
<'tcx
>,
181 self.check_expr_with_expectation_and_args(expr
, expected
, &[])
184 /// Same as `check_expr_with_expectation`, but allows us to pass in the arguments of a
185 /// `ExprKind::Call` when evaluating its callee when it is an `ExprKind::Path`.
186 pub(super) fn check_expr_with_expectation_and_args(
188 expr
: &'tcx hir
::Expr
<'tcx
>,
189 expected
: Expectation
<'tcx
>,
190 args
: &'tcx
[hir
::Expr
<'tcx
>],
192 if self.tcx().sess
.verbose() {
193 // make this code only run with -Zverbose because it is probably slow
194 if let Ok(lint_str
) = self.tcx
.sess
.source_map().span_to_snippet(expr
.span
) {
195 if !lint_str
.contains('
\n'
) {
196 debug
!("expr text: {lint_str}");
198 let mut lines
= lint_str
.lines();
199 if let Some(line0
) = lines
.next() {
200 let remaining_lines
= lines
.count();
201 debug
!("expr text: {line0}");
202 debug
!("expr text: ...(and {remaining_lines} more lines)");
208 // True if `expr` is a `Try::from_ok(())` that is a result of desugaring a try block
209 // without the final expr (e.g. `try { return; }`). We don't want to generate an
210 // unreachable_code lint for it since warnings for autogenerated code are confusing.
211 let is_try_block_generated_unit_expr
= match expr
.kind
{
212 ExprKind
::Call(_
, args
) if expr
.span
.is_desugaring(DesugaringKind
::TryBlock
) => {
213 args
.len() == 1 && args
[0].span
.is_desugaring(DesugaringKind
::TryBlock
)
219 // Warn for expressions after diverging siblings.
220 if !is_try_block_generated_unit_expr
{
221 self.warn_if_unreachable(expr
.hir_id
, expr
.span
, "expression");
224 // Hide the outer diverging and has_errors flags.
225 let old_diverges
= self.diverges
.replace(Diverges
::Maybe
);
226 let old_has_errors
= self.has_errors
.replace(false);
228 let ty
= ensure_sufficient_stack(|| match &expr
.kind
{
230 qpath @ hir
::QPath
::Resolved(..) | qpath @ hir
::QPath
::TypeRelative(..),
231 ) => self.check_expr_path(qpath
, expr
, args
),
232 _
=> self.check_expr_kind(expr
, expected
),
235 // Warn for non-block expressions with diverging children.
241 | ExprKind
::Match(..) => {}
242 // If `expr` is a result of desugaring the try block and is an ok-wrapped
243 // diverging expression (e.g. it arose from desugaring of `try { return }`),
244 // we skip issuing a warning because it is autogenerated code.
245 ExprKind
::Call(..) if expr
.span
.is_desugaring(DesugaringKind
::TryBlock
) => {}
246 ExprKind
::Call(callee
, _
) => self.warn_if_unreachable(expr
.hir_id
, callee
.span
, "call"),
247 ExprKind
::MethodCall(segment
, ..) => {
248 self.warn_if_unreachable(expr
.hir_id
, segment
.ident
.span
, "call")
250 _
=> self.warn_if_unreachable(expr
.hir_id
, expr
.span
, "expression"),
253 // Any expression that produces a value of type `!` must have diverged
255 self.diverges
.set(self.diverges
.get() | Diverges
::always(expr
.span
));
258 // Record the type, which applies it effects.
259 // We need to do this after the warning above, so that
260 // we don't warn for the diverging expression itself.
261 self.write_ty(expr
.hir_id
, ty
);
263 // Combine the diverging and has_error flags.
264 self.diverges
.set(self.diverges
.get() | old_diverges
);
265 self.has_errors
.set(self.has_errors
.get() | old_has_errors
);
267 debug
!("type of {} is...", self.tcx
.hir().node_to_string(expr
.hir_id
));
268 debug
!("... {:?}, expected is {:?}", ty
, expected
);
273 #[instrument(skip(self, expr), level = "debug")]
274 pub(super) fn check_expr_kind(
276 expr
: &'tcx hir
::Expr
<'tcx
>,
277 expected
: Expectation
<'tcx
>,
279 trace
!("expr={:#?}", expr
);
283 ExprKind
::Box(subexpr
) => self.check_expr_box(subexpr
, expected
),
284 ExprKind
::Lit(ref lit
) => self.check_lit(&lit
, expected
),
285 ExprKind
::Binary(op
, lhs
, rhs
) => self.check_binop(expr
, op
, lhs
, rhs
),
286 ExprKind
::Assign(lhs
, rhs
, span
) => {
287 self.check_expr_assign(expr
, expected
, lhs
, rhs
, span
)
289 ExprKind
::AssignOp(op
, lhs
, rhs
) => self.check_binop_assign(expr
, op
, lhs
, rhs
),
290 ExprKind
::Unary(unop
, oprnd
) => self.check_expr_unary(unop
, oprnd
, expected
, expr
),
291 ExprKind
::AddrOf(kind
, mutbl
, oprnd
) => {
292 self.check_expr_addr_of(kind
, mutbl
, oprnd
, expected
, expr
)
294 ExprKind
::Path(QPath
::LangItem(lang_item
, _
, hir_id
)) => {
295 self.check_lang_item_path(lang_item
, expr
, hir_id
)
297 ExprKind
::Path(ref qpath
) => self.check_expr_path(qpath
, expr
, &[]),
298 ExprKind
::InlineAsm(asm
) => {
299 // We defer some asm checks as we may not have resolved the input and output types yet (they may still be infer vars).
300 self.deferred_asm_checks
.borrow_mut().push((asm
, expr
.hir_id
));
301 self.check_expr_asm(asm
)
303 ExprKind
::Break(destination
, ref expr_opt
) => {
304 self.check_expr_break(destination
, expr_opt
.as_deref(), expr
)
306 ExprKind
::Continue(destination
) => {
307 if destination
.target_id
.is_ok() {
310 // There was an error; make type-check fail.
314 ExprKind
::Ret(ref expr_opt
) => self.check_expr_return(expr_opt
.as_deref(), expr
),
315 ExprKind
::Let(let_expr
) => self.check_expr_let(let_expr
),
316 ExprKind
::Loop(body
, _
, source
, _
) => {
317 self.check_expr_loop(body
, source
, expected
, expr
)
319 ExprKind
::Match(discrim
, arms
, match_src
) => {
320 self.check_match(expr
, &discrim
, arms
, expected
, match_src
)
322 ExprKind
::Closure { capture_clause, fn_decl, body, movability, .. }
=> {
323 self.check_expr_closure(expr
, capture_clause
, &fn_decl
, body
, movability
, expected
)
325 ExprKind
::Block(body
, _
) => self.check_block_with_expected(&body
, expected
),
326 ExprKind
::Call(callee
, args
) => self.check_call(expr
, &callee
, args
, expected
),
327 ExprKind
::MethodCall(segment
, args
, _
) => {
328 self.check_method_call(expr
, segment
, args
, expected
)
330 ExprKind
::Cast(e
, t
) => self.check_expr_cast(e
, t
, expr
),
331 ExprKind
::Type(e
, t
) => {
332 let ty
= self.to_ty_saving_user_provided_ty(&t
);
333 self.check_expr_eq_type(&e
, ty
);
336 ExprKind
::If(cond
, then_expr
, opt_else_expr
) => {
337 self.check_then_else(cond
, then_expr
, opt_else_expr
, expr
.span
, expected
)
339 ExprKind
::DropTemps(e
) => self.check_expr_with_expectation(e
, expected
),
340 ExprKind
::Array(args
) => self.check_expr_array(args
, expected
, expr
),
341 ExprKind
::ConstBlock(ref anon_const
) => {
342 self.check_expr_const_block(anon_const
, expected
, expr
)
344 ExprKind
::Repeat(element
, ref count
) => {
345 self.check_expr_repeat(element
, count
, expected
, expr
)
347 ExprKind
::Tup(elts
) => self.check_expr_tuple(elts
, expected
, expr
),
348 ExprKind
::Struct(qpath
, fields
, ref base_expr
) => {
349 self.check_expr_struct(expr
, expected
, qpath
, fields
, base_expr
)
351 ExprKind
::Field(base
, field
) => self.check_field(expr
, &base
, field
),
352 ExprKind
::Index(base
, idx
) => self.check_expr_index(base
, idx
, expr
),
353 ExprKind
::Yield(value
, ref src
) => self.check_expr_yield(value
, expr
, src
),
354 hir
::ExprKind
::Err
=> tcx
.ty_error(),
358 fn check_expr_box(&self, expr
: &'tcx hir
::Expr
<'tcx
>, expected
: Expectation
<'tcx
>) -> Ty
<'tcx
> {
359 let expected_inner
= expected
.to_option(self).map_or(NoExpectation
, |ty
| match ty
.kind() {
360 ty
::Adt(def
, _
) if def
.is_box() => Expectation
::rvalue_hint(self, ty
.boxed_ty()),
363 let referent_ty
= self.check_expr_with_expectation(expr
, expected_inner
);
364 self.require_type_is_sized(referent_ty
, expr
.span
, traits
::SizedBoxType
);
365 self.tcx
.mk_box(referent_ty
)
371 oprnd
: &'tcx hir
::Expr
<'tcx
>,
372 expected
: Expectation
<'tcx
>,
373 expr
: &'tcx hir
::Expr
<'tcx
>,
376 let expected_inner
= match unop
{
377 hir
::UnOp
::Not
| hir
::UnOp
::Neg
=> expected
,
378 hir
::UnOp
::Deref
=> NoExpectation
,
380 let mut oprnd_t
= self.check_expr_with_expectation(&oprnd
, expected_inner
);
382 if !oprnd_t
.references_error() {
383 oprnd_t
= self.structurally_resolved_type(expr
.span
, oprnd_t
);
385 hir
::UnOp
::Deref
=> {
386 if let Some(ty
) = self.lookup_derefing(expr
, oprnd
, oprnd_t
) {
389 let mut err
= type_error_struct
!(
394 "type `{oprnd_t}` cannot be dereferenced",
396 let sp
= tcx
.sess
.source_map().start_point(expr
.span
);
398 tcx
.sess
.parse_sess
.ambiguous_block_expr_parse
.borrow().get(&sp
)
400 tcx
.sess
.parse_sess
.expr_parentheses_needed(&mut err
, *sp
);
403 oprnd_t
= tcx
.ty_error();
407 let result
= self.check_user_unop(expr
, oprnd_t
, unop
);
408 // If it's builtin, we can reuse the type, this helps inference.
409 if !(oprnd_t
.is_integral() || *oprnd_t
.kind() == ty
::Bool
) {
414 let result
= self.check_user_unop(expr
, oprnd_t
, unop
);
415 // If it's builtin, we can reuse the type, this helps inference.
416 if !oprnd_t
.is_numeric() {
425 fn check_expr_addr_of(
427 kind
: hir
::BorrowKind
,
428 mutbl
: hir
::Mutability
,
429 oprnd
: &'tcx hir
::Expr
<'tcx
>,
430 expected
: Expectation
<'tcx
>,
431 expr
: &'tcx hir
::Expr
<'tcx
>,
433 let hint
= expected
.only_has_type(self).map_or(NoExpectation
, |ty
| {
435 ty
::Ref(_
, ty
, _
) | ty
::RawPtr(ty
::TypeAndMut { ty, .. }
) => {
436 if oprnd
.is_syntactic_place_expr() {
437 // Places may legitimately have unsized types.
438 // For example, dereferences of a fat pointer and
439 // the last field of a struct can be unsized.
442 Expectation
::rvalue_hint(self, *ty
)
449 self.check_expr_with_expectation_and_needs(&oprnd
, hint
, Needs
::maybe_mut_place(mutbl
));
451 let tm
= ty
::TypeAndMut { ty, mutbl }
;
453 _
if tm
.ty
.references_error() => self.tcx
.ty_error(),
454 hir
::BorrowKind
::Raw
=> {
455 self.check_named_place_expr(oprnd
);
458 hir
::BorrowKind
::Ref
=> {
459 // Note: at this point, we cannot say what the best lifetime
460 // is to use for resulting pointer. We want to use the
461 // shortest lifetime possible so as to avoid spurious borrowck
462 // errors. Moreover, the longest lifetime will depend on the
463 // precise details of the value whose address is being taken
464 // (and how long it is valid), which we don't know yet until
465 // type inference is complete.
467 // Therefore, here we simply generate a region variable. The
468 // region inferencer will then select a suitable value.
469 // Finally, borrowck will infer the value of the region again,
470 // this time with enough precision to check that the value
471 // whose address was taken can actually be made to live as long
472 // as it needs to live.
473 let region
= self.next_region_var(infer
::AddrOfRegion(expr
.span
));
474 self.tcx
.mk_ref(region
, tm
)
479 /// Does this expression refer to a place that either:
480 /// * Is based on a local or static.
481 /// * Contains a dereference
482 /// Note that the adjustments for the children of `expr` should already
483 /// have been resolved.
484 fn check_named_place_expr(&self, oprnd
: &'tcx hir
::Expr
<'tcx
>) {
485 let is_named
= oprnd
.is_place_expr(|base
| {
486 // Allow raw borrows if there are any deref adjustments.
488 // const VAL: (i32,) = (0,);
489 // const REF: &(i32,) = &(0,);
491 // &raw const VAL.0; // ERROR
492 // &raw const REF.0; // OK, same as &raw const (*REF).0;
494 // This is maybe too permissive, since it allows
495 // `let u = &raw const Box::new((1,)).0`, which creates an
496 // immediately dangling raw pointer.
501 .map_or(false, |x
| x
.iter().any(|adj
| matches
!(adj
.kind
, Adjust
::Deref(_
))))
504 self.tcx
.sess
.emit_err(AddressOfTemporaryTaken { span: oprnd.span }
);
508 fn check_lang_item_path(
510 lang_item
: hir
::LangItem
,
511 expr
: &'tcx hir
::Expr
<'tcx
>,
512 hir_id
: Option
<hir
::HirId
>,
514 self.resolve_lang_item_path(lang_item
, expr
.span
, expr
.hir_id
, hir_id
).1
517 pub(crate) fn check_expr_path(
519 qpath
: &'tcx hir
::QPath
<'tcx
>,
520 expr
: &'tcx hir
::Expr
<'tcx
>,
521 args
: &'tcx
[hir
::Expr
<'tcx
>],
524 let (res
, opt_ty
, segs
) =
525 self.resolve_ty_and_res_fully_qualified_call(qpath
, expr
.hir_id
, expr
.span
);
528 self.set_tainted_by_errors();
531 Res
::Def(DefKind
::Ctor(_
, CtorKind
::Fictive
), _
) => {
532 report_unexpected_variant_res(tcx
, res
, expr
.span
);
535 _
=> self.instantiate_value_path(segs
, opt_ty
, res
, expr
.span
, expr
.hir_id
).0,
538 if let ty
::FnDef(did
, ..) = *ty
.kind() {
539 let fn_sig
= ty
.fn_sig(tcx
);
540 if tcx
.fn_sig(did
).abi() == RustIntrinsic
&& tcx
.item_name(did
) == sym
::transmute
{
541 let from
= fn_sig
.inputs().skip_binder()[0];
542 let to
= fn_sig
.output().skip_binder();
543 // We defer the transmute to the end of typeck, once all inference vars have
544 // been resolved or we errored. This is important as we can only check transmute
545 // on concrete types, but the output type may not be known yet (it would only
546 // be known if explicitly specified via turbofish).
547 self.deferred_transmute_checks
.borrow_mut().push((from
, to
, expr
.span
));
549 if !tcx
.features().unsized_fn_params
{
550 // We want to remove some Sized bounds from std functions,
551 // but don't want to expose the removal to stable Rust.
552 // i.e., we don't want to allow
558 // to work in stable even if the Sized bound on `drop` is relaxed.
559 for i
in 0..fn_sig
.inputs().skip_binder().len() {
560 // We just want to check sizedness, so instead of introducing
561 // placeholder lifetimes with probing, we just replace higher lifetimes
563 let span
= args
.get(i
).map(|a
| a
.span
).unwrap_or(expr
.span
);
564 let input
= self.replace_bound_vars_with_fresh_vars(
566 infer
::LateBoundRegionConversionTime
::FnCall
,
569 self.require_type_is_sized_deferred(
572 traits
::SizedArgumentType(None
),
576 // Here we want to prevent struct constructors from returning unsized types.
577 // There were two cases this happened: fn pointer coercion in stable
578 // and usual function call in presence of unsized_locals.
579 // Also, as we just want to check sizedness, instead of introducing
580 // placeholder lifetimes with probing, we just replace higher lifetimes
582 let output
= self.replace_bound_vars_with_fresh_vars(
584 infer
::LateBoundRegionConversionTime
::FnCall
,
587 self.require_type_is_sized_deferred(output
, expr
.span
, traits
::SizedReturnType
);
590 // We always require that the type provided as the value for
591 // a type parameter outlives the moment of instantiation.
592 let substs
= self.typeck_results
.borrow().node_substs(expr
.hir_id
);
593 self.add_wf_bounds(substs
, expr
);
600 destination
: hir
::Destination
,
601 expr_opt
: Option
<&'tcx hir
::Expr
<'tcx
>>,
602 expr
: &'tcx hir
::Expr
<'tcx
>,
605 if let Ok(target_id
) = destination
.target_id
{
607 if let Some(e
) = expr_opt
{
608 // If this is a break with a value, we need to type-check
609 // the expression. Get an expected type from the loop context.
610 let opt_coerce_to
= {
611 // We should release `enclosing_breakables` before the `check_expr_with_hint`
612 // below, so can't move this block of code to the enclosing scope and share
613 // `ctxt` with the second `enclosing_breakables` borrow below.
614 let mut enclosing_breakables
= self.enclosing_breakables
.borrow_mut();
615 match enclosing_breakables
.opt_find_breakable(target_id
) {
616 Some(ctxt
) => ctxt
.coerce
.as_ref().map(|coerce
| coerce
.expected_ty()),
618 // Avoid ICE when `break` is inside a closure (#65383).
619 return tcx
.ty_error_with_message(
621 "break was outside loop, but no error was emitted",
627 // If the loop context is not a `loop { }`, then break with
628 // a value is illegal, and `opt_coerce_to` will be `None`.
629 // Just set expectation to error in that case.
630 let coerce_to
= opt_coerce_to
.unwrap_or_else(|| tcx
.ty_error());
632 // Recurse without `enclosing_breakables` borrowed.
633 e_ty
= self.check_expr_with_hint(e
, coerce_to
);
634 cause
= self.misc(e
.span
);
636 // Otherwise, this is a break *without* a value. That's
637 // always legal, and is equivalent to `break ()`.
638 e_ty
= tcx
.mk_unit();
639 cause
= self.misc(expr
.span
);
642 // Now that we have type-checked `expr_opt`, borrow
643 // the `enclosing_loops` field and let's coerce the
644 // type of `expr_opt` into what is expected.
645 let mut enclosing_breakables
= self.enclosing_breakables
.borrow_mut();
646 let Some(ctxt
) = enclosing_breakables
.opt_find_breakable(target_id
) else {
647 // Avoid ICE when `break` is inside a closure (#65383).
648 return tcx
.ty_error_with_message(
650 "break was outside loop, but no error was emitted",
654 if let Some(ref mut coerce
) = ctxt
.coerce
{
655 if let Some(ref e
) = expr_opt
{
656 coerce
.coerce(self, &cause
, e
, e_ty
);
658 assert
!(e_ty
.is_unit());
659 let ty
= coerce
.expected_ty();
660 coerce
.coerce_forced_unit(
664 self.suggest_mismatched_types_on_tail(
665 &mut err
, expr
, ty
, e_ty
, target_id
,
667 if let Some(val
) = ty_kind_suggestion(ty
) {
668 let label
= destination
670 .map(|l
| format
!(" {}", l
.ident
))
671 .unwrap_or_else(String
::new
);
674 "give it a value of the expected type",
675 format
!("break{label} {val}"),
676 Applicability
::HasPlaceholders
,
684 // If `ctxt.coerce` is `None`, we can just ignore
685 // the type of the expression. This is because
686 // either this was a break *without* a value, in
687 // which case it is always a legal type (`()`), or
688 // else an error would have been flagged by the
689 // `loops` pass for using break with an expression
690 // where you are not supposed to.
691 assert
!(expr_opt
.is_none() || self.tcx
.sess
.has_errors().is_some());
694 // If we encountered a `break`, then (no surprise) it may be possible to break from the
695 // loop... unless the value being returned from the loop diverges itself, e.g.
696 // `break return 5` or `break loop {}`.
697 ctxt
.may_break
|= !self.diverges
.get().is_always();
699 // the type of a `break` is always `!`, since it diverges
702 // Otherwise, we failed to find the enclosing loop;
703 // this can only happen if the `break` was not
704 // inside a loop at all, which is caught by the
705 // loop-checking pass.
706 let err
= self.tcx
.ty_error_with_message(
708 "break was outside loop, but no error was emitted",
711 // We still need to assign a type to the inner expression to
712 // prevent the ICE in #43162.
713 if let Some(e
) = expr_opt
{
714 self.check_expr_with_hint(e
, err
);
716 // ... except when we try to 'break rust;'.
717 // ICE this expression in particular (see #43162).
718 if let ExprKind
::Path(QPath
::Resolved(_
, path
)) = e
.kind
{
719 if path
.segments
.len() == 1 && path
.segments
[0].ident
.name
== sym
::rust
{
720 fatally_break_rust(self.tcx
.sess
);
725 // There was an error; make type-check fail.
730 fn check_expr_return(
732 expr_opt
: Option
<&'tcx hir
::Expr
<'tcx
>>,
733 expr
: &'tcx hir
::Expr
<'tcx
>,
735 if self.ret_coercion
.is_none() {
736 let mut err
= ReturnStmtOutsideOfFnBody
{
738 encl_body_span
: None
,
742 let encl_item_id
= self.tcx
.hir().get_parent_item(expr
.hir_id
);
744 if let Some(hir
::Node
::Item(hir
::Item
{
745 kind
: hir
::ItemKind
::Fn(..),
749 | Some(hir
::Node
::TraitItem(hir
::TraitItem
{
750 kind
: hir
::TraitItemKind
::Fn(_
, hir
::TraitFn
::Provided(_
)),
754 | Some(hir
::Node
::ImplItem(hir
::ImplItem
{
755 kind
: hir
::ImplItemKind
::Fn(..),
758 })) = self.tcx
.hir().find_by_def_id(encl_item_id
)
760 // We are inside a function body, so reporting "return statement
761 // outside of function body" needs an explanation.
763 let encl_body_owner_id
= self.tcx
.hir().enclosing_body_owner(expr
.hir_id
);
765 // If this didn't hold, we would not have to report an error in
767 assert_ne
!(hir
::HirId
::make_owner(encl_item_id
), encl_body_owner_id
);
769 let encl_body_id
= self.tcx
.hir().body_owned_by(encl_body_owner_id
);
770 let encl_body
= self.tcx
.hir().body(encl_body_id
);
772 err
.encl_body_span
= Some(encl_body
.value
.span
);
773 err
.encl_fn_span
= Some(*encl_fn_span
);
776 self.tcx
.sess
.emit_err(err
);
778 if let Some(e
) = expr_opt
{
779 // We still have to type-check `e` (issue #86188), but calling
780 // `check_return_expr` only works inside fn bodies.
783 } else if let Some(e
) = expr_opt
{
784 if self.ret_coercion_span
.get().is_none() {
785 self.ret_coercion_span
.set(Some(e
.span
));
787 self.check_return_expr(e
, true);
789 let mut coercion
= self.ret_coercion
.as_ref().unwrap().borrow_mut();
790 if self.ret_coercion_span
.get().is_none() {
791 self.ret_coercion_span
.set(Some(expr
.span
));
793 let cause
= self.cause(expr
.span
, ObligationCauseCode
::ReturnNoExpression
);
794 if let Some((fn_decl
, _
)) = self.get_fn_decl(expr
.hir_id
) {
795 coercion
.coerce_forced_unit(
799 let span
= fn_decl
.output
.span();
800 if let Ok(snippet
) = self.tcx
.sess
.source_map().span_to_snippet(span
) {
803 format
!("expected `{snippet}` because of this return type"),
810 coercion
.coerce_forced_unit(self, &cause
, &mut |_
| (), true);
816 /// `explicit_return` is `true` if we're checking an explicit `return expr`,
817 /// and `false` if we're checking a trailing expression.
818 pub(super) fn check_return_expr(
820 return_expr
: &'tcx hir
::Expr
<'tcx
>,
821 explicit_return
: bool
,
823 let ret_coercion
= self.ret_coercion
.as_ref().unwrap_or_else(|| {
824 span_bug
!(return_expr
.span
, "check_return_expr called outside fn body")
827 let ret_ty
= ret_coercion
.borrow().expected_ty();
828 let return_expr_ty
= self.check_expr_with_hint(return_expr
, ret_ty
);
829 let mut span
= return_expr
.span
;
830 // Use the span of the trailing expression for our cause,
831 // not the span of the entire function
832 if !explicit_return
{
833 if let ExprKind
::Block(body
, _
) = return_expr
.kind
&& let Some(last_expr
) = body
.expr
{
834 span
= last_expr
.span
;
837 ret_coercion
.borrow_mut().coerce(
839 &self.cause(span
, ObligationCauseCode
::ReturnValue(return_expr
.hir_id
)),
844 if self.return_type_has_opaque
{
845 // Point any obligations that were registered due to opaque type
846 // inference at the return expression.
847 self.select_obligations_where_possible(false, |errors
| {
848 self.point_at_return_for_opaque_ty_error(errors
, span
, return_expr_ty
);
853 fn point_at_return_for_opaque_ty_error(
855 errors
: &mut Vec
<traits
::FulfillmentError
<'tcx
>>,
857 return_expr_ty
: Ty
<'tcx
>,
859 // Don't point at the whole block if it's empty
860 if span
== self.tcx
.hir().span(self.body_id
) {
864 let cause
= &mut err
.obligation
.cause
;
865 if let ObligationCauseCode
::OpaqueReturnType(None
) = cause
.code() {
866 let new_cause
= ObligationCause
::new(
869 ObligationCauseCode
::OpaqueReturnType(Some((return_expr_ty
, span
))),
876 pub(crate) fn check_lhs_assignable(
878 lhs
: &'tcx hir
::Expr
<'tcx
>,
879 err_code
: &'
static str,
881 adjust_err
: impl FnOnce(&mut DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>),
883 if lhs
.is_syntactic_place_expr() {
887 // FIXME: Make this use SessionDiagnostic once error codes can be dynamically set.
888 let mut err
= self.tcx
.sess
.struct_span_err_with_code(
890 "invalid left-hand side of assignment",
891 DiagnosticId
::Error(err_code
.into()),
893 err
.span_label(lhs
.span
, "cannot assign to this expression");
895 self.comes_from_while_condition(lhs
.hir_id
, |expr
| {
896 err
.span_suggestion_verbose(
897 expr
.span
.shrink_to_lo(),
898 "you might have meant to use pattern destructuring",
900 Applicability
::MachineApplicable
,
904 adjust_err(&mut err
);
909 // Check if an expression `original_expr_id` comes from the condition of a while loop,
910 // as opposed from the body of a while loop, which we can naively check by iterating
911 // parents until we find a loop...
912 pub(super) fn comes_from_while_condition(
914 original_expr_id
: HirId
,
915 then
: impl FnOnce(&hir
::Expr
<'_
>),
917 let mut parent
= self.tcx
.hir().get_parent_node(original_expr_id
);
918 while let Some(node
) = self.tcx
.hir().find(parent
) {
920 hir
::Node
::Expr(hir
::Expr
{
927 hir
::ExprKind
::Match(expr
, ..) | hir
::ExprKind
::If(expr
, ..),
933 hir
::LoopSource
::While
,
938 // Check if our original expression is a child of the condition of a while loop
939 let expr_is_ancestor
= std
::iter
::successors(Some(original_expr_id
), |id
| {
940 self.tcx
.hir().find_parent_node(*id
)
942 .take_while(|id
| *id
!= parent
)
943 .any(|id
| id
== expr
.hir_id
);
944 // if it is, then we have a situation like `while Some(0) = value.get(0) {`,
945 // where `while let` was more likely intended.
946 if expr_is_ancestor
{
952 | hir
::Node
::ImplItem(_
)
953 | hir
::Node
::TraitItem(_
)
954 | hir
::Node
::Crate(_
) => break,
956 parent
= self.tcx
.hir().get_parent_node(parent
);
962 // A generic function for checking the 'then' and 'else' clauses in an 'if'
963 // or 'if-else' expression.
966 cond_expr
: &'tcx hir
::Expr
<'tcx
>,
967 then_expr
: &'tcx hir
::Expr
<'tcx
>,
968 opt_else_expr
: Option
<&'tcx hir
::Expr
<'tcx
>>,
970 orig_expected
: Expectation
<'tcx
>,
972 let cond_ty
= self.check_expr_has_type_or_error(cond_expr
, self.tcx
.types
.bool
, |_
| {}
);
974 self.warn_if_unreachable(
977 "block in `if` or `while` expression",
980 let cond_diverges
= self.diverges
.get();
981 self.diverges
.set(Diverges
::Maybe
);
983 let expected
= orig_expected
.adjust_for_branches(self);
984 let then_ty
= self.check_expr_with_expectation(then_expr
, expected
);
985 let then_diverges
= self.diverges
.get();
986 self.diverges
.set(Diverges
::Maybe
);
988 // We've already taken the expected type's preferences
989 // into account when typing the `then` branch. To figure
990 // out the initial shot at a LUB, we thus only consider
991 // `expected` if it represents a *hard* constraint
992 // (`only_has_type`); otherwise, we just go with a
993 // fresh type variable.
994 let coerce_to_ty
= expected
.coercion_target_type(self, sp
);
995 let mut coerce
: DynamicCoerceMany
<'_
> = CoerceMany
::new(coerce_to_ty
);
997 coerce
.coerce(self, &self.misc(sp
), then_expr
, then_ty
);
999 if let Some(else_expr
) = opt_else_expr
{
1000 let else_ty
= if sp
.desugaring_kind() == Some(DesugaringKind
::LetElse
) {
1001 // todo introduce `check_expr_with_expectation(.., Expectation::LetElse)`
1002 // for errors that point to the offending expression rather than the entire block.
1003 // We could use `check_expr_eq_type(.., tcx.types.never)`, but then there is no
1004 // way to detect that the expected type originated from let-else and provide
1005 // a customized error.
1006 let else_ty
= self.check_expr(else_expr
);
1007 let cause
= self.cause(else_expr
.span
, ObligationCauseCode
::LetElse
);
1009 if let Some(mut err
) =
1010 self.demand_eqtype_with_origin(&cause
, self.tcx
.types
.never
, else_ty
)
1018 self.check_expr_with_expectation(else_expr
, expected
)
1020 let else_diverges
= self.diverges
.get();
1022 let opt_suggest_box_span
= self.opt_suggest_box_span(else_ty
, orig_expected
);
1024 self.if_cause(sp
, then_expr
, else_expr
, then_ty
, else_ty
, opt_suggest_box_span
);
1026 coerce
.coerce(self, &if_cause
, else_expr
, else_ty
);
1028 // We won't diverge unless both branches do (or the condition does).
1029 self.diverges
.set(cond_diverges
| then_diverges
& else_diverges
);
1031 self.if_fallback_coercion(sp
, then_expr
, &mut coerce
);
1033 // If the condition is false we can't diverge.
1034 self.diverges
.set(cond_diverges
);
1037 let result_ty
= coerce
.complete(self);
1038 if cond_ty
.references_error() { self.tcx.ty_error() }
else { result_ty }
1041 /// Type check assignment expression `expr` of form `lhs = rhs`.
1042 /// The expected type is `()` and is passed to the function for the purposes of diagnostics.
1043 fn check_expr_assign(
1045 expr
: &'tcx hir
::Expr
<'tcx
>,
1046 expected
: Expectation
<'tcx
>,
1047 lhs
: &'tcx hir
::Expr
<'tcx
>,
1048 rhs
: &'tcx hir
::Expr
<'tcx
>,
1051 let expected_ty
= expected
.coercion_target_type(self, expr
.span
);
1052 if expected_ty
== self.tcx
.types
.bool
{
1053 // The expected type is `bool` but this will result in `()` so we can reasonably
1054 // say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.
1055 // The likely cause of this is `if foo = bar { .. }`.
1056 let actual_ty
= self.tcx
.mk_unit();
1057 let mut err
= self.demand_suptype_diag(expr
.span
, expected_ty
, actual_ty
).unwrap();
1058 let lhs_ty
= self.check_expr(&lhs
);
1059 let rhs_ty
= self.check_expr(&rhs
);
1060 let (applicability
, eq
) = if self.can_coerce(rhs_ty
, lhs_ty
) {
1061 (Applicability
::MachineApplicable
, true)
1063 (Applicability
::MaybeIncorrect
, false)
1065 if !lhs
.is_syntactic_place_expr()
1066 && lhs
.is_approximately_pattern()
1067 && !matches
!(lhs
.kind
, hir
::ExprKind
::Lit(_
))
1069 // Do not suggest `if let x = y` as `==` is way more likely to be the intention.
1070 let hir
= self.tcx
.hir();
1071 if let hir
::Node
::Expr(hir
::Expr { kind: ExprKind::If { .. }
, .. }) =
1072 hir
.get(hir
.get_parent_node(hir
.get_parent_node(expr
.hir_id
)))
1074 err
.span_suggestion_verbose(
1075 expr
.span
.shrink_to_lo(),
1076 "you might have meant to use pattern matching",
1083 err
.span_suggestion_verbose(
1085 "you might have meant to compare for equality",
1091 // If the assignment expression itself is ill-formed, don't
1092 // bother emitting another error
1093 if lhs_ty
.references_error() || rhs_ty
.references_error() {
1098 return self.tcx
.ty_error();
1101 let lhs_ty
= self.check_expr_with_needs(&lhs
, Needs
::MutPlace
);
1103 let suggest_deref_binop
= |err
: &mut DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>,
1105 if let Some(lhs_deref_ty
) = self.deref_once_mutably_for_diagnostic(lhs_ty
) {
1106 // Can only assign if the type is sized, so if `DerefMut` yields a type that is
1107 // unsized, do not suggest dereferencing it.
1108 let lhs_deref_ty_is_sized
= self
1110 .type_implements_trait(
1111 self.tcx
.lang_items().sized_trait().unwrap(),
1117 if lhs_deref_ty_is_sized
&& self.can_coerce(rhs_ty
, lhs_deref_ty
) {
1118 err
.span_suggestion_verbose(
1119 lhs
.span
.shrink_to_lo(),
1120 "consider dereferencing here to assign to the mutably borrowed value",
1122 Applicability
::MachineApplicable
,
1128 self.check_lhs_assignable(lhs
, "E0070", span
, |err
| {
1129 let rhs_ty
= self.check_expr(&rhs
);
1130 suggest_deref_binop(err
, rhs_ty
);
1133 // This is (basically) inlined `check_expr_coercable_to_type`, but we want
1134 // to suggest an additional fixup here in `suggest_deref_binop`.
1135 let rhs_ty
= self.check_expr_with_hint(&rhs
, lhs_ty
);
1136 if let (_
, Some(mut diag
)) =
1137 self.demand_coerce_diag(rhs
, rhs_ty
, lhs_ty
, Some(lhs
), AllowTwoPhase
::No
)
1139 suggest_deref_binop(&mut diag
, rhs_ty
);
1143 self.require_type_is_sized(lhs_ty
, lhs
.span
, traits
::AssignmentLhsSized
);
1145 if lhs_ty
.references_error() || rhs_ty
.references_error() {
1152 pub(super) fn check_expr_let(&self, let_expr
: &'tcx hir
::Let
<'tcx
>) -> Ty
<'tcx
> {
1153 // for let statements, this is done in check_stmt
1154 let init
= let_expr
.init
;
1155 self.warn_if_unreachable(init
.hir_id
, init
.span
, "block in `let` expression");
1156 // otherwise check exactly as a let statement
1157 self.check_decl(let_expr
.into());
1158 // but return a bool, for this is a boolean expression
1164 body
: &'tcx hir
::Block
<'tcx
>,
1165 source
: hir
::LoopSource
,
1166 expected
: Expectation
<'tcx
>,
1167 expr
: &'tcx hir
::Expr
<'tcx
>,
1169 let coerce
= match source
{
1170 // you can only use break with a value from a normal `loop { }`
1171 hir
::LoopSource
::Loop
=> {
1172 let coerce_to
= expected
.coercion_target_type(self, body
.span
);
1173 Some(CoerceMany
::new(coerce_to
))
1176 hir
::LoopSource
::While
| hir
::LoopSource
::ForLoop
=> None
,
1179 let ctxt
= BreakableCtxt
{
1181 may_break
: false, // Will get updated if/when we find a `break`.
1184 let (ctxt
, ()) = self.with_breakable_ctxt(expr
.hir_id
, ctxt
, || {
1185 self.check_block_no_value(&body
);
1189 // No way to know whether it's diverging because
1190 // of a `break` or an outer `break` or `return`.
1191 self.diverges
.set(Diverges
::Maybe
);
1194 // If we permit break with a value, then result type is
1195 // the LUB of the breaks (possibly ! if none); else, it
1196 // is nil. This makes sense because infinite loops
1197 // (which would have type !) are only possible iff we
1198 // permit break with a value [1].
1199 if ctxt
.coerce
.is_none() && !ctxt
.may_break
{
1201 self.tcx
.sess
.delay_span_bug(body
.span
, "no coercion, but loop may not break");
1203 ctxt
.coerce
.map(|c
| c
.complete(self)).unwrap_or_else(|| self.tcx
.mk_unit())
1206 /// Checks a method call.
1207 fn check_method_call(
1209 expr
: &'tcx hir
::Expr
<'tcx
>,
1210 segment
: &hir
::PathSegment
<'_
>,
1211 args
: &'tcx
[hir
::Expr
<'tcx
>],
1212 expected
: Expectation
<'tcx
>,
1214 let rcvr
= &args
[0];
1215 let rcvr_t
= self.check_expr(&rcvr
);
1216 // no need to check for bot/err -- callee does that
1217 let rcvr_t
= self.structurally_resolved_type(args
[0].span
, rcvr_t
);
1218 let span
= segment
.ident
.span
;
1220 let method
= match self.lookup_method(rcvr_t
, segment
, span
, expr
, rcvr
, args
) {
1222 // We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to
1223 // trigger this codepath causing `structurally_resolved_type` to emit an error.
1225 self.write_method_call(expr
.hir_id
, method
);
1229 if segment
.ident
.name
!= kw
::Empty
{
1230 if let Some(mut err
) = self.report_method_error(
1234 SelfSource
::MethodCall(&args
[0]),
1245 // Call the generic checker.
1246 self.check_method_argument_types(
1258 e
: &'tcx hir
::Expr
<'tcx
>,
1259 t
: &'tcx hir
::Ty
<'tcx
>,
1260 expr
: &'tcx hir
::Expr
<'tcx
>,
1262 // Find the type of `e`. Supply hints based on the type we are casting to,
1264 let t_cast
= self.to_ty_saving_user_provided_ty(t
);
1265 let t_cast
= self.resolve_vars_if_possible(t_cast
);
1266 let t_expr
= self.check_expr_with_expectation(e
, ExpectCastableToType(t_cast
));
1267 let t_expr
= self.resolve_vars_if_possible(t_expr
);
1269 // Eagerly check for some obvious errors.
1270 if t_expr
.references_error() || t_cast
.references_error() {
1273 // Defer other checks until we're done type checking.
1274 let mut deferred_cast_checks
= self.deferred_cast_checks
.borrow_mut();
1275 match cast
::CastCheck
::new(self, e
, t_expr
, t_cast
, t
.span
, expr
.span
) {
1278 "check_expr_cast: deferring cast from {:?} to {:?}: {:?}",
1279 t_cast
, t_expr
, cast_check
,
1281 deferred_cast_checks
.push(cast_check
);
1284 Err(_
) => self.tcx
.ty_error(),
1289 fn check_expr_array(
1291 args
: &'tcx
[hir
::Expr
<'tcx
>],
1292 expected
: Expectation
<'tcx
>,
1293 expr
: &'tcx hir
::Expr
<'tcx
>,
1295 let element_ty
= if !args
.is_empty() {
1296 let coerce_to
= expected
1298 .and_then(|uty
| match *uty
.kind() {
1299 ty
::Array(ty
, _
) | ty
::Slice(ty
) => Some(ty
),
1302 .unwrap_or_else(|| {
1303 self.next_ty_var(TypeVariableOrigin
{
1304 kind
: TypeVariableOriginKind
::TypeInference
,
1308 let mut coerce
= CoerceMany
::with_coercion_sites(coerce_to
, args
);
1309 assert_eq
!(self.diverges
.get(), Diverges
::Maybe
);
1311 let e_ty
= self.check_expr_with_hint(e
, coerce_to
);
1312 let cause
= self.misc(e
.span
);
1313 coerce
.coerce(self, &cause
, e
, e_ty
);
1315 coerce
.complete(self)
1317 self.next_ty_var(TypeVariableOrigin
{
1318 kind
: TypeVariableOriginKind
::TypeInference
,
1322 self.tcx
.mk_array(element_ty
, args
.len() as u64)
1325 fn check_expr_const_block(
1327 anon_const
: &'tcx hir
::AnonConst
,
1328 expected
: Expectation
<'tcx
>,
1329 _expr
: &'tcx hir
::Expr
<'tcx
>,
1331 let body
= self.tcx
.hir().body(anon_const
.body
);
1333 // Create a new function context.
1334 let fcx
= FnCtxt
::new(self, self.param_env
.with_const(), body
.value
.hir_id
);
1335 crate::check
::GatherLocalsVisitor
::new(&fcx
).visit_body(body
);
1337 let ty
= fcx
.check_expr_with_expectation(&body
.value
, expected
);
1338 fcx
.require_type_is_sized(ty
, body
.value
.span
, traits
::ConstSized
);
1339 fcx
.write_ty(anon_const
.hir_id
, ty
);
1343 fn check_expr_repeat(
1345 element
: &'tcx hir
::Expr
<'tcx
>,
1346 count
: &'tcx hir
::ArrayLen
,
1347 expected
: Expectation
<'tcx
>,
1348 _expr
: &'tcx hir
::Expr
<'tcx
>,
1351 let count
= self.array_length_to_const(count
);
1353 let uty
= match expected
{
1354 ExpectHasType(uty
) => match *uty
.kind() {
1355 ty
::Array(ty
, _
) | ty
::Slice(ty
) => Some(ty
),
1361 let (element_ty
, t
) = match uty
{
1363 self.check_expr_coercable_to_type(&element
, uty
, None
);
1367 let ty
= self.next_ty_var(TypeVariableOrigin
{
1368 kind
: TypeVariableOriginKind
::MiscVariable
,
1371 let element_ty
= self.check_expr_has_type_or_error(&element
, ty
, |_
| {}
);
1376 if element_ty
.references_error() {
1377 return tcx
.ty_error();
1380 self.check_repeat_element_needs_copy_bound(element
, count
, element_ty
);
1382 tcx
.mk_ty(ty
::Array(t
, count
))
1385 fn check_repeat_element_needs_copy_bound(
1387 element
: &hir
::Expr
<'_
>,
1388 count
: ty
::Const
<'tcx
>,
1389 element_ty
: Ty
<'tcx
>,
1392 // Actual constants as the repeat element get inserted repeatedly instead of getting copied via Copy.
1393 match &element
.kind
{
1394 hir
::ExprKind
::ConstBlock(..) => return,
1395 hir
::ExprKind
::Path(qpath
) => {
1396 let res
= self.typeck_results
.borrow().qpath_res(qpath
, element
.hir_id
);
1397 if let Res
::Def(DefKind
::Const
| DefKind
::AssocConst
| DefKind
::AnonConst
, _
) = res
1404 // If someone calls a const fn, they can extract that call out into a separate constant (or a const
1405 // block in the future), so we check that to tell them that in the diagnostic. Does not affect typeck.
1406 let is_const_fn
= match element
.kind
{
1407 hir
::ExprKind
::Call(func
, _args
) => match *self.node_ty(func
.hir_id
).kind() {
1408 ty
::FnDef(def_id
, _
) => tcx
.is_const_fn(def_id
),
1414 // If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
1415 // don't copy that one element, we move it. Only check for Copy if the length is larger.
1416 if count
.try_eval_usize(tcx
, self.param_env
).map_or(true, |len
| len
> 1) {
1417 let lang_item
= self.tcx
.require_lang_item(LangItem
::Copy
, None
);
1418 let code
= traits
::ObligationCauseCode
::RepeatElementCopy { is_const_fn }
;
1419 self.require_type_meets(element_ty
, element
.span
, code
, lang_item
);
1423 fn check_expr_tuple(
1425 elts
: &'tcx
[hir
::Expr
<'tcx
>],
1426 expected
: Expectation
<'tcx
>,
1427 expr
: &'tcx hir
::Expr
<'tcx
>,
1429 let flds
= expected
.only_has_type(self).and_then(|ty
| {
1430 let ty
= self.resolve_vars_with_obligations(ty
);
1432 ty
::Tuple(flds
) => Some(&flds
[..]),
1437 let elt_ts_iter
= elts
.iter().enumerate().map(|(i
, e
)| match flds
{
1438 Some(fs
) if i
< fs
.len() => {
1440 self.check_expr_coercable_to_type(&e
, ety
, None
);
1443 _
=> self.check_expr_with_expectation(&e
, NoExpectation
),
1445 let tuple
= self.tcx
.mk_tup(elt_ts_iter
);
1446 if tuple
.references_error() {
1449 self.require_type_is_sized(tuple
, expr
.span
, traits
::TupleInitializerSized
);
1454 fn check_expr_struct(
1456 expr
: &hir
::Expr
<'_
>,
1457 expected
: Expectation
<'tcx
>,
1459 fields
: &'tcx
[hir
::ExprField
<'tcx
>],
1460 base_expr
: &'tcx Option
<&'tcx hir
::Expr
<'tcx
>>,
1462 // Find the relevant variant
1463 let Some((variant
, adt_ty
)) = self.check_struct_path(qpath
, expr
.hir_id
) else {
1464 self.check_struct_fields_on_error(fields
, base_expr
);
1465 return self.tcx
.ty_error();
1468 // Prohibit struct expressions when non-exhaustive flag is set.
1469 let adt
= adt_ty
.ty_adt_def().expect("`check_struct_path` returned non-ADT type");
1470 if !adt
.did().is_local() && variant
.is_field_list_non_exhaustive() {
1473 .emit_err(StructExprNonExhaustive { span: expr.span, what: adt.variant_descr() }
);
1476 self.check_expr_struct_fields(
1487 self.require_type_is_sized(adt_ty
, expr
.span
, traits
::StructInitializerSized
);
1491 fn check_expr_struct_fields(
1494 expected
: Expectation
<'tcx
>,
1495 expr_id
: hir
::HirId
,
1497 variant
: &'tcx ty
::VariantDef
,
1498 ast_fields
: &'tcx
[hir
::ExprField
<'tcx
>],
1499 base_expr
: &'tcx Option
<&'tcx hir
::Expr
<'tcx
>>,
1504 let expected_inputs
=
1505 self.expected_inputs_for_expected_output(span
, expected
, adt_ty
, &[adt_ty
]);
1506 let adt_ty_hint
= if let Some(expected_inputs
) = expected_inputs
{
1507 expected_inputs
.get(0).cloned().unwrap_or(adt_ty
)
1511 // re-link the regions that EIfEO can erase.
1512 self.demand_eqtype(span
, adt_ty_hint
, adt_ty
);
1514 let ty
::Adt(adt
, substs
) = adt_ty
.kind() else {
1515 span_bug
!(span
, "non-ADT passed to check_expr_struct_fields");
1517 let adt_kind
= adt
.adt_kind();
1519 let mut remaining_fields
= variant
1523 .map(|(i
, field
)| (field
.ident(tcx
).normalize_to_macros_2_0(), (i
, field
)))
1524 .collect
::<FxHashMap
<_
, _
>>();
1526 let mut seen_fields
= FxHashMap
::default();
1528 let mut error_happened
= false;
1530 // Type-check each field.
1531 for field
in ast_fields
{
1532 let ident
= tcx
.adjust_ident(field
.ident
, variant
.def_id
);
1533 let field_type
= if let Some((i
, v_field
)) = remaining_fields
.remove(&ident
) {
1534 seen_fields
.insert(ident
, field
.span
);
1535 self.write_field_index(field
.hir_id
, i
);
1537 // We don't look at stability attributes on
1538 // struct-like enums (yet...), but it's definitely not
1539 // a bug to have constructed one.
1540 if adt_kind
!= AdtKind
::Enum
{
1541 tcx
.check_stability(v_field
.did
, Some(expr_id
), field
.span
, None
);
1544 self.field_ty(field
.span
, v_field
, substs
)
1546 error_happened
= true;
1547 if let Some(prev_span
) = seen_fields
.get(&ident
) {
1548 tcx
.sess
.emit_err(FieldMultiplySpecifiedInInitializer
{
1549 span
: field
.ident
.span
,
1550 prev_span
: *prev_span
,
1554 self.report_unknown_field(
1559 adt
.variant_descr(),
1567 // Make sure to give a type to the field even if there's
1568 // an error, so we can continue type-checking.
1569 self.check_expr_coercable_to_type(&field
.expr
, field_type
, None
);
1572 // Make sure the programmer specified correct number of fields.
1573 if adt_kind
== AdtKind
::Union
{
1574 if ast_fields
.len() != 1 {
1579 "union expressions should have exactly one field",
1585 // If check_expr_struct_fields hit an error, do not attempt to populate
1586 // the fields with the base_expr. This could cause us to hit errors later
1587 // when certain fields are assumed to exist that in fact do not.
1592 if let Some(base_expr
) = base_expr
{
1593 // FIXME: We are currently creating two branches here in order to maintain
1594 // consistency. But they should be merged as much as possible.
1595 let fru_tys
= if self.tcx
.features().type_changing_struct_update
{
1596 if adt
.is_struct() {
1597 // Make some fresh substitutions for our ADT type.
1598 let fresh_substs
= self.fresh_substs_for_item(base_expr
.span
, adt
.did());
1599 // We do subtyping on the FRU fields first, so we can
1600 // learn exactly what types we expect the base expr
1601 // needs constrained to be compatible with the struct
1602 // type we expect from the expectation value.
1603 let fru_tys
= variant
1607 let fru_ty
= self.normalize_associated_types_in(
1609 self.field_ty(base_expr
.span
, f
, fresh_substs
),
1611 let ident
= self.tcx
.adjust_ident(f
.ident(self.tcx
), variant
.def_id
);
1612 if let Some(_
) = remaining_fields
.remove(&ident
) {
1613 let target_ty
= self.field_ty(base_expr
.span
, f
, substs
);
1614 let cause
= self.misc(base_expr
.span
);
1615 match self.at(&cause
, self.param_env
).sup(target_ty
, fru_ty
) {
1616 Ok(InferOk { obligations, value: () }
) => {
1617 self.register_predicates(obligations
)
1620 // This should never happen, since we're just subtyping the
1621 // remaining_fields, but it's fine to emit this, I guess.
1622 self.report_mismatched_types(
1626 FieldMisMatch(variant
.name
, ident
.name
),
1632 self.resolve_vars_if_possible(fru_ty
)
1635 // The use of fresh substs that we have subtyped against
1636 // our base ADT type's fields allows us to guide inference
1637 // along so that, e.g.
1639 // MyStruct<'a, F1, F2, const C: usize> {
1641 // // Other fields that reference `'a`, `F2`, and `C`
1644 // let x = MyStruct {
1649 // will have the `other_struct` expression constrained to
1650 // `MyStruct<'a, _, F2, C>`, as opposed to just `_`...
1651 // This is important to allow coercions to happen in
1652 // `other_struct` itself. See `coerce-in-base-expr.rs`.
1653 let fresh_base_ty
= self.tcx
.mk_adt(*adt
, fresh_substs
);
1654 self.check_expr_has_type_or_error(
1656 self.resolve_vars_if_possible(fresh_base_ty
),
1661 // Check the base_expr, regardless of a bad expected adt_ty, so we can get
1662 // type errors on that expression, too.
1663 self.check_expr(base_expr
);
1666 .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span }
);
1670 self.check_expr_has_type_or_error(base_expr
, adt_ty
, |_
| {
1671 let base_ty
= self.typeck_results
.borrow().expr_ty(*base_expr
);
1672 let same_adt
= match (adt_ty
.kind(), base_ty
.kind()) {
1673 (ty
::Adt(adt
, _
), ty
::Adt(base_adt
, _
)) if adt
== base_adt
=> true,
1676 if self.tcx
.sess
.is_nightly_build() && same_adt
{
1678 &self.tcx
.sess
.parse_sess
,
1679 sym
::type_changing_struct_update
,
1681 "type changing struct updating is experimental",
1686 match adt_ty
.kind() {
1687 ty
::Adt(adt
, substs
) if adt
.is_struct() => variant
1691 self.normalize_associated_types_in(expr_span
, f
.ty(self.tcx
, substs
))
1697 .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span }
);
1702 self.typeck_results
.borrow_mut().fru_field_types_mut().insert(expr_id
, fru_tys
);
1703 } else if adt_kind
!= AdtKind
::Union
&& !remaining_fields
.is_empty() {
1704 debug
!(?remaining_fields
);
1705 let private_fields
: Vec
<&ty
::FieldDef
> = variant
1709 !field
.vis
.is_accessible_from(tcx
.parent_module(expr_id
).to_def_id(), tcx
)
1713 if !private_fields
.is_empty() {
1714 self.report_private_fields(adt_ty
, span
, private_fields
, ast_fields
);
1716 self.report_missing_fields(
1728 fn check_struct_fields_on_error(
1730 fields
: &'tcx
[hir
::ExprField
<'tcx
>],
1731 base_expr
: &'tcx Option
<&'tcx hir
::Expr
<'tcx
>>,
1733 for field
in fields
{
1734 self.check_expr(&field
.expr
);
1736 if let Some(base
) = *base_expr
{
1737 self.check_expr(&base
);
1741 /// Report an error for a struct field expression when there are fields which aren't provided.
1744 /// error: missing field `you_can_use_this_field` in initializer of `foo::Foo`
1745 /// --> src/main.rs:8:5
1747 /// 8 | foo::Foo {};
1748 /// | ^^^^^^^^ missing `you_can_use_this_field`
1750 /// error: aborting due to previous error
1752 fn report_missing_fields(
1756 remaining_fields
: FxHashMap
<Ident
, (usize, &ty
::FieldDef
)>,
1757 variant
: &'tcx ty
::VariantDef
,
1758 ast_fields
: &'tcx
[hir
::ExprField
<'tcx
>],
1759 substs
: SubstsRef
<'tcx
>,
1761 let len
= remaining_fields
.len();
1763 let mut displayable_field_names
: Vec
<&str> =
1764 remaining_fields
.keys().map(|ident
| ident
.as_str()).collect();
1765 // sorting &str primitives here, sort_unstable is ok
1766 displayable_field_names
.sort_unstable();
1768 let mut truncated_fields_error
= String
::new();
1769 let remaining_fields_names
= match &displayable_field_names
[..] {
1770 [field1
] => format
!("`{}`", field1
),
1771 [field1
, field2
] => format
!("`{field1}` and `{field2}`"),
1772 [field1
, field2
, field3
] => format
!("`{field1}`, `{field2}` and `{field3}`"),
1774 truncated_fields_error
=
1775 format
!(" and {} other field{}", len
- 3, pluralize
!(len
- 3));
1776 displayable_field_names
1779 .map(|n
| format
!("`{n}`"))
1780 .collect
::<Vec
<_
>>()
1785 let mut err
= struct_span_err
!(
1789 "missing field{} {}{} in initializer of `{}`",
1791 remaining_fields_names
,
1792 truncated_fields_error
,
1795 err
.span_label(span
, format
!("missing {remaining_fields_names}{truncated_fields_error}"));
1797 // If the last field is a range literal, but it isn't supposed to be, then they probably
1798 // meant to use functional update syntax.
1800 // I don't use 'is_range_literal' because only double-sided, half-open ranges count.
1804 QPath
::LangItem(LangItem
::Range
, ..),
1805 &[ref range_start
, ref range_end
],
1808 )) = ast_fields
.last().map(|last
| (last
, &last
.expr
.kind
)) &&
1810 variant
.fields
.iter().find(|field
| field
.ident(self.tcx
) == last
.ident
) &&
1811 let range_def_id
= self.tcx
.lang_items().range_struct() &&
1813 .and_then(|field
| field
.ty(self.tcx
, substs
).ty_adt_def())
1814 .map(|adt
| adt
.did())
1821 .span_to_snippet(range_end
.expr
.span
)
1822 .map(|s
| format
!(" from `{s}`"))
1823 .unwrap_or(String
::new());
1824 err
.span_suggestion(
1825 range_start
.span
.shrink_to_hi(),
1826 &format
!("to set the remaining fields{instead}, separate the last named field with a comma"),
1828 Applicability
::MaybeIncorrect
,
1835 /// Report an error for a struct field expression when there are invisible fields.
1838 /// error: cannot construct `Foo` with struct literal syntax due to private fields
1839 /// --> src/main.rs:8:5
1841 /// 8 | foo::Foo {};
1844 /// error: aborting due to previous error
1846 fn report_private_fields(
1850 private_fields
: Vec
<&ty
::FieldDef
>,
1851 used_fields
: &'tcx
[hir
::ExprField
<'tcx
>],
1853 let mut err
= self.tcx
.sess
.struct_span_err(
1856 "cannot construct `{adt_ty}` with struct literal syntax due to private fields",
1859 let (used_private_fields
, remaining_private_fields
): (
1860 Vec
<(Symbol
, Span
, bool
)>,
1861 Vec
<(Symbol
, Span
, bool
)>,
1865 match used_fields
.iter().find(|used_field
| field
.name
== used_field
.ident
.name
) {
1866 Some(used_field
) => (field
.name
, used_field
.span
, true),
1867 None
=> (field
.name
, self.tcx
.def_span(field
.did
), false),
1870 .partition(|field
| field
.2);
1871 err
.span_labels(used_private_fields
.iter().map(|(_
, span
, _
)| *span
), "private field");
1872 if !remaining_private_fields
.is_empty() {
1873 let remaining_private_fields_len
= remaining_private_fields
.len();
1874 let names
= match &remaining_private_fields
1876 .map(|(name
, _
, _
)| name
.to_string())
1877 .collect
::<Vec
<_
>>()[..]
1879 _
if remaining_private_fields_len
> 6 => String
::new(),
1880 [name
] => format
!("`{name}` "),
1881 [names @
.., last
] => {
1882 let names
= names
.iter().map(|name
| format
!("`{name}`")).collect
::<Vec
<_
>>();
1883 format
!("{} and `{last}` ", names
.join(", "))
1885 [] => unreachable
!(),
1888 "... and other private field{s} {names}that {were} not provided",
1889 s
= pluralize
!(remaining_private_fields_len
),
1890 were
= pluralize
!("was", remaining_private_fields_len
),
1896 fn report_unknown_field(
1899 variant
: &'tcx ty
::VariantDef
,
1900 field
: &hir
::ExprField
<'_
>,
1901 skip_fields
: &[hir
::ExprField
<'_
>],
1905 if variant
.is_recovered() {
1906 self.set_tainted_by_errors();
1909 let mut err
= self.type_error_struct_with_diag(
1911 |actual
| match ty
.kind() {
1912 ty
::Adt(adt
, ..) if adt
.is_enum() => struct_span_err
!(
1916 "{} `{}::{}` has no field named `{}`",
1922 _
=> struct_span_err
!(
1926 "{} `{}` has no field named `{}`",
1935 let variant_ident_span
= self.tcx
.def_ident_span(variant
.def_id
).unwrap();
1936 match variant
.ctor_kind
{
1937 CtorKind
::Fn
=> match ty
.kind() {
1938 ty
::Adt(adt
, ..) if adt
.is_enum() => {
1942 "`{adt}::{variant}` defined here",
1944 variant
= variant
.name
,
1947 err
.span_label(field
.ident
.span
, "field does not exist");
1948 err
.span_suggestion_verbose(
1951 "`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax",
1953 variant
= variant
.name
,
1956 "{adt}::{variant}(/* fields */)",
1958 variant
= variant
.name
,
1960 Applicability
::HasPlaceholders
,
1964 err
.span_label(variant_ident_span
, format
!("`{adt}` defined here", adt
= ty
));
1965 err
.span_label(field
.ident
.span
, "field does not exist");
1966 err
.span_suggestion_verbose(
1969 "`{adt}` is a tuple {kind_name}, use the appropriate syntax",
1971 kind_name
= kind_name
,
1973 format
!("{adt}(/* fields */)", adt
= ty
),
1974 Applicability
::HasPlaceholders
,
1979 // prevent all specified fields from being suggested
1980 let skip_fields
= skip_fields
.iter().map(|x
| x
.ident
.name
);
1981 if let Some(field_name
) = self.suggest_field_name(
1984 skip_fields
.collect(),
1987 err
.span_suggestion(
1989 "a field with a similar name exists",
1991 Applicability
::MaybeIncorrect
,
1995 ty
::Adt(adt
, ..) => {
1999 format
!("`{}::{}` does not have this field", ty
, variant
.name
),
2004 format
!("`{ty}` does not have this field"),
2007 let available_field_names
=
2008 self.available_field_names(variant
, expr_span
);
2009 if !available_field_names
.is_empty() {
2011 "available fields are: {}",
2012 self.name_series_display(available_field_names
)
2016 _
=> bug
!("non-ADT passed to report_unknown_field"),
2024 // Return a hint about the closest match in field names
2025 fn suggest_field_name(
2027 variant
: &'tcx ty
::VariantDef
,
2030 // The span where stability will be checked
2032 ) -> Option
<Symbol
> {
2036 .filter_map(|field
| {
2037 // ignore already set fields and private fields from non-local crates
2038 // and unstable fields.
2039 if skip
.iter().any(|&x
| x
== field
.name
)
2040 || (!variant
.def_id
.is_local() && !field
.vis
.is_public())
2042 self.tcx
.eval_stability(field
.did
, None
, span
, None
),
2043 stability
::EvalResult
::Deny { .. }
2051 .collect
::<Vec
<Symbol
>>();
2053 find_best_match_for_name(&names
, field
, None
)
2056 fn available_field_names(
2058 variant
: &'tcx ty
::VariantDef
,
2065 let def_scope
= self
2067 .adjust_ident_and_get_scope(field
.ident(self.tcx
), variant
.def_id
, self.body_id
)
2069 field
.vis
.is_accessible_from(def_scope
, self.tcx
)
2071 self.tcx
.eval_stability(field
.did
, None
, access_span
, None
),
2072 stability
::EvalResult
::Deny { .. }
2075 .filter(|field
| !self.tcx
.is_doc_hidden(field
.did
))
2076 .map(|field
| field
.name
)
2080 fn name_series_display(&self, names
: Vec
<Symbol
>) -> String
{
2081 // dynamic limit, to never omit just one field
2082 let limit
= if names
.len() == 6 { 6 }
else { 5 }
;
2084 names
.iter().take(limit
).map(|n
| format
!("`{}`", n
)).collect
::<Vec
<_
>>().join(", ");
2085 if names
.len() > limit
{
2086 display
= format
!("{} ... and {} others", display
, names
.len() - limit
);
2091 // Check field access expressions
2094 expr
: &'tcx hir
::Expr
<'tcx
>,
2095 base
: &'tcx hir
::Expr
<'tcx
>,
2098 debug
!("check_field(expr: {:?}, base: {:?}, field: {:?})", expr
, base
, field
);
2099 let expr_t
= self.check_expr(base
);
2100 let expr_t
= self.structurally_resolved_type(base
.span
, expr_t
);
2101 let mut private_candidate
= None
;
2102 let mut autoderef
= self.autoderef(expr
.span
, expr_t
);
2103 while let Some((base_t
, _
)) = autoderef
.next() {
2104 debug
!("base_t: {:?}", base_t
);
2105 match base_t
.kind() {
2106 ty
::Adt(base_def
, substs
) if !base_def
.is_enum() => {
2107 debug
!("struct named {:?}", base_t
);
2108 let (ident
, def_scope
) =
2109 self.tcx
.adjust_ident_and_get_scope(field
, base_def
.did(), self.body_id
);
2110 let fields
= &base_def
.non_enum_variant().fields
;
2111 if let Some(index
) = fields
2113 .position(|f
| f
.ident(self.tcx
).normalize_to_macros_2_0() == ident
)
2115 let field
= &fields
[index
];
2116 let field_ty
= self.field_ty(expr
.span
, field
, substs
);
2117 // Save the index of all fields regardless of their visibility in case
2118 // of error recovery.
2119 self.write_field_index(expr
.hir_id
, index
);
2120 let adjustments
= self.adjust_steps(&autoderef
);
2121 if field
.vis
.is_accessible_from(def_scope
, self.tcx
) {
2122 self.apply_adjustments(base
, adjustments
);
2123 self.register_predicates(autoderef
.into_obligations());
2125 self.tcx
.check_stability(field
.did
, Some(expr
.hir_id
), expr
.span
, None
);
2128 private_candidate
= Some((adjustments
, base_def
.did(), field_ty
));
2132 let fstr
= field
.as_str();
2133 if let Ok(index
) = fstr
.parse
::<usize>() {
2134 if fstr
== index
.to_string() {
2135 if let Some(&field_ty
) = tys
.get(index
) {
2136 let adjustments
= self.adjust_steps(&autoderef
);
2137 self.apply_adjustments(base
, adjustments
);
2138 self.register_predicates(autoderef
.into_obligations());
2140 self.write_field_index(expr
.hir_id
, index
);
2149 self.structurally_resolved_type(autoderef
.span(), autoderef
.final_ty(false));
2151 if let Some((adjustments
, did
, field_ty
)) = private_candidate
{
2152 // (#90483) apply adjustments to avoid ExprUseVisitor from
2153 // creating erroneous projection.
2154 self.apply_adjustments(base
, adjustments
);
2155 self.ban_private_field_access(expr
, expr_t
, field
, did
);
2159 if field
.name
== kw
::Empty
{
2160 } else if self.method_exists(field
, expr_t
, expr
.hir_id
, true) {
2161 self.ban_take_value_of_method(expr
, expr_t
, field
);
2162 } else if !expr_t
.is_primitive_ty() {
2163 self.ban_nonexisting_field(field
, base
, expr
, expr_t
);
2170 "`{expr_t}` is a primitive type and therefore doesn't have fields",
2175 self.tcx().ty_error()
2178 fn check_call_constructor
<G
: EmissionGuarantee
>(
2180 err
: &mut DiagnosticBuilder
<'_
, G
>,
2181 base
: &'tcx hir
::Expr
<'tcx
>,
2184 if let Some(local_id
) = def_id
.as_local() {
2185 let hir_id
= self.tcx
.hir().local_def_id_to_hir_id(local_id
);
2186 let node
= self.tcx
.hir().get(hir_id
);
2188 if let Some(fields
) = node
.tuple_fields() {
2189 let kind
= match self.tcx
.opt_def_kind(local_id
) {
2190 Some(DefKind
::Ctor(of
, _
)) => of
,
2194 suggest_call_constructor(base
.span
, kind
, fields
.len(), err
);
2197 // The logic here isn't smart but `associated_item_def_ids`
2198 // doesn't work nicely on local.
2199 if let DefKind
::Ctor(of
, _
) = self.tcx
.def_kind(def_id
) {
2200 let parent_def_id
= self.tcx
.parent(def_id
);
2201 let fields
= self.tcx
.associated_item_def_ids(parent_def_id
);
2202 suggest_call_constructor(base
.span
, of
, fields
.len(), err
);
2207 fn suggest_await_on_field_access(
2209 err
: &mut Diagnostic
,
2211 base
: &'tcx hir
::Expr
<'tcx
>,
2214 let output_ty
= match self.infcx
.get_impl_future_output_ty(ty
) {
2215 Some(output_ty
) => self.resolve_vars_if_possible(output_ty
),
2218 let mut add_label
= true;
2219 if let ty
::Adt(def
, _
) = output_ty
.skip_binder().kind() {
2220 // no field access on enum type
2226 .any(|field
| field
.ident(self.tcx
) == field_ident
)
2231 "field not available in `impl Future`, but it is available in its `Output`",
2233 err
.span_suggestion_verbose(
2234 base
.span
.shrink_to_hi(),
2235 "consider `await`ing on the `Future` and access the field of its `Output`",
2237 Applicability
::MaybeIncorrect
,
2243 err
.span_label(field_ident
.span
, &format
!("field not found in `{ty}`"));
2247 fn ban_nonexisting_field(
2250 base
: &'tcx hir
::Expr
<'tcx
>,
2251 expr
: &'tcx hir
::Expr
<'tcx
>,
2255 "ban_nonexisting_field: field={:?}, base={:?}, expr={:?}, expr_ty={:?}",
2256 field
, base
, expr
, expr_t
2258 let mut err
= self.no_such_field_err(field
, expr_t
, base
.hir_id
);
2260 match *expr_t
.peel_refs().kind() {
2261 ty
::Array(_
, len
) => {
2262 self.maybe_suggest_array_indexing(&mut err
, expr
, base
, field
, len
);
2265 self.suggest_first_deref_field(&mut err
, expr
, base
, field
);
2267 ty
::Adt(def
, _
) if !def
.is_enum() => {
2268 self.suggest_fields_on_recordish(&mut err
, def
, field
, expr
.span
);
2270 ty
::Param(param_ty
) => {
2271 self.point_at_param_definition(&mut err
, param_ty
);
2273 ty
::Opaque(_
, _
) => {
2274 self.suggest_await_on_field_access(&mut err
, field
, base
, expr_t
.peel_refs());
2276 ty
::FnDef(def_id
, _
) => {
2277 self.check_call_constructor(&mut err
, base
, def_id
);
2282 if field
.name
== kw
::Await
{
2283 // We know by construction that `<expr>.await` is either on Rust 2015
2284 // or results in `ExprKind::Await`. Suggest switching the edition to 2018.
2285 err
.note("to `.await` a `Future`, switch to Rust 2018 or later");
2286 err
.help_use_latest_edition();
2292 fn ban_private_field_access(
2294 expr
: &hir
::Expr
<'_
>,
2299 let struct_path
= self.tcx().def_path_str(base_did
);
2300 let kind_name
= self.tcx().def_kind(base_did
).descr(base_did
);
2301 let mut err
= struct_span_err
!(
2305 "field `{field}` of {kind_name} `{struct_path}` is private",
2307 err
.span_label(field
.span
, "private field");
2308 // Also check if an accessible method exists, which is often what is meant.
2309 if self.method_exists(field
, expr_t
, expr
.hir_id
, false) && !self.expr_in_place(expr
.hir_id
)
2311 self.suggest_method_call(
2313 &format
!("a method `{field}` also exists, call it with parentheses"),
2323 fn ban_take_value_of_method(&self, expr
: &hir
::Expr
<'_
>, expr_t
: Ty
<'tcx
>, field
: Ident
) {
2324 let mut err
= type_error_struct
!(
2329 "attempted to take value of method `{field}` on type `{expr_t}`",
2331 err
.span_label(field
.span
, "method, not a field");
2333 if let hir
::Node
::Expr(hir
::Expr { kind: ExprKind::Call(callee, _args), .. }
) =
2334 self.tcx
.hir().get(self.tcx
.hir().get_parent_node(expr
.hir_id
))
2336 expr
.hir_id
== callee
.hir_id
2341 self.tcx
.sess
.source_map().span_to_snippet(expr
.span
).unwrap_or(String
::new());
2342 let is_wrapped
= expr_snippet
.starts_with('
('
) && expr_snippet
.ends_with('
)'
);
2343 let after_open
= expr
.span
.lo() + rustc_span
::BytePos(1);
2344 let before_close
= expr
.span
.hi() - rustc_span
::BytePos(1);
2346 if expr_is_call
&& is_wrapped
{
2347 err
.multipart_suggestion(
2348 "remove wrapping parentheses to call the method",
2350 (expr
.span
.with_hi(after_open
), String
::new()),
2351 (expr
.span
.with_lo(before_close
), String
::new()),
2353 Applicability
::MachineApplicable
,
2355 } else if !self.expr_in_place(expr
.hir_id
) {
2356 // Suggest call parentheses inside the wrapping parentheses
2357 let span
= if is_wrapped
{
2358 expr
.span
.with_lo(after_open
).with_hi(before_close
)
2362 self.suggest_method_call(
2364 "use parentheses to call the method",
2371 let mut found
= false;
2373 if let ty
::RawPtr(ty_and_mut
) = expr_t
.kind()
2374 && let ty
::Adt(adt_def
, _
) = ty_and_mut
.ty
.kind()
2376 if adt_def
.variants().len() == 1
2384 .any(|f
| f
.ident(self.tcx
) == field
)
2386 if let Some(dot_loc
) = expr_snippet
.rfind('
.'
) {
2388 err
.span_suggestion(
2389 expr
.span
.with_hi(expr
.span
.lo() + BytePos
::from_usize(dot_loc
)),
2390 "to access the field, dereference first",
2391 format
!("(*{})", &expr_snippet
[0..dot_loc
]),
2392 Applicability
::MaybeIncorrect
,
2399 err
.help("methods are immutable and cannot be assigned to");
2406 fn point_at_param_definition(&self, err
: &mut Diagnostic
, param
: ty
::ParamTy
) {
2407 let generics
= self.tcx
.generics_of(self.body_id
.owner
.to_def_id());
2408 let generic_param
= generics
.type_param(¶m
, self.tcx
);
2409 if let ty
::GenericParamDefKind
::Type { synthetic: true, .. }
= generic_param
.kind
{
2412 let param_def_id
= generic_param
.def_id
;
2413 let param_hir_id
= match param_def_id
.as_local() {
2414 Some(x
) => self.tcx
.hir().local_def_id_to_hir_id(x
),
2417 let param_span
= self.tcx
.hir().span(param_hir_id
);
2418 let param_name
= self.tcx
.hir().ty_param_name(param_def_id
.expect_local());
2420 err
.span_label(param_span
, &format
!("type parameter '{param_name}' declared here"));
2423 fn suggest_fields_on_recordish(
2425 err
: &mut Diagnostic
,
2426 def
: ty
::AdtDef
<'tcx
>,
2430 if let Some(suggested_field_name
) =
2431 self.suggest_field_name(def
.non_enum_variant(), field
.name
, vec
![], access_span
)
2433 err
.span_suggestion(
2435 "a field with a similar name exists",
2436 suggested_field_name
,
2437 Applicability
::MaybeIncorrect
,
2440 err
.span_label(field
.span
, "unknown field");
2441 let struct_variant_def
= def
.non_enum_variant();
2442 let field_names
= self.available_field_names(struct_variant_def
, access_span
);
2443 if !field_names
.is_empty() {
2445 "available fields are: {}",
2446 self.name_series_display(field_names
),
2452 fn maybe_suggest_array_indexing(
2454 err
: &mut Diagnostic
,
2455 expr
: &hir
::Expr
<'_
>,
2456 base
: &hir
::Expr
<'_
>,
2458 len
: ty
::Const
<'tcx
>,
2460 if let (Some(len
), Ok(user_index
)) =
2461 (len
.try_eval_usize(self.tcx
, self.param_env
), field
.as_str().parse
::<u64>())
2462 && let Ok(base
) = self.tcx
.sess
.source_map().span_to_snippet(base
.span
)
2464 let help
= "instead of using tuple indexing, use array indexing";
2465 let suggestion
= format
!("{base}[{field}]");
2466 let applicability
= if len
< user_index
{
2467 Applicability
::MachineApplicable
2469 Applicability
::MaybeIncorrect
2471 err
.span_suggestion(expr
.span
, help
, suggestion
, applicability
);
2475 fn suggest_first_deref_field(
2477 err
: &mut Diagnostic
,
2478 expr
: &hir
::Expr
<'_
>,
2479 base
: &hir
::Expr
<'_
>,
2482 if let Ok(base
) = self.tcx
.sess
.source_map().span_to_snippet(base
.span
) {
2483 let msg
= format
!("`{base}` is a raw pointer; try dereferencing it");
2484 let suggestion
= format
!("(*{base}).{field}");
2485 err
.span_suggestion(expr
.span
, &msg
, suggestion
, Applicability
::MaybeIncorrect
);
2489 fn no_such_field_err(
2494 ) -> DiagnosticBuilder
<'_
, ErrorGuaranteed
> {
2495 let span
= field
.span
;
2496 debug
!("no_such_field_err(span: {:?}, field: {:?}, expr_t: {:?})", span
, field
, expr_t
);
2498 let mut err
= type_error_struct
!(
2503 "no field `{field}` on type `{expr_t}`",
2506 // try to add a suggestion in case the field is a nested field of a field of the Adt
2507 if let Some((fields
, substs
)) = self.get_field_candidates(span
, expr_t
) {
2508 for candidate_field
in fields
.iter() {
2509 if let Some(mut field_path
) = self.check_for_nested_field_satisfying(
2511 &|candidate_field
, _
| candidate_field
.ident(self.tcx()) == field
,
2515 self.tcx
.parent_module(id
).to_def_id(),
2517 // field_path includes `field` that we're looking for, so pop it.
2520 let field_path_str
= field_path
2522 .map(|id
| id
.name
.to_ident_string())
2523 .collect
::<Vec
<String
>>()
2525 debug
!("field_path_str: {:?}", field_path_str
);
2527 err
.span_suggestion_verbose(
2528 field
.span
.shrink_to_lo(),
2529 "one of the expressions' fields has a field of the same name",
2530 format
!("{field_path_str}."),
2531 Applicability
::MaybeIncorrect
,
2539 pub(crate) fn get_field_candidates(
2543 ) -> Option
<(&[ty
::FieldDef
], SubstsRef
<'tcx
>)> {
2544 debug
!("get_field_candidates(span: {:?}, base_t: {:?}", span
, base_t
);
2546 for (base_t
, _
) in self.autoderef(span
, base_t
) {
2547 match base_t
.kind() {
2548 ty
::Adt(base_def
, substs
) if !base_def
.is_enum() => {
2549 let fields
= &base_def
.non_enum_variant().fields
;
2550 // For compile-time reasons put a limit on number of fields we search
2551 if fields
.len() > 100 {
2554 return Some((fields
, substs
));
2562 /// This method is called after we have encountered a missing field error to recursively
2563 /// search for the field
2564 pub(crate) fn check_for_nested_field_satisfying(
2567 matches
: &impl Fn(&ty
::FieldDef
, Ty
<'tcx
>) -> bool
,
2568 candidate_field
: &ty
::FieldDef
,
2569 subst
: SubstsRef
<'tcx
>,
2570 mut field_path
: Vec
<Ident
>,
2572 ) -> Option
<Vec
<Ident
>> {
2574 "check_for_nested_field_satisfying(span: {:?}, candidate_field: {:?}, field_path: {:?}",
2575 span
, candidate_field
, field_path
2578 if field_path
.len() > 3 {
2579 // For compile-time reasons and to avoid infinite recursion we only check for fields
2580 // up to a depth of three
2583 // recursively search fields of `candidate_field` if it's a ty::Adt
2584 field_path
.push(candidate_field
.ident(self.tcx
).normalize_to_macros_2_0());
2585 let field_ty
= candidate_field
.ty(self.tcx
, subst
);
2586 if let Some((nested_fields
, subst
)) = self.get_field_candidates(span
, field_ty
) {
2587 for field
in nested_fields
.iter() {
2588 if field
.vis
.is_accessible_from(id
, self.tcx
) {
2589 if matches(candidate_field
, field_ty
) {
2590 return Some(field_path
);
2591 } else if let Some(field_path
) = self.check_for_nested_field_satisfying(
2599 return Some(field_path
);
2608 fn check_expr_index(
2610 base
: &'tcx hir
::Expr
<'tcx
>,
2611 idx
: &'tcx hir
::Expr
<'tcx
>,
2612 expr
: &'tcx hir
::Expr
<'tcx
>,
2614 let base_t
= self.check_expr(&base
);
2615 let idx_t
= self.check_expr(&idx
);
2617 if base_t
.references_error() {
2619 } else if idx_t
.references_error() {
2622 let base_t
= self.structurally_resolved_type(base
.span
, base_t
);
2623 match self.lookup_indexing(expr
, base
, base_t
, idx
, idx_t
) {
2624 Some((index_ty
, element_ty
)) => {
2625 // two-phase not needed because index_ty is never mutable
2626 self.demand_coerce(idx
, idx_t
, index_ty
, None
, AllowTwoPhase
::No
);
2630 let mut err
= type_error_struct
!(
2635 "cannot index into a value of type `{base_t}`",
2637 // Try to give some advice about indexing tuples.
2638 if let ty
::Tuple(..) = base_t
.kind() {
2639 let mut needs_note
= true;
2640 // If the index is an integer, we can show the actual
2641 // fixed expression:
2642 if let ExprKind
::Lit(ref lit
) = idx
.kind
{
2643 if let ast
::LitKind
::Int(i
, ast
::LitIntType
::Unsuffixed
) = lit
.node
{
2644 let snip
= self.tcx
.sess
.source_map().span_to_snippet(base
.span
);
2645 if let Ok(snip
) = snip
{
2646 err
.span_suggestion(
2648 "to access tuple elements, use",
2649 format
!("{snip}.{i}"),
2650 Applicability
::MachineApplicable
,
2658 "to access tuple elements, use tuple indexing \
2659 syntax (e.g., `tuple.0`)",
2670 fn check_expr_yield(
2672 value
: &'tcx hir
::Expr
<'tcx
>,
2673 expr
: &'tcx hir
::Expr
<'tcx
>,
2674 src
: &'tcx hir
::YieldSource
,
2676 match self.resume_yield_tys
{
2677 Some((resume_ty
, yield_ty
)) => {
2678 self.check_expr_coercable_to_type(&value
, yield_ty
, None
);
2682 // Given that this `yield` expression was generated as a result of lowering a `.await`,
2683 // we know that the yield type must be `()`; however, the context won't contain this
2684 // information. Hence, we check the source of the yield expression here and check its
2685 // value's type against `()` (this check should always hold).
2686 None
if src
.is_await() => {
2687 self.check_expr_coercable_to_type(&value
, self.tcx
.mk_unit(), None
);
2691 self.tcx
.sess
.emit_err(YieldExprOutsideOfGenerator { span: expr.span }
);
2692 // Avoid expressions without types during writeback (#78653).
2693 self.check_expr(value
);
2699 fn check_expr_asm_operand(&self, expr
: &'tcx hir
::Expr
<'tcx
>, is_input
: bool
) {
2700 let needs
= if is_input { Needs::None }
else { Needs::MutPlace }
;
2701 let ty
= self.check_expr_with_needs(expr
, needs
);
2702 self.require_type_is_sized(ty
, expr
.span
, traits
::InlineAsmSized
);
2704 if !is_input
&& !expr
.is_syntactic_place_expr() {
2705 let mut err
= self.tcx
.sess
.struct_span_err(expr
.span
, "invalid asm output");
2706 err
.span_label(expr
.span
, "cannot assign to this expression");
2710 // If this is an input value, we require its type to be fully resolved
2711 // at this point. This allows us to provide helpful coercions which help
2712 // pass the type candidate list in a later pass.
2714 // We don't require output types to be resolved at this point, which
2715 // allows them to be inferred based on how they are used later in the
2718 let ty
= self.structurally_resolved_type(expr
.span
, ty
);
2721 let fnptr_ty
= self.tcx
.mk_fn_ptr(ty
.fn_sig(self.tcx
));
2722 self.demand_coerce(expr
, ty
, fnptr_ty
, None
, AllowTwoPhase
::No
);
2724 ty
::Ref(_
, base_ty
, mutbl
) => {
2725 let ptr_ty
= self.tcx
.mk_ptr(ty
::TypeAndMut { ty: base_ty, mutbl }
);
2726 self.demand_coerce(expr
, ty
, ptr_ty
, None
, AllowTwoPhase
::No
);
2733 fn check_expr_asm(&self, asm
: &'tcx hir
::InlineAsm
<'tcx
>) -> Ty
<'tcx
> {
2734 for (op
, _op_sp
) in asm
.operands
{
2736 hir
::InlineAsmOperand
::In { expr, .. }
=> {
2737 self.check_expr_asm_operand(expr
, true);
2739 hir
::InlineAsmOperand
::Out { expr: Some(expr), .. }
2740 | hir
::InlineAsmOperand
::InOut { expr, .. }
=> {
2741 self.check_expr_asm_operand(expr
, false);
2743 hir
::InlineAsmOperand
::Out { expr: None, .. }
=> {}
2744 hir
::InlineAsmOperand
::SplitInOut { in_expr, out_expr, .. }
=> {
2745 self.check_expr_asm_operand(in_expr
, true);
2746 if let Some(out_expr
) = out_expr
{
2747 self.check_expr_asm_operand(out_expr
, false);
2750 // `AnonConst`s have their own body and is type-checked separately.
2751 // As they don't flow into the type system we don't need them to
2753 hir
::InlineAsmOperand
::Const { .. }
| hir
::InlineAsmOperand
::SymFn { .. }
=> {}
2754 hir
::InlineAsmOperand
::SymStatic { .. }
=> {}
2757 if asm
.options
.contains(ast
::InlineAsmOptions
::NORETURN
) {
2758 self.tcx
.types
.never
2765 pub(super) fn ty_kind_suggestion(ty
: Ty
<'_
>) -> Option
<&'
static str> {
2766 Some(match ty
.kind() {
2769 ty
::Int(_
) | ty
::Uint(_
) => "42",
2770 ty
::Float(_
) => "3.14159",
2771 ty
::Error(_
) | ty
::Never
=> return None
,