1 //! Type checking expressions.
3 //! See `mod.rs` for more context on type checking in general.
6 use crate::coercion
::CoerceMany
;
7 use crate::coercion
::DynamicCoerceMany
;
8 use crate::errors
::TypeMismatchFruTypo
;
9 use crate::errors
::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive}
;
11 FieldMultiplySpecifiedInInitializer
, FunctionalRecordUpdateOnNonStruct
, HelpUseLatestEdition
,
12 YieldExprOutsideOfGenerator
,
14 use crate::fatally_break_rust
;
15 use crate::method
::SelfSource
;
16 use crate::type_error_struct
;
17 use crate::Expectation
::{self, ExpectCastableToType, ExpectHasType, NoExpectation}
;
19 report_unexpected_variant_res
, BreakableCtxt
, Diverges
, FnCtxt
, Needs
,
20 TupleArgumentsFlag
::DontTupleArguments
,
23 use rustc_data_structures
::fx
::FxHashMap
;
24 use rustc_data_structures
::stack
::ensure_sufficient_stack
;
26 pluralize
, struct_span_err
, AddToDiagnostic
, Applicability
, Diagnostic
, DiagnosticBuilder
,
27 DiagnosticId
, ErrorGuaranteed
, StashKey
,
30 use rustc_hir
::def
::{CtorKind, DefKind, Res}
;
31 use rustc_hir
::def_id
::DefId
;
32 use rustc_hir
::intravisit
::Visitor
;
33 use rustc_hir
::lang_items
::LangItem
;
34 use rustc_hir
::{ExprKind, HirId, QPath}
;
35 use rustc_hir_analysis
::astconv
::AstConv
as _
;
36 use rustc_hir_analysis
::check
::ty_kind_suggestion
;
37 use rustc_infer
::infer
;
38 use rustc_infer
::infer
::type_variable
::{TypeVariableOrigin, TypeVariableOriginKind}
;
39 use rustc_infer
::infer
::DefineOpaqueTypes
;
40 use rustc_infer
::infer
::InferOk
;
41 use rustc_infer
::traits
::query
::NoSolution
;
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, Ty, TypeVisitableExt}
;
48 use rustc_session
::errors
::ExprParenthesesNeeded
;
49 use rustc_session
::parse
::feature_err
;
50 use rustc_span
::edit_distance
::find_best_match_for_name
;
51 use rustc_span
::hygiene
::DesugaringKind
;
52 use rustc_span
::source_map
::{Span, Spanned}
;
53 use rustc_span
::symbol
::{kw, sym, Ident, Symbol}
;
54 use rustc_target
::abi
::FieldIdx
;
55 use rustc_target
::spec
::abi
::Abi
::RustIntrinsic
;
56 use rustc_trait_selection
::infer
::InferCtxtExt
;
57 use rustc_trait_selection
::traits
::error_reporting
::TypeErrCtxtExt
;
58 use rustc_trait_selection
::traits
::ObligationCtxt
;
59 use rustc_trait_selection
::traits
::{self, ObligationCauseCode}
;
61 impl<'a
, 'tcx
> FnCtxt
<'a
, 'tcx
> {
62 fn check_expr_eq_type(&self, expr
: &'tcx hir
::Expr
<'tcx
>, expected
: Ty
<'tcx
>) {
63 let ty
= self.check_expr_with_hint(expr
, expected
);
64 self.demand_eqtype(expr
.span
, expected
, ty
);
67 pub fn check_expr_has_type_or_error(
69 expr
: &'tcx hir
::Expr
<'tcx
>,
71 extend_err
: impl FnMut(&mut Diagnostic
),
73 self.check_expr_meets_expectation_or_error(expr
, ExpectHasType(expected
), extend_err
)
76 fn check_expr_meets_expectation_or_error(
78 expr
: &'tcx hir
::Expr
<'tcx
>,
79 expected
: Expectation
<'tcx
>,
80 mut extend_err
: impl FnMut(&mut Diagnostic
),
82 let expected_ty
= expected
.to_option(&self).unwrap_or(self.tcx
.types
.bool
);
83 let mut ty
= self.check_expr_with_expectation(expr
, expected
);
85 // While we don't allow *arbitrary* coercions here, we *do* allow
86 // coercions from ! to `expected`.
88 if let Some(adjustments
) = self.typeck_results
.borrow().adjustments().get(expr
.hir_id
) {
89 let reported
= self.tcx().sess
.delay_span_bug(
91 "expression with never type wound up being adjusted",
93 return if let [Adjustment { kind: Adjust::NeverToAny, target }
] = &adjustments
[..] {
96 self.tcx().ty_error(reported
)
100 let adj_ty
= self.next_ty_var(TypeVariableOrigin
{
101 kind
: TypeVariableOriginKind
::AdjustmentType
,
104 self.apply_adjustments(
106 vec
![Adjustment { kind: Adjust::NeverToAny, target: adj_ty }
],
111 if let Some(mut err
) = self.demand_suptype_diag(expr
.span
, expected_ty
, ty
) {
112 let _
= self.emit_type_mismatch_suggestions(
114 expr
.peel_drop_temps(),
120 extend_err(&mut err
);
126 pub(super) fn check_expr_coercible_to_type(
128 expr
: &'tcx hir
::Expr
<'tcx
>,
130 expected_ty_expr
: Option
<&'tcx hir
::Expr
<'tcx
>>,
132 let ty
= self.check_expr_with_hint(expr
, expected
);
133 // checks don't need two phase
134 self.demand_coerce(expr
, ty
, expected
, expected_ty_expr
, AllowTwoPhase
::No
)
137 pub(super) fn check_expr_with_hint(
139 expr
: &'tcx hir
::Expr
<'tcx
>,
142 self.check_expr_with_expectation(expr
, ExpectHasType(expected
))
145 fn check_expr_with_expectation_and_needs(
147 expr
: &'tcx hir
::Expr
<'tcx
>,
148 expected
: Expectation
<'tcx
>,
151 let ty
= self.check_expr_with_expectation(expr
, expected
);
153 // If the expression is used in a place whether mutable place is required
154 // e.g. LHS of assignment, perform the conversion.
155 if let Needs
::MutPlace
= needs
{
156 self.convert_place_derefs_to_mutable(expr
);
162 pub(super) fn check_expr(&self, expr
: &'tcx hir
::Expr
<'tcx
>) -> Ty
<'tcx
> {
163 self.check_expr_with_expectation(expr
, NoExpectation
)
166 pub(super) fn check_expr_with_needs(
168 expr
: &'tcx hir
::Expr
<'tcx
>,
171 self.check_expr_with_expectation_and_needs(expr
, NoExpectation
, needs
)
175 /// If an expression has any sub-expressions that result in a type error,
176 /// inspecting that expression's type with `ty.references_error()` will return
177 /// true. Likewise, if an expression is known to diverge, inspecting its
178 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
179 /// strict, _|_ can appear in the type of an expression that does not,
180 /// itself, diverge: for example, fn() -> _|_.)
181 /// Note that inspecting a type's structure *directly* may expose the fact
182 /// that there are actually multiple representations for `Error`, so avoid
183 /// that when err needs to be handled differently.
184 #[instrument(skip(self, expr), level = "debug")]
185 pub(super) fn check_expr_with_expectation(
187 expr
: &'tcx hir
::Expr
<'tcx
>,
188 expected
: Expectation
<'tcx
>,
190 self.check_expr_with_expectation_and_args(expr
, expected
, &[])
193 /// Same as `check_expr_with_expectation`, but allows us to pass in the arguments of a
194 /// `ExprKind::Call` when evaluating its callee when it is an `ExprKind::Path`.
195 pub(super) fn check_expr_with_expectation_and_args(
197 expr
: &'tcx hir
::Expr
<'tcx
>,
198 expected
: Expectation
<'tcx
>,
199 args
: &'tcx
[hir
::Expr
<'tcx
>],
201 if self.tcx().sess
.verbose() {
202 // make this code only run with -Zverbose because it is probably slow
203 if let Ok(lint_str
) = self.tcx
.sess
.source_map().span_to_snippet(expr
.span
) {
204 if !lint_str
.contains('
\n'
) {
205 debug
!("expr text: {lint_str}");
207 let mut lines
= lint_str
.lines();
208 if let Some(line0
) = lines
.next() {
209 let remaining_lines
= lines
.count();
210 debug
!("expr text: {line0}");
211 debug
!("expr text: ...(and {remaining_lines} more lines)");
217 // True if `expr` is a `Try::from_ok(())` that is a result of desugaring a try block
218 // without the final expr (e.g. `try { return; }`). We don't want to generate an
219 // unreachable_code lint for it since warnings for autogenerated code are confusing.
220 let is_try_block_generated_unit_expr
= match expr
.kind
{
221 ExprKind
::Call(_
, args
) if expr
.span
.is_desugaring(DesugaringKind
::TryBlock
) => {
222 args
.len() == 1 && args
[0].span
.is_desugaring(DesugaringKind
::TryBlock
)
228 // Warn for expressions after diverging siblings.
229 if !is_try_block_generated_unit_expr
{
230 self.warn_if_unreachable(expr
.hir_id
, expr
.span
, "expression");
233 // Hide the outer diverging and has_errors flags.
234 let old_diverges
= self.diverges
.replace(Diverges
::Maybe
);
236 let ty
= ensure_sufficient_stack(|| match &expr
.kind
{
238 qpath @
(hir
::QPath
::Resolved(..) | hir
::QPath
::TypeRelative(..)),
239 ) => self.check_expr_path(qpath
, expr
, args
),
240 _
=> self.check_expr_kind(expr
, expected
),
242 let ty
= self.resolve_vars_if_possible(ty
);
244 // Warn for non-block expressions with diverging children.
250 | ExprKind
::Match(..) => {}
251 // If `expr` is a result of desugaring the try block and is an ok-wrapped
252 // diverging expression (e.g. it arose from desugaring of `try { return }`),
253 // we skip issuing a warning because it is autogenerated code.
254 ExprKind
::Call(..) if expr
.span
.is_desugaring(DesugaringKind
::TryBlock
) => {}
255 ExprKind
::Call(callee
, _
) => self.warn_if_unreachable(expr
.hir_id
, callee
.span
, "call"),
256 ExprKind
::MethodCall(segment
, ..) => {
257 self.warn_if_unreachable(expr
.hir_id
, segment
.ident
.span
, "call")
259 _
=> self.warn_if_unreachable(expr
.hir_id
, expr
.span
, "expression"),
262 // Any expression that produces a value of type `!` must have diverged
264 self.diverges
.set(self.diverges
.get() | Diverges
::always(expr
.span
));
267 // Record the type, which applies it effects.
268 // We need to do this after the warning above, so that
269 // we don't warn for the diverging expression itself.
270 self.write_ty(expr
.hir_id
, ty
);
272 // Combine the diverging and has_error flags.
273 self.diverges
.set(self.diverges
.get() | old_diverges
);
275 debug
!("type of {} is...", self.tcx
.hir().node_to_string(expr
.hir_id
));
276 debug
!("... {:?}, expected is {:?}", ty
, expected
);
281 #[instrument(skip(self, expr), level = "debug")]
284 expr
: &'tcx hir
::Expr
<'tcx
>,
285 expected
: Expectation
<'tcx
>,
287 trace
!("expr={:#?}", expr
);
291 ExprKind
::Lit(ref lit
) => self.check_lit(&lit
, expected
),
292 ExprKind
::Binary(op
, lhs
, rhs
) => self.check_binop(expr
, op
, lhs
, rhs
, expected
),
293 ExprKind
::Assign(lhs
, rhs
, span
) => {
294 self.check_expr_assign(expr
, expected
, lhs
, rhs
, span
)
296 ExprKind
::AssignOp(op
, lhs
, rhs
) => {
297 self.check_binop_assign(expr
, op
, lhs
, rhs
, expected
)
299 ExprKind
::Unary(unop
, oprnd
) => self.check_expr_unary(unop
, oprnd
, expected
, expr
),
300 ExprKind
::AddrOf(kind
, mutbl
, oprnd
) => {
301 self.check_expr_addr_of(kind
, mutbl
, oprnd
, expected
, expr
)
303 ExprKind
::Path(QPath
::LangItem(lang_item
, _
, hir_id
)) => {
304 self.check_lang_item_path(lang_item
, expr
, hir_id
)
306 ExprKind
::Path(ref qpath
) => self.check_expr_path(qpath
, expr
, &[]),
307 ExprKind
::InlineAsm(asm
) => {
308 // We defer some asm checks as we may not have resolved the input and output types yet (they may still be infer vars).
309 self.deferred_asm_checks
.borrow_mut().push((asm
, expr
.hir_id
));
310 self.check_expr_asm(asm
)
312 ExprKind
::OffsetOf(container
, ref fields
) => {
313 self.check_offset_of(container
, fields
, expr
)
315 ExprKind
::Break(destination
, ref expr_opt
) => {
316 self.check_expr_break(destination
, expr_opt
.as_deref(), expr
)
318 ExprKind
::Continue(destination
) => {
319 if destination
.target_id
.is_ok() {
322 // There was an error; make type-check fail.
326 ExprKind
::Ret(ref expr_opt
) => self.check_expr_return(expr_opt
.as_deref(), expr
),
327 ExprKind
::Let(let_expr
) => self.check_expr_let(let_expr
),
328 ExprKind
::Loop(body
, _
, source
, _
) => {
329 self.check_expr_loop(body
, source
, expected
, expr
)
331 ExprKind
::Match(discrim
, arms
, match_src
) => {
332 self.check_match(expr
, &discrim
, arms
, expected
, match_src
)
334 ExprKind
::Closure(closure
) => self.check_expr_closure(closure
, expr
.span
, expected
),
335 ExprKind
::Block(body
, _
) => self.check_block_with_expected(&body
, expected
),
336 ExprKind
::Call(callee
, args
) => self.check_call(expr
, &callee
, args
, expected
),
337 ExprKind
::MethodCall(segment
, receiver
, args
, _
) => {
338 self.check_method_call(expr
, segment
, receiver
, args
, expected
)
340 ExprKind
::Cast(e
, t
) => self.check_expr_cast(e
, t
, expr
),
341 ExprKind
::Type(e
, t
) => {
342 let ty
= self.to_ty_saving_user_provided_ty(&t
);
343 self.check_expr_eq_type(&e
, ty
);
346 ExprKind
::If(cond
, then_expr
, opt_else_expr
) => {
347 self.check_then_else(cond
, then_expr
, opt_else_expr
, expr
.span
, expected
)
349 ExprKind
::DropTemps(e
) => self.check_expr_with_expectation(e
, expected
),
350 ExprKind
::Array(args
) => self.check_expr_array(args
, expected
, expr
),
351 ExprKind
::ConstBlock(ref anon_const
) => {
352 self.check_expr_const_block(anon_const
, expected
, expr
)
354 ExprKind
::Repeat(element
, ref count
) => {
355 self.check_expr_repeat(element
, count
, expected
, expr
)
357 ExprKind
::Tup(elts
) => self.check_expr_tuple(elts
, expected
, expr
),
358 ExprKind
::Struct(qpath
, fields
, ref base_expr
) => {
359 self.check_expr_struct(expr
, expected
, qpath
, fields
, base_expr
)
361 ExprKind
::Field(base
, field
) => self.check_field(expr
, &base
, field
, expected
),
362 ExprKind
::Index(base
, idx
) => self.check_expr_index(base
, idx
, expr
),
363 ExprKind
::Yield(value
, ref src
) => self.check_expr_yield(value
, expr
, src
),
364 hir
::ExprKind
::Err(guar
) => tcx
.ty_error(guar
),
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
).with_parent(None
);
398 tcx
.sess
.parse_sess
.ambiguous_block_expr_parse
.borrow().get(&sp
)
400 err
.subdiagnostic(ExprParenthesesNeeded
::surrounding(*sp
));
402 oprnd_t
= tcx
.ty_error(err
.emit());
406 let result
= self.check_user_unop(expr
, oprnd_t
, unop
, expected_inner
);
407 // If it's builtin, we can reuse the type, this helps inference.
408 if !(oprnd_t
.is_integral() || *oprnd_t
.kind() == ty
::Bool
) {
413 let result
= self.check_user_unop(expr
, oprnd_t
, unop
, expected_inner
);
414 // If it's builtin, we can reuse the type, this helps inference.
415 if !oprnd_t
.is_numeric() {
424 fn check_expr_addr_of(
426 kind
: hir
::BorrowKind
,
427 mutbl
: hir
::Mutability
,
428 oprnd
: &'tcx hir
::Expr
<'tcx
>,
429 expected
: Expectation
<'tcx
>,
430 expr
: &'tcx hir
::Expr
<'tcx
>,
432 let hint
= expected
.only_has_type(self).map_or(NoExpectation
, |ty
| {
434 ty
::Ref(_
, ty
, _
) | ty
::RawPtr(ty
::TypeAndMut { ty, .. }
) => {
435 if oprnd
.is_syntactic_place_expr() {
436 // Places may legitimately have unsized types.
437 // For example, dereferences of a fat pointer and
438 // the last field of a struct can be unsized.
441 Expectation
::rvalue_hint(self, *ty
)
448 self.check_expr_with_expectation_and_needs(&oprnd
, hint
, Needs
::maybe_mut_place(mutbl
));
450 let tm
= ty
::TypeAndMut { ty, mutbl }
;
452 _
if tm
.ty
.references_error() => self.tcx
.ty_error_misc(),
453 hir
::BorrowKind
::Raw
=> {
454 self.check_named_place_expr(oprnd
);
457 hir
::BorrowKind
::Ref
=> {
458 // Note: at this point, we cannot say what the best lifetime
459 // is to use for resulting pointer. We want to use the
460 // shortest lifetime possible so as to avoid spurious borrowck
461 // errors. Moreover, the longest lifetime will depend on the
462 // precise details of the value whose address is being taken
463 // (and how long it is valid), which we don't know yet until
464 // type inference is complete.
466 // Therefore, here we simply generate a region variable. The
467 // region inferencer will then select a suitable value.
468 // Finally, borrowck will infer the value of the region again,
469 // this time with enough precision to check that the value
470 // whose address was taken can actually be made to live as long
471 // as it needs to live.
472 let region
= self.next_region_var(infer
::AddrOfRegion(expr
.span
));
473 self.tcx
.mk_ref(region
, tm
)
478 /// Does this expression refer to a place that either:
479 /// * Is based on a local or static.
480 /// * Contains a dereference
481 /// Note that the adjustments for the children of `expr` should already
482 /// have been resolved.
483 fn check_named_place_expr(&self, oprnd
: &'tcx hir
::Expr
<'tcx
>) {
484 let is_named
= oprnd
.is_place_expr(|base
| {
485 // Allow raw borrows if there are any deref adjustments.
487 // const VAL: (i32,) = (0,);
488 // const REF: &(i32,) = &(0,);
490 // &raw const VAL.0; // ERROR
491 // &raw const REF.0; // OK, same as &raw const (*REF).0;
493 // This is maybe too permissive, since it allows
494 // `let u = &raw const Box::new((1,)).0`, which creates an
495 // immediately dangling raw pointer.
500 .is_some_and(|x
| x
.iter().any(|adj
| matches
!(adj
.kind
, Adjust
::Deref(_
))))
503 self.tcx
.sess
.emit_err(AddressOfTemporaryTaken { span: oprnd.span }
);
507 fn check_lang_item_path(
509 lang_item
: hir
::LangItem
,
510 expr
: &'tcx hir
::Expr
<'tcx
>,
511 hir_id
: Option
<hir
::HirId
>,
513 self.resolve_lang_item_path(lang_item
, expr
.span
, expr
.hir_id
, hir_id
).1
516 pub(crate) fn check_expr_path(
518 qpath
: &'tcx hir
::QPath
<'tcx
>,
519 expr
: &'tcx hir
::Expr
<'tcx
>,
520 args
: &'tcx
[hir
::Expr
<'tcx
>],
523 let (res
, opt_ty
, segs
) =
524 self.resolve_ty_and_res_fully_qualified_call(qpath
, expr
.hir_id
, expr
.span
);
527 self.suggest_assoc_method_call(segs
);
529 self.tcx
.sess
.delay_span_bug(qpath
.span(), "`Res::Err` but no error emitted");
530 self.set_tainted_by_errors(e
);
533 Res
::Def(DefKind
::Variant
, _
) => {
534 let e
= report_unexpected_variant_res(tcx
, res
, qpath
, expr
.span
, "E0533", "value");
537 _
=> self.instantiate_value_path(segs
, opt_ty
, res
, expr
.span
, expr
.hir_id
).0,
540 if let ty
::FnDef(did
, ..) = *ty
.kind() {
541 let fn_sig
= ty
.fn_sig(tcx
);
542 if tcx
.fn_sig(did
).skip_binder().abi() == RustIntrinsic
543 && tcx
.item_name(did
) == sym
::transmute
545 let from
= fn_sig
.inputs().skip_binder()[0];
546 let to
= fn_sig
.output().skip_binder();
547 // We defer the transmute to the end of typeck, once all inference vars have
548 // been resolved or we errored. This is important as we can only check transmute
549 // on concrete types, but the output type may not be known yet (it would only
550 // be known if explicitly specified via turbofish).
551 self.deferred_transmute_checks
.borrow_mut().push((from
, to
, expr
.hir_id
));
553 if !tcx
.features().unsized_fn_params
{
554 // We want to remove some Sized bounds from std functions,
555 // but don't want to expose the removal to stable Rust.
556 // i.e., we don't want to allow
562 // to work in stable even if the Sized bound on `drop` is relaxed.
563 for i
in 0..fn_sig
.inputs().skip_binder().len() {
564 // We just want to check sizedness, so instead of introducing
565 // placeholder lifetimes with probing, we just replace higher lifetimes
567 let span
= args
.get(i
).map(|a
| a
.span
).unwrap_or(expr
.span
);
568 let input
= self.instantiate_binder_with_fresh_vars(
570 infer
::LateBoundRegionConversionTime
::FnCall
,
573 self.require_type_is_sized_deferred(
576 traits
::SizedArgumentType(None
),
580 // Here we want to prevent struct constructors from returning unsized types.
581 // There were two cases this happened: fn pointer coercion in stable
582 // and usual function call in presence of unsized_locals.
583 // Also, as we just want to check sizedness, instead of introducing
584 // placeholder lifetimes with probing, we just replace higher lifetimes
586 let output
= self.instantiate_binder_with_fresh_vars(
588 infer
::LateBoundRegionConversionTime
::FnCall
,
591 self.require_type_is_sized_deferred(output
, expr
.span
, traits
::SizedReturnType
);
594 // We always require that the type provided as the value for
595 // a type parameter outlives the moment of instantiation.
596 let substs
= self.typeck_results
.borrow().node_substs(expr
.hir_id
);
597 self.add_wf_bounds(substs
, expr
);
604 destination
: hir
::Destination
,
605 expr_opt
: Option
<&'tcx hir
::Expr
<'tcx
>>,
606 expr
: &'tcx hir
::Expr
<'tcx
>,
609 if let Ok(target_id
) = destination
.target_id
{
611 if let Some(e
) = expr_opt
{
612 // If this is a break with a value, we need to type-check
613 // the expression. Get an expected type from the loop context.
614 let opt_coerce_to
= {
615 // We should release `enclosing_breakables` before the `check_expr_with_hint`
616 // below, so can't move this block of code to the enclosing scope and share
617 // `ctxt` with the second `enclosing_breakables` borrow below.
618 let mut enclosing_breakables
= self.enclosing_breakables
.borrow_mut();
619 match enclosing_breakables
.opt_find_breakable(target_id
) {
620 Some(ctxt
) => ctxt
.coerce
.as_ref().map(|coerce
| coerce
.expected_ty()),
622 // Avoid ICE when `break` is inside a closure (#65383).
623 return tcx
.ty_error_with_message(
625 "break was outside loop, but no error was emitted",
631 // If the loop context is not a `loop { }`, then break with
632 // a value is illegal, and `opt_coerce_to` will be `None`.
633 // Just set expectation to error in that case.
634 let coerce_to
= opt_coerce_to
.unwrap_or_else(|| tcx
.ty_error_misc());
636 // Recurse without `enclosing_breakables` borrowed.
637 e_ty
= self.check_expr_with_hint(e
, coerce_to
);
638 cause
= self.misc(e
.span
);
640 // Otherwise, this is a break *without* a value. That's
641 // always legal, and is equivalent to `break ()`.
642 e_ty
= tcx
.mk_unit();
643 cause
= self.misc(expr
.span
);
646 // Now that we have type-checked `expr_opt`, borrow
647 // the `enclosing_loops` field and let's coerce the
648 // type of `expr_opt` into what is expected.
649 let mut enclosing_breakables
= self.enclosing_breakables
.borrow_mut();
650 let Some(ctxt
) = enclosing_breakables
.opt_find_breakable(target_id
) else {
651 // Avoid ICE when `break` is inside a closure (#65383).
652 return tcx
.ty_error_with_message(
654 "break was outside loop, but no error was emitted",
658 if let Some(ref mut coerce
) = ctxt
.coerce
{
659 if let Some(ref e
) = expr_opt
{
660 coerce
.coerce(self, &cause
, e
, e_ty
);
662 assert
!(e_ty
.is_unit());
663 let ty
= coerce
.expected_ty();
664 coerce
.coerce_forced_unit(
668 self.suggest_mismatched_types_on_tail(
669 &mut err
, expr
, ty
, e_ty
, target_id
,
671 if let Some(val
) = ty_kind_suggestion(ty
) {
672 let label
= destination
674 .map(|l
| format
!(" {}", l
.ident
))
675 .unwrap_or_else(String
::new
);
678 "give it a value of the expected type",
679 format
!("break{label} {val}"),
680 Applicability
::HasPlaceholders
,
688 // If `ctxt.coerce` is `None`, we can just ignore
689 // the type of the expression. This is because
690 // either this was a break *without* a value, in
691 // which case it is always a legal type (`()`), or
692 // else an error would have been flagged by the
693 // `loops` pass for using break with an expression
694 // where you are not supposed to.
695 assert
!(expr_opt
.is_none() || self.tcx
.sess
.has_errors().is_some());
698 // If we encountered a `break`, then (no surprise) it may be possible to break from the
699 // loop... unless the value being returned from the loop diverges itself, e.g.
700 // `break return 5` or `break loop {}`.
701 ctxt
.may_break
|= !self.diverges
.get().is_always();
703 // the type of a `break` is always `!`, since it diverges
706 // Otherwise, we failed to find the enclosing loop;
707 // this can only happen if the `break` was not
708 // inside a loop at all, which is caught by the
709 // loop-checking pass.
710 let err
= self.tcx
.ty_error_with_message(
712 "break was outside loop, but no error was emitted",
715 // We still need to assign a type to the inner expression to
716 // prevent the ICE in #43162.
717 if let Some(e
) = expr_opt
{
718 self.check_expr_with_hint(e
, err
);
720 // ... except when we try to 'break rust;'.
721 // ICE this expression in particular (see #43162).
722 if let ExprKind
::Path(QPath
::Resolved(_
, path
)) = e
.kind
{
723 if path
.segments
.len() == 1 && path
.segments
[0].ident
.name
== sym
::rust
{
724 fatally_break_rust(self.tcx
);
729 // There was an error; make type-check fail.
734 fn check_expr_return(
736 expr_opt
: Option
<&'tcx hir
::Expr
<'tcx
>>,
737 expr
: &'tcx hir
::Expr
<'tcx
>,
739 if self.ret_coercion
.is_none() {
740 let mut err
= ReturnStmtOutsideOfFnBody
{
742 encl_body_span
: None
,
746 let encl_item_id
= self.tcx
.hir().get_parent_item(expr
.hir_id
);
748 if let Some(hir
::Node
::Item(hir
::Item
{
749 kind
: hir
::ItemKind
::Fn(..),
753 | Some(hir
::Node
::TraitItem(hir
::TraitItem
{
754 kind
: hir
::TraitItemKind
::Fn(_
, hir
::TraitFn
::Provided(_
)),
758 | Some(hir
::Node
::ImplItem(hir
::ImplItem
{
759 kind
: hir
::ImplItemKind
::Fn(..),
762 })) = self.tcx
.hir().find_by_def_id(encl_item_id
.def_id
)
764 // We are inside a function body, so reporting "return statement
765 // outside of function body" needs an explanation.
767 let encl_body_owner_id
= self.tcx
.hir().enclosing_body_owner(expr
.hir_id
);
769 // If this didn't hold, we would not have to report an error in
771 assert_ne
!(encl_item_id
.def_id
, encl_body_owner_id
);
773 let encl_body_id
= self.tcx
.hir().body_owned_by(encl_body_owner_id
);
774 let encl_body
= self.tcx
.hir().body(encl_body_id
);
776 err
.encl_body_span
= Some(encl_body
.value
.span
);
777 err
.encl_fn_span
= Some(*encl_fn_span
);
780 self.tcx
.sess
.emit_err(err
);
782 if let Some(e
) = expr_opt
{
783 // We still have to type-check `e` (issue #86188), but calling
784 // `check_return_expr` only works inside fn bodies.
787 } else if let Some(e
) = expr_opt
{
788 if self.ret_coercion_span
.get().is_none() {
789 self.ret_coercion_span
.set(Some(e
.span
));
791 self.check_return_expr(e
, true);
793 let mut coercion
= self.ret_coercion
.as_ref().unwrap().borrow_mut();
794 if self.ret_coercion_span
.get().is_none() {
795 self.ret_coercion_span
.set(Some(expr
.span
));
797 let cause
= self.cause(expr
.span
, ObligationCauseCode
::ReturnNoExpression
);
798 if let Some((_
, fn_decl
, _
)) = self.get_fn_decl(expr
.hir_id
) {
799 coercion
.coerce_forced_unit(
803 let span
= fn_decl
.output
.span();
804 if let Ok(snippet
) = self.tcx
.sess
.source_map().span_to_snippet(span
) {
807 format
!("expected `{snippet}` because of this return type"),
814 coercion
.coerce_forced_unit(self, &cause
, &mut |_
| (), true);
820 /// `explicit_return` is `true` if we're checking an explicit `return expr`,
821 /// and `false` if we're checking a trailing expression.
822 pub(super) fn check_return_expr(
824 return_expr
: &'tcx hir
::Expr
<'tcx
>,
825 explicit_return
: bool
,
827 let ret_coercion
= self.ret_coercion
.as_ref().unwrap_or_else(|| {
828 span_bug
!(return_expr
.span
, "check_return_expr called outside fn body")
831 let ret_ty
= ret_coercion
.borrow().expected_ty();
832 let return_expr_ty
= self.check_expr_with_hint(return_expr
, ret_ty
);
833 let mut span
= return_expr
.span
;
834 // Use the span of the trailing expression for our cause,
835 // not the span of the entire function
836 if !explicit_return
{
837 if let ExprKind
::Block(body
, _
) = return_expr
.kind
&& let Some(last_expr
) = body
.expr
{
838 span
= last_expr
.span
;
841 ret_coercion
.borrow_mut().coerce(
843 &self.cause(span
, ObligationCauseCode
::ReturnValue(return_expr
.hir_id
)),
848 if let Some(fn_sig
) = self.body_fn_sig()
849 && fn_sig
.output().has_opaque_types()
851 // Point any obligations that were registered due to opaque type
852 // inference at the return expression.
853 self.select_obligations_where_possible(|errors
| {
854 self.point_at_return_for_opaque_ty_error(errors
, span
, return_expr_ty
, return_expr
.span
);
859 fn point_at_return_for_opaque_ty_error(
861 errors
: &mut Vec
<traits
::FulfillmentError
<'tcx
>>,
863 return_expr_ty
: Ty
<'tcx
>,
866 // Don't point at the whole block if it's empty
867 if span
== return_span
{
871 let cause
= &mut err
.obligation
.cause
;
872 if let ObligationCauseCode
::OpaqueReturnType(None
) = cause
.code() {
873 let new_cause
= ObligationCause
::new(
876 ObligationCauseCode
::OpaqueReturnType(Some((return_expr_ty
, span
))),
883 pub(crate) fn check_lhs_assignable(
885 lhs
: &'tcx hir
::Expr
<'tcx
>,
886 err_code
: &'
static str,
888 adjust_err
: impl FnOnce(&mut Diagnostic
),
890 if lhs
.is_syntactic_place_expr() {
894 // FIXME: Make this use Diagnostic once error codes can be dynamically set.
895 let mut err
= self.tcx
.sess
.struct_span_err_with_code(
897 "invalid left-hand side of assignment",
898 DiagnosticId
::Error(err_code
.into()),
900 err
.span_label(lhs
.span
, "cannot assign to this expression");
902 self.comes_from_while_condition(lhs
.hir_id
, |expr
| {
903 err
.span_suggestion_verbose(
904 expr
.span
.shrink_to_lo(),
905 "you might have meant to use pattern destructuring",
907 Applicability
::MachineApplicable
,
911 adjust_err(&mut err
);
916 // Check if an expression `original_expr_id` comes from the condition of a while loop,
917 /// as opposed from the body of a while loop, which we can naively check by iterating
918 /// parents until we find a loop...
919 pub(super) fn comes_from_while_condition(
921 original_expr_id
: HirId
,
922 then
: impl FnOnce(&hir
::Expr
<'_
>),
924 let mut parent
= self.tcx
.hir().parent_id(original_expr_id
);
925 while let Some(node
) = self.tcx
.hir().find(parent
) {
927 hir
::Node
::Expr(hir
::Expr
{
934 hir
::ExprKind
::Match(expr
, ..) | hir
::ExprKind
::If(expr
, ..),
940 hir
::LoopSource
::While
,
945 // Check if our original expression is a child of the condition of a while loop
946 let expr_is_ancestor
= std
::iter
::successors(Some(original_expr_id
), |id
| {
947 self.tcx
.hir().opt_parent_id(*id
)
949 .take_while(|id
| *id
!= parent
)
950 .any(|id
| id
== expr
.hir_id
);
951 // if it is, then we have a situation like `while Some(0) = value.get(0) {`,
952 // where `while let` was more likely intended.
953 if expr_is_ancestor
{
959 | hir
::Node
::ImplItem(_
)
960 | hir
::Node
::TraitItem(_
)
961 | hir
::Node
::Crate(_
) => break,
963 parent
= self.tcx
.hir().parent_id(parent
);
969 // A generic function for checking the 'then' and 'else' clauses in an 'if'
970 // or 'if-else' expression.
973 cond_expr
: &'tcx hir
::Expr
<'tcx
>,
974 then_expr
: &'tcx hir
::Expr
<'tcx
>,
975 opt_else_expr
: Option
<&'tcx hir
::Expr
<'tcx
>>,
977 orig_expected
: Expectation
<'tcx
>,
979 let cond_ty
= self.check_expr_has_type_or_error(cond_expr
, self.tcx
.types
.bool
, |_
| {}
);
981 self.warn_if_unreachable(
984 "block in `if` or `while` expression",
987 let cond_diverges
= self.diverges
.get();
988 self.diverges
.set(Diverges
::Maybe
);
990 let expected
= orig_expected
.adjust_for_branches(self);
991 let then_ty
= self.check_expr_with_expectation(then_expr
, expected
);
992 let then_diverges
= self.diverges
.get();
993 self.diverges
.set(Diverges
::Maybe
);
995 // We've already taken the expected type's preferences
996 // into account when typing the `then` branch. To figure
997 // out the initial shot at a LUB, we thus only consider
998 // `expected` if it represents a *hard* constraint
999 // (`only_has_type`); otherwise, we just go with a
1000 // fresh type variable.
1001 let coerce_to_ty
= expected
.coercion_target_type(self, sp
);
1002 let mut coerce
: DynamicCoerceMany
<'_
> = CoerceMany
::new(coerce_to_ty
);
1004 coerce
.coerce(self, &self.misc(sp
), then_expr
, then_ty
);
1006 if let Some(else_expr
) = opt_else_expr
{
1007 let else_ty
= self.check_expr_with_expectation(else_expr
, expected
);
1008 let else_diverges
= self.diverges
.get();
1010 let opt_suggest_box_span
= self.opt_suggest_box_span(then_ty
, else_ty
, orig_expected
);
1011 let if_cause
= self.if_cause(
1018 opt_suggest_box_span
,
1021 coerce
.coerce(self, &if_cause
, else_expr
, else_ty
);
1023 // We won't diverge unless both branches do (or the condition does).
1024 self.diverges
.set(cond_diverges
| then_diverges
& else_diverges
);
1026 self.if_fallback_coercion(sp
, then_expr
, &mut coerce
);
1028 // If the condition is false we can't diverge.
1029 self.diverges
.set(cond_diverges
);
1032 let result_ty
= coerce
.complete(self);
1033 if let Err(guar
) = cond_ty
.error_reported() { self.tcx.ty_error(guar) }
else { result_ty }
1036 /// Type check assignment expression `expr` of form `lhs = rhs`.
1037 /// The expected type is `()` and is passed to the function for the purposes of diagnostics.
1038 fn check_expr_assign(
1040 expr
: &'tcx hir
::Expr
<'tcx
>,
1041 expected
: Expectation
<'tcx
>,
1042 lhs
: &'tcx hir
::Expr
<'tcx
>,
1043 rhs
: &'tcx hir
::Expr
<'tcx
>,
1046 let expected_ty
= expected
.coercion_target_type(self, expr
.span
);
1047 if expected_ty
== self.tcx
.types
.bool
{
1048 // The expected type is `bool` but this will result in `()` so we can reasonably
1049 // say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.
1050 // The likely cause of this is `if foo = bar { .. }`.
1051 let actual_ty
= self.tcx
.mk_unit();
1052 let mut err
= self.demand_suptype_diag(expr
.span
, expected_ty
, actual_ty
).unwrap();
1053 let lhs_ty
= self.check_expr(&lhs
);
1054 let rhs_ty
= self.check_expr(&rhs
);
1055 let (applicability
, eq
) = if self.can_coerce(rhs_ty
, lhs_ty
) {
1056 (Applicability
::MachineApplicable
, true)
1057 } else if let ExprKind
::Binary(
1058 Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. }
,
1063 // if x == 1 && y == 2 { .. }
1065 let actual_lhs_ty
= self.check_expr(&rhs_expr
);
1066 (Applicability
::MaybeIncorrect
, self.can_coerce(rhs_ty
, actual_lhs_ty
))
1067 } else if let ExprKind
::Binary(
1068 Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. }
,
1073 // if x == 1 && y == 2 { .. }
1075 let actual_rhs_ty
= self.check_expr(&lhs_expr
);
1076 (Applicability
::MaybeIncorrect
, self.can_coerce(actual_rhs_ty
, lhs_ty
))
1078 (Applicability
::MaybeIncorrect
, false)
1080 if !lhs
.is_syntactic_place_expr()
1081 && lhs
.is_approximately_pattern()
1082 && !matches
!(lhs
.kind
, hir
::ExprKind
::Lit(_
))
1084 // Do not suggest `if let x = y` as `==` is way more likely to be the intention.
1085 let hir
= self.tcx
.hir();
1086 if let hir
::Node
::Expr(hir
::Expr { kind: ExprKind::If { .. }
, .. }) =
1087 hir
.get_parent(hir
.parent_id(expr
.hir_id
))
1089 err
.span_suggestion_verbose(
1090 expr
.span
.shrink_to_lo(),
1091 "you might have meant to use pattern matching",
1098 err
.span_suggestion_verbose(
1099 span
.shrink_to_hi(),
1100 "you might have meant to compare for equality",
1106 // If the assignment expression itself is ill-formed, don't
1107 // bother emitting another error
1108 let reported
= err
.emit_unless(lhs_ty
.references_error() || rhs_ty
.references_error());
1109 return self.tcx
.ty_error(reported
);
1112 let lhs_ty
= self.check_expr_with_needs(&lhs
, Needs
::MutPlace
);
1114 let suggest_deref_binop
= |err
: &mut Diagnostic
, rhs_ty
: Ty
<'tcx
>| {
1115 if let Some(lhs_deref_ty
) = self.deref_once_mutably_for_diagnostic(lhs_ty
) {
1116 // Can only assign if the type is sized, so if `DerefMut` yields a type that is
1117 // unsized, do not suggest dereferencing it.
1118 let lhs_deref_ty_is_sized
= self
1120 .type_implements_trait(
1121 self.tcx
.require_lang_item(LangItem
::Sized
, None
),
1126 if lhs_deref_ty_is_sized
&& self.can_coerce(rhs_ty
, lhs_deref_ty
) {
1127 err
.span_suggestion_verbose(
1128 lhs
.span
.shrink_to_lo(),
1129 "consider dereferencing here to assign to the mutably borrowed value",
1131 Applicability
::MachineApplicable
,
1137 // This is (basically) inlined `check_expr_coercible_to_type`, but we want
1138 // to suggest an additional fixup here in `suggest_deref_binop`.
1139 let rhs_ty
= self.check_expr_with_hint(&rhs
, lhs_ty
);
1140 if let (_
, Some(mut diag
)) =
1141 self.demand_coerce_diag(rhs
, rhs_ty
, lhs_ty
, Some(lhs
), AllowTwoPhase
::No
)
1143 suggest_deref_binop(&mut diag
, rhs_ty
);
1147 self.check_lhs_assignable(lhs
, "E0070", span
, |err
| {
1148 if let Some(rhs_ty
) = self.typeck_results
.borrow().expr_ty_opt(rhs
) {
1149 suggest_deref_binop(err
, rhs_ty
);
1153 self.require_type_is_sized(lhs_ty
, lhs
.span
, traits
::AssignmentLhsSized
);
1155 if let Err(guar
) = (lhs_ty
, rhs_ty
).error_reported() {
1156 self.tcx
.ty_error(guar
)
1162 pub(super) fn check_expr_let(&self, let_expr
: &'tcx hir
::Let
<'tcx
>) -> Ty
<'tcx
> {
1163 // for let statements, this is done in check_stmt
1164 let init
= let_expr
.init
;
1165 self.warn_if_unreachable(init
.hir_id
, init
.span
, "block in `let` expression");
1166 // otherwise check exactly as a let statement
1167 self.check_decl(let_expr
.into());
1168 // but return a bool, for this is a boolean expression
1174 body
: &'tcx hir
::Block
<'tcx
>,
1175 source
: hir
::LoopSource
,
1176 expected
: Expectation
<'tcx
>,
1177 expr
: &'tcx hir
::Expr
<'tcx
>,
1179 let coerce
= match source
{
1180 // you can only use break with a value from a normal `loop { }`
1181 hir
::LoopSource
::Loop
=> {
1182 let coerce_to
= expected
.coercion_target_type(self, body
.span
);
1183 Some(CoerceMany
::new(coerce_to
))
1186 hir
::LoopSource
::While
| hir
::LoopSource
::ForLoop
=> None
,
1189 let ctxt
= BreakableCtxt
{
1191 may_break
: false, // Will get updated if/when we find a `break`.
1194 let (ctxt
, ()) = self.with_breakable_ctxt(expr
.hir_id
, ctxt
, || {
1195 self.check_block_no_value(&body
);
1199 // No way to know whether it's diverging because
1200 // of a `break` or an outer `break` or `return`.
1201 self.diverges
.set(Diverges
::Maybe
);
1204 // If we permit break with a value, then result type is
1205 // the LUB of the breaks (possibly ! if none); else, it
1206 // is nil. This makes sense because infinite loops
1207 // (which would have type !) are only possible iff we
1208 // permit break with a value [1].
1209 if ctxt
.coerce
.is_none() && !ctxt
.may_break
{
1211 self.tcx
.sess
.delay_span_bug(body
.span
, "no coercion, but loop may not break");
1213 ctxt
.coerce
.map(|c
| c
.complete(self)).unwrap_or_else(|| self.tcx
.mk_unit())
1216 /// Checks a method call.
1217 fn check_method_call(
1219 expr
: &'tcx hir
::Expr
<'tcx
>,
1220 segment
: &hir
::PathSegment
<'_
>,
1221 rcvr
: &'tcx hir
::Expr
<'tcx
>,
1222 args
: &'tcx
[hir
::Expr
<'tcx
>],
1223 expected
: Expectation
<'tcx
>,
1225 let rcvr_t
= self.check_expr(&rcvr
);
1226 // no need to check for bot/err -- callee does that
1227 let rcvr_t
= self.structurally_resolved_type(rcvr
.span
, rcvr_t
);
1228 let span
= segment
.ident
.span
;
1230 let method
= match self.lookup_method(rcvr_t
, segment
, span
, expr
, rcvr
, args
) {
1232 // We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to
1233 // trigger this codepath causing `structurally_resolved_type` to emit an error.
1235 self.write_method_call(expr
.hir_id
, method
);
1239 if segment
.ident
.name
!= kw
::Empty
{
1240 if let Some(mut err
) = self.report_method_error(
1244 SelfSource
::MethodCall(rcvr
),
1257 // Call the generic checker.
1258 self.check_method_argument_types(span
, expr
, method
, &args
, DontTupleArguments
, expected
)
1263 e
: &'tcx hir
::Expr
<'tcx
>,
1264 t
: &'tcx hir
::Ty
<'tcx
>,
1265 expr
: &'tcx hir
::Expr
<'tcx
>,
1267 // Find the type of `e`. Supply hints based on the type we are casting to,
1269 let t_cast
= self.to_ty_saving_user_provided_ty(t
);
1270 let t_cast
= self.resolve_vars_if_possible(t_cast
);
1271 let t_expr
= self.check_expr_with_expectation(e
, ExpectCastableToType(t_cast
));
1272 let t_expr
= self.resolve_vars_if_possible(t_expr
);
1274 // Eagerly check for some obvious errors.
1275 if let Err(guar
) = (t_expr
, t_cast
).error_reported() {
1276 self.tcx
.ty_error(guar
)
1278 // Defer other checks until we're done type checking.
1279 let mut deferred_cast_checks
= self.deferred_cast_checks
.borrow_mut();
1280 match cast
::CastCheck
::new(
1287 self.param_env
.constness(),
1291 "check_expr_cast: deferring cast from {:?} to {:?}: {:?}",
1292 t_cast
, t_expr
, cast_check
,
1294 deferred_cast_checks
.push(cast_check
);
1297 Err(guar
) => self.tcx
.ty_error(guar
),
1302 fn check_expr_array(
1304 args
: &'tcx
[hir
::Expr
<'tcx
>],
1305 expected
: Expectation
<'tcx
>,
1306 expr
: &'tcx hir
::Expr
<'tcx
>,
1308 let element_ty
= if !args
.is_empty() {
1309 let coerce_to
= expected
1311 .and_then(|uty
| match *uty
.kind() {
1312 ty
::Array(ty
, _
) | ty
::Slice(ty
) => Some(ty
),
1315 .unwrap_or_else(|| {
1316 self.next_ty_var(TypeVariableOrigin
{
1317 kind
: TypeVariableOriginKind
::TypeInference
,
1321 let mut coerce
= CoerceMany
::with_coercion_sites(coerce_to
, args
);
1322 assert_eq
!(self.diverges
.get(), Diverges
::Maybe
);
1324 let e_ty
= self.check_expr_with_hint(e
, coerce_to
);
1325 let cause
= self.misc(e
.span
);
1326 coerce
.coerce(self, &cause
, e
, e_ty
);
1328 coerce
.complete(self)
1330 self.next_ty_var(TypeVariableOrigin
{
1331 kind
: TypeVariableOriginKind
::TypeInference
,
1335 let array_len
= args
.len() as u64;
1336 self.suggest_array_len(expr
, array_len
);
1337 self.tcx
.mk_array(element_ty
, array_len
)
1340 fn suggest_array_len(&self, expr
: &'tcx hir
::Expr
<'tcx
>, array_len
: u64) {
1341 let parent_node
= self.tcx
.hir().parent_iter(expr
.hir_id
).find(|(_
, node
)| {
1342 !matches
!(node
, hir
::Node
::Expr(hir
::Expr { kind: hir::ExprKind::AddrOf(..), .. }
))
1345 hir
::Node
::Local(hir
::Local { ty: Some(ty), .. }
)
1346 | hir
::Node
::Item(hir
::Item { kind: hir::ItemKind::Const(ty, _), .. }
))
1347 ) = parent_node
else {
1350 if let hir
::TyKind
::Array(_
, length
) = ty
.peel_refs().kind
1351 && let hir
::ArrayLen
::Body(hir
::AnonConst { hir_id, .. }
) = length
1352 && let Some(span
) = self.tcx
.hir().opt_span(hir_id
)
1354 match self.tcx
.sess
.diagnostic().steal_diagnostic(span
, StashKey
::UnderscoreForArrayLengths
) {
1356 err
.span_suggestion(
1358 "consider specifying the array length",
1360 Applicability
::MaybeIncorrect
,
1369 fn check_expr_const_block(
1371 anon_const
: &'tcx hir
::AnonConst
,
1372 expected
: Expectation
<'tcx
>,
1373 _expr
: &'tcx hir
::Expr
<'tcx
>,
1375 let body
= self.tcx
.hir().body(anon_const
.body
);
1377 // Create a new function context.
1378 let def_id
= anon_const
.def_id
;
1379 let fcx
= FnCtxt
::new(self, self.param_env
.with_const(), def_id
);
1380 crate::GatherLocalsVisitor
::new(&fcx
).visit_body(body
);
1382 let ty
= fcx
.check_expr_with_expectation(&body
.value
, expected
);
1383 fcx
.require_type_is_sized(ty
, body
.value
.span
, traits
::ConstSized
);
1384 fcx
.write_ty(anon_const
.hir_id
, ty
);
1388 fn check_expr_repeat(
1390 element
: &'tcx hir
::Expr
<'tcx
>,
1391 count
: &'tcx hir
::ArrayLen
,
1392 expected
: Expectation
<'tcx
>,
1393 expr
: &'tcx hir
::Expr
<'tcx
>,
1396 let count
= self.array_length_to_const(count
);
1397 if let Some(count
) = count
.try_eval_target_usize(tcx
, self.param_env
) {
1398 self.suggest_array_len(expr
, count
);
1401 let uty
= match expected
{
1402 ExpectHasType(uty
) => match *uty
.kind() {
1403 ty
::Array(ty
, _
) | ty
::Slice(ty
) => Some(ty
),
1409 let (element_ty
, t
) = match uty
{
1411 self.check_expr_coercible_to_type(&element
, uty
, None
);
1415 let ty
= self.next_ty_var(TypeVariableOrigin
{
1416 kind
: TypeVariableOriginKind
::MiscVariable
,
1419 let element_ty
= self.check_expr_has_type_or_error(&element
, ty
, |_
| {}
);
1424 if let Err(guar
) = element_ty
.error_reported() {
1425 return tcx
.ty_error(guar
);
1428 self.check_repeat_element_needs_copy_bound(element
, count
, element_ty
);
1430 self.register_wf_obligation(
1431 tcx
.mk_array_with_const_len(t
, count
).into(),
1433 traits
::WellFormed(None
),
1436 tcx
.mk_array_with_const_len(t
, count
)
1439 fn check_repeat_element_needs_copy_bound(
1441 element
: &hir
::Expr
<'_
>,
1442 count
: ty
::Const
<'tcx
>,
1443 element_ty
: Ty
<'tcx
>,
1446 // Actual constants as the repeat element get inserted repeatedly instead of getting copied via Copy.
1447 match &element
.kind
{
1448 hir
::ExprKind
::ConstBlock(..) => return,
1449 hir
::ExprKind
::Path(qpath
) => {
1450 let res
= self.typeck_results
.borrow().qpath_res(qpath
, element
.hir_id
);
1451 if let Res
::Def(DefKind
::Const
| DefKind
::AssocConst
| DefKind
::AnonConst
, _
) = res
1458 // If someone calls a const fn, they can extract that call out into a separate constant (or a const
1459 // block in the future), so we check that to tell them that in the diagnostic. Does not affect typeck.
1460 let is_const_fn
= match element
.kind
{
1461 hir
::ExprKind
::Call(func
, _args
) => match *self.node_ty(func
.hir_id
).kind() {
1462 ty
::FnDef(def_id
, _
) => tcx
.is_const_fn(def_id
),
1468 // If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
1469 // don't copy that one element, we move it. Only check for Copy if the length is larger.
1470 if count
.try_eval_target_usize(tcx
, self.param_env
).map_or(true, |len
| len
> 1) {
1471 let lang_item
= self.tcx
.require_lang_item(LangItem
::Copy
, None
);
1472 let code
= traits
::ObligationCauseCode
::RepeatElementCopy { is_const_fn }
;
1473 self.require_type_meets(element_ty
, element
.span
, code
, lang_item
);
1477 fn check_expr_tuple(
1479 elts
: &'tcx
[hir
::Expr
<'tcx
>],
1480 expected
: Expectation
<'tcx
>,
1481 expr
: &'tcx hir
::Expr
<'tcx
>,
1483 let flds
= expected
.only_has_type(self).and_then(|ty
| {
1484 let ty
= self.resolve_vars_with_obligations(ty
);
1486 ty
::Tuple(flds
) => Some(&flds
[..]),
1491 let elt_ts_iter
= elts
.iter().enumerate().map(|(i
, e
)| match flds
{
1492 Some(fs
) if i
< fs
.len() => {
1494 self.check_expr_coercible_to_type(&e
, ety
, None
);
1497 _
=> self.check_expr_with_expectation(&e
, NoExpectation
),
1499 let tuple
= self.tcx
.mk_tup_from_iter(elt_ts_iter
);
1500 if let Err(guar
) = tuple
.error_reported() {
1501 self.tcx
.ty_error(guar
)
1503 self.require_type_is_sized(tuple
, expr
.span
, traits
::TupleInitializerSized
);
1508 fn check_expr_struct(
1510 expr
: &hir
::Expr
<'_
>,
1511 expected
: Expectation
<'tcx
>,
1513 fields
: &'tcx
[hir
::ExprField
<'tcx
>],
1514 base_expr
: &'tcx Option
<&'tcx hir
::Expr
<'tcx
>>,
1516 // Find the relevant variant
1517 let (variant
, adt_ty
) = match self.check_struct_path(qpath
, expr
.hir_id
) {
1520 self.check_struct_fields_on_error(fields
, base_expr
);
1521 return self.tcx
.ty_error(guar
);
1525 // Prohibit struct expressions when non-exhaustive flag is set.
1526 let adt
= adt_ty
.ty_adt_def().expect("`check_struct_path` returned non-ADT type");
1527 if !adt
.did().is_local() && variant
.is_field_list_non_exhaustive() {
1530 .emit_err(StructExprNonExhaustive { span: expr.span, what: adt.variant_descr() }
);
1533 self.check_expr_struct_fields(
1544 self.require_type_is_sized(adt_ty
, expr
.span
, traits
::StructInitializerSized
);
1548 fn check_expr_struct_fields(
1551 expected
: Expectation
<'tcx
>,
1552 expr_id
: hir
::HirId
,
1554 variant
: &'tcx ty
::VariantDef
,
1555 ast_fields
: &'tcx
[hir
::ExprField
<'tcx
>],
1556 base_expr
: &'tcx Option
<&'tcx hir
::Expr
<'tcx
>>,
1561 let expected_inputs
=
1562 self.expected_inputs_for_expected_output(span
, expected
, adt_ty
, &[adt_ty
]);
1563 let adt_ty_hint
= if let Some(expected_inputs
) = expected_inputs
{
1564 expected_inputs
.get(0).cloned().unwrap_or(adt_ty
)
1568 // re-link the regions that EIfEO can erase.
1569 self.demand_eqtype(span
, adt_ty_hint
, adt_ty
);
1571 let ty
::Adt(adt
, substs
) = adt_ty
.kind() else {
1572 span_bug
!(span
, "non-ADT passed to check_expr_struct_fields");
1574 let adt_kind
= adt
.adt_kind();
1576 let mut remaining_fields
= variant
1579 .map(|(i
, field
)| (field
.ident(tcx
).normalize_to_macros_2_0(), (i
, field
)))
1580 .collect
::<FxHashMap
<_
, _
>>();
1582 let mut seen_fields
= FxHashMap
::default();
1584 let mut error_happened
= false;
1586 // Type-check each field.
1587 for (idx
, field
) in ast_fields
.iter().enumerate() {
1588 let ident
= tcx
.adjust_ident(field
.ident
, variant
.def_id
);
1589 let field_type
= if let Some((i
, v_field
)) = remaining_fields
.remove(&ident
) {
1590 seen_fields
.insert(ident
, field
.span
);
1591 self.write_field_index(field
.hir_id
, i
);
1593 // We don't look at stability attributes on
1594 // struct-like enums (yet...), but it's definitely not
1595 // a bug to have constructed one.
1596 if adt_kind
!= AdtKind
::Enum
{
1597 tcx
.check_stability(v_field
.did
, Some(expr_id
), field
.span
, None
);
1600 self.field_ty(field
.span
, v_field
, substs
)
1602 error_happened
= true;
1603 let guar
= if let Some(prev_span
) = seen_fields
.get(&ident
) {
1604 tcx
.sess
.emit_err(FieldMultiplySpecifiedInInitializer
{
1605 span
: field
.ident
.span
,
1606 prev_span
: *prev_span
,
1610 self.report_unknown_field(
1615 adt
.variant_descr(),
1623 // Make sure to give a type to the field even if there's
1624 // an error, so we can continue type-checking.
1625 let ty
= self.check_expr_with_hint(&field
.expr
, field_type
);
1627 self.demand_coerce_diag(&field
.expr
, ty
, field_type
, None
, AllowTwoPhase
::No
);
1629 if let Some(mut diag
) = diag
{
1630 if idx
== ast_fields
.len() - 1 {
1631 if remaining_fields
.is_empty() {
1632 self.suggest_fru_from_range(field
, variant
, substs
, &mut diag
);
1635 diag
.stash(field
.span
, StashKey
::MaybeFruTypo
);
1643 // Make sure the programmer specified correct number of fields.
1644 if adt_kind
== AdtKind
::Union
{
1645 if ast_fields
.len() != 1 {
1650 "union expressions should have exactly one field",
1656 // If check_expr_struct_fields hit an error, do not attempt to populate
1657 // the fields with the base_expr. This could cause us to hit errors later
1658 // when certain fields are assumed to exist that in fact do not.
1660 if let Some(base_expr
) = base_expr
{
1661 self.check_expr(base_expr
);
1666 if let Some(base_expr
) = base_expr
{
1667 // FIXME: We are currently creating two branches here in order to maintain
1668 // consistency. But they should be merged as much as possible.
1669 let fru_tys
= if self.tcx
.features().type_changing_struct_update
{
1670 if adt
.is_struct() {
1671 // Make some fresh substitutions for our ADT type.
1672 let fresh_substs
= self.fresh_substs_for_item(base_expr
.span
, adt
.did());
1673 // We do subtyping on the FRU fields first, so we can
1674 // learn exactly what types we expect the base expr
1675 // needs constrained to be compatible with the struct
1676 // type we expect from the expectation value.
1677 let fru_tys
= variant
1681 let fru_ty
= self.normalize(
1683 self.field_ty(base_expr
.span
, f
, fresh_substs
),
1685 let ident
= self.tcx
.adjust_ident(f
.ident(self.tcx
), variant
.def_id
);
1686 if let Some(_
) = remaining_fields
.remove(&ident
) {
1687 let target_ty
= self.field_ty(base_expr
.span
, f
, substs
);
1688 let cause
= self.misc(base_expr
.span
);
1689 match self.at(&cause
, self.param_env
).sup(
1690 DefineOpaqueTypes
::No
,
1694 Ok(InferOk { obligations, value: () }
) => {
1695 self.register_predicates(obligations
)
1698 // This should never happen, since we're just subtyping the
1699 // remaining_fields, but it's fine to emit this, I guess.
1701 .report_mismatched_types(
1705 FieldMisMatch(variant
.name
, ident
.name
),
1711 self.resolve_vars_if_possible(fru_ty
)
1714 // The use of fresh substs that we have subtyped against
1715 // our base ADT type's fields allows us to guide inference
1716 // along so that, e.g.
1718 // MyStruct<'a, F1, F2, const C: usize> {
1720 // // Other fields that reference `'a`, `F2`, and `C`
1723 // let x = MyStruct {
1728 // will have the `other_struct` expression constrained to
1729 // `MyStruct<'a, _, F2, C>`, as opposed to just `_`...
1730 // This is important to allow coercions to happen in
1731 // `other_struct` itself. See `coerce-in-base-expr.rs`.
1732 let fresh_base_ty
= self.tcx
.mk_adt(*adt
, fresh_substs
);
1733 self.check_expr_has_type_or_error(
1735 self.resolve_vars_if_possible(fresh_base_ty
),
1740 // Check the base_expr, regardless of a bad expected adt_ty, so we can get
1741 // type errors on that expression, too.
1742 self.check_expr(base_expr
);
1745 .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span }
);
1749 self.check_expr_has_type_or_error(base_expr
, adt_ty
, |_
| {
1750 let base_ty
= self.typeck_results
.borrow().expr_ty(*base_expr
);
1751 let same_adt
= matches
!((adt_ty
.kind(), base_ty
.kind()),
1752 (ty
::Adt(adt
, _
), ty
::Adt(base_adt
, _
)) if adt
== base_adt
);
1753 if self.tcx
.sess
.is_nightly_build() && same_adt
{
1755 &self.tcx
.sess
.parse_sess
,
1756 sym
::type_changing_struct_update
,
1758 "type changing struct updating is experimental",
1763 match adt_ty
.kind() {
1764 ty
::Adt(adt
, substs
) if adt
.is_struct() => variant
1767 .map(|f
| self.normalize(expr_span
, f
.ty(self.tcx
, substs
)))
1772 .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span }
);
1777 self.typeck_results
.borrow_mut().fru_field_types_mut().insert(expr_id
, fru_tys
);
1778 } else if adt_kind
!= AdtKind
::Union
&& !remaining_fields
.is_empty() {
1779 debug
!(?remaining_fields
);
1780 let private_fields
: Vec
<&ty
::FieldDef
> = variant
1783 .filter(|field
| !field
.vis
.is_accessible_from(tcx
.parent_module(expr_id
), tcx
))
1786 if !private_fields
.is_empty() {
1787 self.report_private_fields(adt_ty
, span
, private_fields
, ast_fields
);
1789 self.report_missing_fields(
1801 fn check_struct_fields_on_error(
1803 fields
: &'tcx
[hir
::ExprField
<'tcx
>],
1804 base_expr
: &'tcx Option
<&'tcx hir
::Expr
<'tcx
>>,
1806 for field
in fields
{
1807 self.check_expr(&field
.expr
);
1809 if let Some(base
) = *base_expr
{
1810 self.check_expr(&base
);
1814 /// Report an error for a struct field expression when there are fields which aren't provided.
1817 /// error: missing field `you_can_use_this_field` in initializer of `foo::Foo`
1818 /// --> src/main.rs:8:5
1820 /// 8 | foo::Foo {};
1821 /// | ^^^^^^^^ missing `you_can_use_this_field`
1823 /// error: aborting due to previous error
1825 fn report_missing_fields(
1829 remaining_fields
: FxHashMap
<Ident
, (FieldIdx
, &ty
::FieldDef
)>,
1830 variant
: &'tcx ty
::VariantDef
,
1831 ast_fields
: &'tcx
[hir
::ExprField
<'tcx
>],
1832 substs
: SubstsRef
<'tcx
>,
1834 let len
= remaining_fields
.len();
1836 let mut displayable_field_names
: Vec
<&str> =
1837 remaining_fields
.keys().map(|ident
| ident
.as_str()).collect();
1838 // sorting &str primitives here, sort_unstable is ok
1839 displayable_field_names
.sort_unstable();
1841 let mut truncated_fields_error
= String
::new();
1842 let remaining_fields_names
= match &displayable_field_names
[..] {
1843 [field1
] => format
!("`{}`", field1
),
1844 [field1
, field2
] => format
!("`{field1}` and `{field2}`"),
1845 [field1
, field2
, field3
] => format
!("`{field1}`, `{field2}` and `{field3}`"),
1847 truncated_fields_error
=
1848 format
!(" and {} other field{}", len
- 3, pluralize
!(len
- 3));
1849 displayable_field_names
1852 .map(|n
| format
!("`{n}`"))
1853 .collect
::<Vec
<_
>>()
1858 let mut err
= struct_span_err
!(
1862 "missing field{} {}{} in initializer of `{}`",
1864 remaining_fields_names
,
1865 truncated_fields_error
,
1868 err
.span_label(span
, format
!("missing {remaining_fields_names}{truncated_fields_error}"));
1870 if let Some(last
) = ast_fields
.last() {
1871 self.suggest_fru_from_range(last
, variant
, substs
, &mut err
);
1877 /// If the last field is a range literal, but it isn't supposed to be, then they probably
1878 /// meant to use functional update syntax.
1879 fn suggest_fru_from_range(
1881 last_expr_field
: &hir
::ExprField
<'tcx
>,
1882 variant
: &ty
::VariantDef
,
1883 substs
: SubstsRef
<'tcx
>,
1884 err
: &mut Diagnostic
,
1886 // I don't use 'is_range_literal' because only double-sided, half-open ranges count.
1887 if let ExprKind
::Struct(
1888 QPath
::LangItem(LangItem
::Range
, ..),
1889 [range_start
, range_end
],
1891 ) = last_expr_field
.expr
.kind
1892 && let variant_field
=
1893 variant
.fields
.iter().find(|field
| field
.ident(self.tcx
) == last_expr_field
.ident
)
1894 && let range_def_id
= self.tcx
.lang_items().range_struct()
1896 .and_then(|field
| field
.ty(self.tcx
, substs
).ty_adt_def())
1897 .map(|adt
| adt
.did())
1900 // Suppress any range expr type mismatches
1901 if let Some(mut diag
) = self
1905 .steal_diagnostic(last_expr_field
.span
, StashKey
::MaybeFruTypo
)
1907 diag
.delay_as_bug();
1910 // Use a (somewhat arbitrary) filtering heuristic to avoid printing
1911 // expressions that are either too long, or have control character
1912 //such as newlines in them.
1917 .span_to_snippet(range_end
.expr
.span
)
1919 .filter(|s
| s
.len() < 25 && !s
.contains(|c
: char| c
.is_control()));
1925 .span_extend_while(range_start
.span
, |c
| c
.is_whitespace())
1926 .unwrap_or(range_start
.span
).shrink_to_hi().to(range_end
.span
);
1928 err
.subdiagnostic(TypeMismatchFruTypo
{
1929 expr_span
: range_start
.span
,
1936 /// Report an error for a struct field expression when there are invisible fields.
1939 /// error: cannot construct `Foo` with struct literal syntax due to private fields
1940 /// --> src/main.rs:8:5
1942 /// 8 | foo::Foo {};
1945 /// error: aborting due to previous error
1947 fn report_private_fields(
1951 private_fields
: Vec
<&ty
::FieldDef
>,
1952 used_fields
: &'tcx
[hir
::ExprField
<'tcx
>],
1955 self.tcx
.sess
.struct_span_err(
1958 "cannot construct `{adt_ty}` with struct literal syntax due to private fields",
1961 let (used_private_fields
, remaining_private_fields
): (
1962 Vec
<(Symbol
, Span
, bool
)>,
1963 Vec
<(Symbol
, Span
, bool
)>,
1967 match used_fields
.iter().find(|used_field
| field
.name
== used_field
.ident
.name
) {
1968 Some(used_field
) => (field
.name
, used_field
.span
, true),
1969 None
=> (field
.name
, self.tcx
.def_span(field
.did
), false),
1972 .partition(|field
| field
.2);
1973 err
.span_labels(used_private_fields
.iter().map(|(_
, span
, _
)| *span
), "private field");
1974 if !remaining_private_fields
.is_empty() {
1975 let remaining_private_fields_len
= remaining_private_fields
.len();
1976 let names
= match &remaining_private_fields
1978 .map(|(name
, _
, _
)| name
)
1979 .collect
::<Vec
<_
>>()[..]
1981 _
if remaining_private_fields_len
> 6 => String
::new(),
1982 [name
] => format
!("`{name}` "),
1983 [names @
.., last
] => {
1984 let names
= names
.iter().map(|name
| format
!("`{name}`")).collect
::<Vec
<_
>>();
1985 format
!("{} and `{last}` ", names
.join(", "))
1987 [] => unreachable
!(),
1990 "... and other private field{s} {names}that {were} not provided",
1991 s
= pluralize
!(remaining_private_fields_len
),
1992 were
= pluralize
!("was", remaining_private_fields_len
),
1998 fn report_unknown_field(
2001 variant
: &'tcx ty
::VariantDef
,
2002 field
: &hir
::ExprField
<'_
>,
2003 skip_fields
: &[hir
::ExprField
<'_
>],
2006 ) -> ErrorGuaranteed
{
2007 if variant
.is_recovered() {
2011 .delay_span_bug(expr_span
, "parser recovered but no error was emitted");
2012 self.set_tainted_by_errors(guar
);
2015 let mut err
= self.err_ctxt().type_error_struct_with_diag(
2017 |actual
| match ty
.kind() {
2018 ty
::Adt(adt
, ..) if adt
.is_enum() => struct_span_err
!(
2022 "{} `{}::{}` has no field named `{}`",
2028 _
=> struct_span_err
!(
2032 "{} `{}` has no field named `{}`",
2041 let variant_ident_span
= self.tcx
.def_ident_span(variant
.def_id
).unwrap();
2042 match variant
.ctor_kind() {
2043 Some(CtorKind
::Fn
) => match ty
.kind() {
2044 ty
::Adt(adt
, ..) if adt
.is_enum() => {
2048 "`{adt}::{variant}` defined here",
2050 variant
= variant
.name
,
2053 err
.span_label(field
.ident
.span
, "field does not exist");
2054 err
.span_suggestion_verbose(
2057 "`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax",
2059 variant
= variant
.name
,
2062 "{adt}::{variant}(/* fields */)",
2064 variant
= variant
.name
,
2066 Applicability
::HasPlaceholders
,
2070 err
.span_label(variant_ident_span
, format
!("`{adt}` defined here", adt
= ty
));
2071 err
.span_label(field
.ident
.span
, "field does not exist");
2072 err
.span_suggestion_verbose(
2075 "`{adt}` is a tuple {kind_name}, use the appropriate syntax",
2077 kind_name
= kind_name
,
2079 format
!("{adt}(/* fields */)", adt
= ty
),
2080 Applicability
::HasPlaceholders
,
2085 // prevent all specified fields from being suggested
2086 let skip_fields
= skip_fields
.iter().map(|x
| x
.ident
.name
);
2087 if let Some(field_name
) = self.suggest_field_name(
2090 skip_fields
.collect(),
2093 err
.span_suggestion(
2095 "a field with a similar name exists",
2097 Applicability
::MaybeIncorrect
,
2101 ty
::Adt(adt
, ..) => {
2105 format
!("`{}::{}` does not have this field", ty
, variant
.name
),
2110 format
!("`{ty}` does not have this field"),
2113 let available_field_names
=
2114 self.available_field_names(variant
, expr_span
);
2115 if !available_field_names
.is_empty() {
2117 "available fields are: {}",
2118 self.name_series_display(available_field_names
)
2122 _
=> bug
!("non-ADT passed to report_unknown_field"),
2130 // Return a hint about the closest match in field names
2131 fn suggest_field_name(
2133 variant
: &'tcx ty
::VariantDef
,
2136 // The span where stability will be checked
2138 ) -> Option
<Symbol
> {
2142 .filter_map(|field
| {
2143 // ignore already set fields and private fields from non-local crates
2144 // and unstable fields.
2145 if skip
.iter().any(|&x
| x
== field
.name
)
2146 || (!variant
.def_id
.is_local() && !field
.vis
.is_public())
2148 self.tcx
.eval_stability(field
.did
, None
, span
, None
),
2149 stability
::EvalResult
::Deny { .. }
2157 .collect
::<Vec
<Symbol
>>();
2159 find_best_match_for_name(&names
, field
, None
)
2162 fn available_field_names(
2164 variant
: &'tcx ty
::VariantDef
,
2167 let body_owner_hir_id
= self.tcx
.hir().local_def_id_to_hir_id(self.body_id
);
2172 let def_scope
= self
2174 .adjust_ident_and_get_scope(
2175 field
.ident(self.tcx
),
2180 field
.vis
.is_accessible_from(def_scope
, self.tcx
)
2182 self.tcx
.eval_stability(field
.did
, None
, access_span
, None
),
2183 stability
::EvalResult
::Deny { .. }
2186 .filter(|field
| !self.tcx
.is_doc_hidden(field
.did
))
2187 .map(|field
| field
.name
)
2191 fn name_series_display(&self, names
: Vec
<Symbol
>) -> String
{
2192 // dynamic limit, to never omit just one field
2193 let limit
= if names
.len() == 6 { 6 }
else { 5 }
;
2195 names
.iter().take(limit
).map(|n
| format
!("`{}`", n
)).collect
::<Vec
<_
>>().join(", ");
2196 if names
.len() > limit
{
2197 display
= format
!("{} ... and {} others", display
, names
.len() - limit
);
2202 // Check field access expressions
2205 expr
: &'tcx hir
::Expr
<'tcx
>,
2206 base
: &'tcx hir
::Expr
<'tcx
>,
2208 expected
: Expectation
<'tcx
>,
2210 debug
!("check_field(expr: {:?}, base: {:?}, field: {:?})", expr
, base
, field
);
2211 let base_ty
= self.check_expr(base
);
2212 let base_ty
= self.structurally_resolved_type(base
.span
, base_ty
);
2213 let mut private_candidate
= None
;
2214 let mut autoderef
= self.autoderef(expr
.span
, base_ty
);
2215 while let Some((deref_base_ty
, _
)) = autoderef
.next() {
2216 debug
!("deref_base_ty: {:?}", deref_base_ty
);
2217 match deref_base_ty
.kind() {
2218 ty
::Adt(base_def
, substs
) if !base_def
.is_enum() => {
2219 debug
!("struct named {:?}", deref_base_ty
);
2220 let body_hir_id
= self.tcx
.hir().local_def_id_to_hir_id(self.body_id
);
2221 let (ident
, def_scope
) =
2222 self.tcx
.adjust_ident_and_get_scope(field
, base_def
.did(), body_hir_id
);
2223 let fields
= &base_def
.non_enum_variant().fields
;
2224 if let Some((index
, field
)) = fields
2226 .find(|(_
, f
)| f
.ident(self.tcx
).normalize_to_macros_2_0() == ident
)
2228 let field_ty
= self.field_ty(expr
.span
, field
, substs
);
2229 // Save the index of all fields regardless of their visibility in case
2230 // of error recovery.
2231 self.write_field_index(expr
.hir_id
, index
);
2232 let adjustments
= self.adjust_steps(&autoderef
);
2233 if field
.vis
.is_accessible_from(def_scope
, self.tcx
) {
2234 self.apply_adjustments(base
, adjustments
);
2235 self.register_predicates(autoderef
.into_obligations());
2237 self.tcx
.check_stability(field
.did
, Some(expr
.hir_id
), expr
.span
, None
);
2240 private_candidate
= Some((adjustments
, base_def
.did()));
2244 if let Ok(index
) = field
.as_str().parse
::<usize>() {
2245 if field
.name
== sym
::integer(index
) {
2246 if let Some(&field_ty
) = tys
.get(index
) {
2247 let adjustments
= self.adjust_steps(&autoderef
);
2248 self.apply_adjustments(base
, adjustments
);
2249 self.register_predicates(autoderef
.into_obligations());
2251 self.write_field_index(expr
.hir_id
, FieldIdx
::from_usize(index
));
2260 self.structurally_resolved_type(autoderef
.span(), autoderef
.final_ty(false));
2262 if let Some((adjustments
, did
)) = private_candidate
{
2263 // (#90483) apply adjustments to avoid ExprUseVisitor from
2264 // creating erroneous projection.
2265 self.apply_adjustments(base
, adjustments
);
2266 let guar
= self.ban_private_field_access(
2271 expected
.only_has_type(self),
2273 return self.tcx().ty_error(guar
);
2276 let guar
= if field
.name
== kw
::Empty
{
2277 self.tcx
.sess
.delay_span_bug(field
.span
, "field name with no name")
2278 } else if self.method_exists(
2283 expected
.only_has_type(self),
2285 self.ban_take_value_of_method(expr
, base_ty
, field
)
2286 } else if !base_ty
.is_primitive_ty() {
2287 self.ban_nonexisting_field(field
, base
, expr
, base_ty
)
2289 let field_name
= field
.to_string();
2290 let mut err
= type_error_struct
!(
2295 "`{base_ty}` is a primitive type and therefore doesn't have fields",
2297 let is_valid_suffix
= |field
: &str| {
2298 if field
== "f32" || field
== "f64" {
2301 let mut chars
= field
.chars().peekable();
2302 match chars
.peek() {
2303 Some('e'
) | Some('E'
) => {
2305 if let Some(c
) = chars
.peek()
2306 && !c
.is_numeric() && *c
!= '
-'
&& *c
!= '
+'
2310 while let Some(c
) = chars
.peek() {
2311 if !c
.is_numeric() {
2319 let suffix
= chars
.collect
::<String
>();
2320 suffix
.is_empty() || suffix
== "f32" || suffix
== "f64"
2322 let maybe_partial_suffix
= |field
: &str| -> Option
<&str> {
2323 let first_chars
= ['f'
, 'l'
];
2325 && field
.to_lowercase().starts_with(first_chars
)
2326 && field
[1..].chars().all(|c
| c
.is_ascii_digit())
2328 if field
.to_lowercase().starts_with(['f'
]) { Some("f32") }
else { Some("f64") }
2333 if let ty
::Infer(ty
::IntVar(_
)) = base_ty
.kind()
2334 && let ExprKind
::Lit(Spanned
{
2335 node
: ast
::LitKind
::Int(_
, ast
::LitIntType
::Unsuffixed
),
2338 && !base
.span
.from_expansion()
2340 if is_valid_suffix(&field_name
) {
2341 err
.span_suggestion_verbose(
2342 field
.span
.shrink_to_lo(),
2343 "if intended to be a floating point literal, consider adding a `0` after the period",
2345 Applicability
::MaybeIncorrect
,
2347 } else if let Some(correct_suffix
) = maybe_partial_suffix(&field_name
) {
2348 err
.span_suggestion_verbose(
2350 format
!("if intended to be a floating point literal, consider adding a `0` after the period and a `{correct_suffix}` suffix"),
2351 format
!("0{correct_suffix}"),
2352 Applicability
::MaybeIncorrect
,
2359 self.tcx().ty_error(guar
)
2362 fn suggest_await_on_field_access(
2364 err
: &mut Diagnostic
,
2366 base
: &'tcx hir
::Expr
<'tcx
>,
2369 let Some(output_ty
) = self.get_impl_future_output_ty(ty
) else { return; }
;
2370 let mut add_label
= true;
2371 if let ty
::Adt(def
, _
) = output_ty
.kind() {
2372 // no field access on enum type
2378 .any(|field
| field
.ident(self.tcx
) == field_ident
)
2383 "field not available in `impl Future`, but it is available in its `Output`",
2385 err
.span_suggestion_verbose(
2386 base
.span
.shrink_to_hi(),
2387 "consider `await`ing on the `Future` and access the field of its `Output`",
2389 Applicability
::MaybeIncorrect
,
2395 err
.span_label(field_ident
.span
, format
!("field not found in `{ty}`"));
2399 fn ban_nonexisting_field(
2402 base
: &'tcx hir
::Expr
<'tcx
>,
2403 expr
: &'tcx hir
::Expr
<'tcx
>,
2405 ) -> ErrorGuaranteed
{
2407 "ban_nonexisting_field: field={:?}, base={:?}, expr={:?}, base_ty={:?}",
2408 ident
, base
, expr
, base_ty
2410 let mut err
= self.no_such_field_err(ident
, base_ty
, base
.hir_id
);
2412 match *base_ty
.peel_refs().kind() {
2413 ty
::Array(_
, len
) => {
2414 self.maybe_suggest_array_indexing(&mut err
, expr
, base
, ident
, len
);
2417 self.suggest_first_deref_field(&mut err
, expr
, base
, ident
);
2419 ty
::Adt(def
, _
) if !def
.is_enum() => {
2420 self.suggest_fields_on_recordish(&mut err
, def
, ident
, expr
.span
);
2422 ty
::Param(param_ty
) => {
2423 self.point_at_param_definition(&mut err
, param_ty
);
2425 ty
::Alias(ty
::Opaque
, _
) => {
2426 self.suggest_await_on_field_access(&mut err
, ident
, base
, base_ty
.peel_refs());
2431 self.suggest_fn_call(&mut err
, base
, base_ty
, |output_ty
| {
2432 if let ty
::Adt(def
, _
) = output_ty
.kind() && !def
.is_enum() {
2433 def
.non_enum_variant().fields
.iter().any(|field
| {
2434 field
.ident(self.tcx
) == ident
2435 && field
.vis
.is_accessible_from(expr
.hir_id
.owner
.def_id
, self.tcx
)
2437 } else if let ty
::Tuple(tys
) = output_ty
.kind()
2438 && let Ok(idx
) = ident
.as_str().parse
::<usize>()
2446 if ident
.name
== kw
::Await
{
2447 // We know by construction that `<expr>.await` is either on Rust 2015
2448 // or results in `ExprKind::Await`. Suggest switching the edition to 2018.
2449 err
.note("to `.await` a `Future`, switch to Rust 2018 or later");
2450 HelpUseLatestEdition
::new().add_to_diagnostic(&mut err
);
2456 fn ban_private_field_access(
2458 expr
: &hir
::Expr
<'tcx
>,
2462 return_ty
: Option
<Ty
<'tcx
>>,
2463 ) -> ErrorGuaranteed
{
2464 let mut err
= self.private_field_err(field
, base_did
);
2466 // Also check if an accessible method exists, which is often what is meant.
2467 if self.method_exists(field
, expr_t
, expr
.hir_id
, false, return_ty
)
2468 && !self.expr_in_place(expr
.hir_id
)
2470 self.suggest_method_call(
2472 format
!("a method `{field}` also exists, call it with parentheses"),
2482 fn ban_take_value_of_method(
2484 expr
: &hir
::Expr
<'tcx
>,
2487 ) -> ErrorGuaranteed
{
2488 let mut err
= type_error_struct
!(
2493 "attempted to take value of method `{field}` on type `{expr_t}`",
2495 err
.span_label(field
.span
, "method, not a field");
2497 if let hir
::Node
::Expr(hir
::Expr { kind: ExprKind::Call(callee, _args), .. }
) =
2498 self.tcx
.hir().get_parent(expr
.hir_id
)
2500 expr
.hir_id
== callee
.hir_id
2505 self.tcx
.sess
.source_map().span_to_snippet(expr
.span
).unwrap_or_default();
2506 let is_wrapped
= expr_snippet
.starts_with('
('
) && expr_snippet
.ends_with('
)'
);
2507 let after_open
= expr
.span
.lo() + rustc_span
::BytePos(1);
2508 let before_close
= expr
.span
.hi() - rustc_span
::BytePos(1);
2510 if expr_is_call
&& is_wrapped
{
2511 err
.multipart_suggestion(
2512 "remove wrapping parentheses to call the method",
2514 (expr
.span
.with_hi(after_open
), String
::new()),
2515 (expr
.span
.with_lo(before_close
), String
::new()),
2517 Applicability
::MachineApplicable
,
2519 } else if !self.expr_in_place(expr
.hir_id
) {
2520 // Suggest call parentheses inside the wrapping parentheses
2521 let span
= if is_wrapped
{
2522 expr
.span
.with_lo(after_open
).with_hi(before_close
)
2526 self.suggest_method_call(
2528 "use parentheses to call the method",
2534 } else if let ty
::RawPtr(ty_and_mut
) = expr_t
.kind()
2535 && let ty
::Adt(adt_def
, _
) = ty_and_mut
.ty
.kind()
2536 && let ExprKind
::Field(base_expr
, _
) = expr
.kind
2537 && adt_def
.variants().len() == 1
2545 .any(|f
| f
.ident(self.tcx
) == field
)
2547 err
.multipart_suggestion(
2548 "to access the field, dereference first",
2550 (base_expr
.span
.shrink_to_lo(), "(*".to_string()),
2551 (base_expr
.span
.shrink_to_hi(), ")".to_string()),
2553 Applicability
::MaybeIncorrect
,
2556 err
.help("methods are immutable and cannot be assigned to");
2562 fn point_at_param_definition(&self, err
: &mut Diagnostic
, param
: ty
::ParamTy
) {
2563 let generics
= self.tcx
.generics_of(self.body_id
);
2564 let generic_param
= generics
.type_param(¶m
, self.tcx
);
2565 if let ty
::GenericParamDefKind
::Type { synthetic: true, .. }
= generic_param
.kind
{
2568 let param_def_id
= generic_param
.def_id
;
2569 let param_hir_id
= match param_def_id
.as_local() {
2570 Some(x
) => self.tcx
.hir().local_def_id_to_hir_id(x
),
2573 let param_span
= self.tcx
.hir().span(param_hir_id
);
2574 let param_name
= self.tcx
.hir().ty_param_name(param_def_id
.expect_local());
2576 err
.span_label(param_span
, format
!("type parameter '{param_name}' declared here"));
2579 fn suggest_fields_on_recordish(
2581 err
: &mut Diagnostic
,
2582 def
: ty
::AdtDef
<'tcx
>,
2586 if let Some(suggested_field_name
) =
2587 self.suggest_field_name(def
.non_enum_variant(), field
.name
, vec
![], access_span
)
2589 err
.span_suggestion(
2591 "a field with a similar name exists",
2592 suggested_field_name
,
2593 Applicability
::MaybeIncorrect
,
2596 err
.span_label(field
.span
, "unknown field");
2597 let struct_variant_def
= def
.non_enum_variant();
2598 let field_names
= self.available_field_names(struct_variant_def
, access_span
);
2599 if !field_names
.is_empty() {
2601 "available fields are: {}",
2602 self.name_series_display(field_names
),
2608 fn maybe_suggest_array_indexing(
2610 err
: &mut Diagnostic
,
2611 expr
: &hir
::Expr
<'_
>,
2612 base
: &hir
::Expr
<'_
>,
2614 len
: ty
::Const
<'tcx
>,
2616 if let (Some(len
), Ok(user_index
)) =
2617 (len
.try_eval_target_usize(self.tcx
, self.param_env
), field
.as_str().parse
::<u64>())
2618 && let Ok(base
) = self.tcx
.sess
.source_map().span_to_snippet(base
.span
)
2620 let help
= "instead of using tuple indexing, use array indexing";
2621 let suggestion
= format
!("{base}[{field}]");
2622 let applicability
= if len
< user_index
{
2623 Applicability
::MachineApplicable
2625 Applicability
::MaybeIncorrect
2627 err
.span_suggestion(expr
.span
, help
, suggestion
, applicability
);
2631 fn suggest_first_deref_field(
2633 err
: &mut Diagnostic
,
2634 expr
: &hir
::Expr
<'_
>,
2635 base
: &hir
::Expr
<'_
>,
2638 if let Ok(base
) = self.tcx
.sess
.source_map().span_to_snippet(base
.span
) {
2639 let msg
= format
!("`{base}` is a raw pointer; try dereferencing it");
2640 let suggestion
= format
!("(*{base}).{field}");
2641 err
.span_suggestion(expr
.span
, msg
, suggestion
, Applicability
::MaybeIncorrect
);
2645 fn no_such_field_err(
2650 ) -> DiagnosticBuilder
<'_
, ErrorGuaranteed
> {
2651 let span
= field
.span
;
2652 debug
!("no_such_field_err(span: {:?}, field: {:?}, expr_t: {:?})", span
, field
, expr_t
);
2654 let mut err
= type_error_struct
!(
2659 "no field `{field}` on type `{expr_t}`",
2662 // try to add a suggestion in case the field is a nested field of a field of the Adt
2663 let mod_id
= self.tcx
.parent_module(id
).to_def_id();
2664 if let Some((fields
, substs
)) =
2665 self.get_field_candidates_considering_privacy(span
, expr_t
, mod_id
)
2667 let candidate_fields
: Vec
<_
> = fields
2668 .filter_map(|candidate_field
| {
2669 self.check_for_nested_field_satisfying(
2671 &|candidate_field
, _
| candidate_field
.ident(self.tcx()) == field
,
2678 .map(|mut field_path
| {
2682 .map(|id
| id
.name
.to_ident_string())
2683 .collect
::<Vec
<String
>>()
2686 .collect
::<Vec
<_
>>();
2688 let len
= candidate_fields
.len();
2690 err
.span_suggestions(
2691 field
.span
.shrink_to_lo(),
2693 "{} of the expressions' fields {} a field of the same name",
2694 if len
> 1 { "some" }
else { "one" }
,
2695 if len
> 1 { "have" }
else { "has" }
,
2697 candidate_fields
.iter().map(|path
| format
!("{path}.")),
2698 Applicability
::MaybeIncorrect
,
2705 fn private_field_err(
2709 ) -> DiagnosticBuilder
<'_
, ErrorGuaranteed
> {
2710 let struct_path
= self.tcx().def_path_str(base_did
);
2711 let kind_name
= self.tcx().def_descr(base_did
);
2712 let mut err
= struct_span_err
!(
2716 "field `{field}` of {kind_name} `{struct_path}` is private",
2718 err
.span_label(field
.span
, "private field");
2723 pub(crate) fn get_field_candidates_considering_privacy(
2728 ) -> Option
<(impl Iterator
<Item
= &'tcx ty
::FieldDef
> + 'tcx
, SubstsRef
<'tcx
>)> {
2729 debug
!("get_field_candidates(span: {:?}, base_t: {:?}", span
, base_ty
);
2731 for (base_t
, _
) in self.autoderef(span
, base_ty
) {
2732 match base_t
.kind() {
2733 ty
::Adt(base_def
, substs
) if !base_def
.is_enum() => {
2735 let fields
= &base_def
.non_enum_variant().fields
;
2736 // Some struct, e.g. some that impl `Deref`, have all private fields
2737 // because you're expected to deref them to access the _real_ fields.
2738 // This, for example, will help us suggest accessing a field through a `Box<T>`.
2739 if fields
.iter().all(|field
| !field
.vis
.is_accessible_from(mod_id
, tcx
)) {
2745 .filter(move |field
| field
.vis
.is_accessible_from(mod_id
, tcx
))
2746 // For compile-time reasons put a limit on number of fields we search
2757 /// This method is called after we have encountered a missing field error to recursively
2758 /// search for the field
2759 pub(crate) fn check_for_nested_field_satisfying(
2762 matches
: &impl Fn(&ty
::FieldDef
, Ty
<'tcx
>) -> bool
,
2763 candidate_field
: &ty
::FieldDef
,
2764 subst
: SubstsRef
<'tcx
>,
2765 mut field_path
: Vec
<Ident
>,
2767 ) -> Option
<Vec
<Ident
>> {
2769 "check_for_nested_field_satisfying(span: {:?}, candidate_field: {:?}, field_path: {:?}",
2770 span
, candidate_field
, field_path
2773 if field_path
.len() > 3 {
2774 // For compile-time reasons and to avoid infinite recursion we only check for fields
2775 // up to a depth of three
2778 field_path
.push(candidate_field
.ident(self.tcx
).normalize_to_macros_2_0());
2779 let field_ty
= candidate_field
.ty(self.tcx
, subst
);
2780 if matches(candidate_field
, field_ty
) {
2781 return Some(field_path
);
2782 } else if let Some((nested_fields
, subst
)) =
2783 self.get_field_candidates_considering_privacy(span
, field_ty
, mod_id
)
2785 // recursively search fields of `candidate_field` if it's a ty::Adt
2786 for field
in nested_fields
{
2787 if let Some(field_path
) = self.check_for_nested_field_satisfying(
2795 return Some(field_path
);
2803 fn check_expr_index(
2805 base
: &'tcx hir
::Expr
<'tcx
>,
2806 idx
: &'tcx hir
::Expr
<'tcx
>,
2807 expr
: &'tcx hir
::Expr
<'tcx
>,
2809 let base_t
= self.check_expr(&base
);
2810 let idx_t
= self.check_expr(&idx
);
2812 if base_t
.references_error() {
2814 } else if idx_t
.references_error() {
2817 let base_t
= self.structurally_resolved_type(base
.span
, base_t
);
2818 match self.lookup_indexing(expr
, base
, base_t
, idx
, idx_t
) {
2819 Some((index_ty
, element_ty
)) => {
2820 // two-phase not needed because index_ty is never mutable
2821 self.demand_coerce(idx
, idx_t
, index_ty
, None
, AllowTwoPhase
::No
);
2822 self.select_obligations_where_possible(|errors
| {
2823 self.point_at_index_if_possible(errors
, idx
.span
)
2828 // Attempt to *shallowly* search for an impl which matches,
2829 // but has nested obligations which are unsatisfied.
2830 for (base_t
, _
) in self.autoderef(base
.span
, base_t
).silence_errors() {
2831 if let Some((_
, index_ty
, element_ty
)) =
2832 self.find_and_report_unsatisfied_index_impl(base
, base_t
)
2834 self.demand_coerce(idx
, idx_t
, index_ty
, None
, AllowTwoPhase
::No
);
2839 let mut err
= type_error_struct
!(
2844 "cannot index into a value of type `{base_t}`",
2846 // Try to give some advice about indexing tuples.
2847 if let ty
::Tuple(types
) = base_t
.kind() {
2848 let mut needs_note
= true;
2849 // If the index is an integer, we can show the actual
2850 // fixed expression:
2851 if let ExprKind
::Lit(ref lit
) = idx
.kind
2852 && let ast
::LitKind
::Int(i
, ast
::LitIntType
::Unsuffixed
) = lit
.node
2853 && i
< types
.len().try_into().expect("expected tuple index to be < usize length")
2855 let snip
= self.tcx
.sess
.source_map().span_to_snippet(base
.span
);
2856 if let Ok(snip
) = snip
{
2857 err
.span_suggestion(
2859 "to access tuple elements, use",
2860 format
!("{snip}.{i}"),
2861 Applicability
::MachineApplicable
,
2865 } else if let ExprKind
::Path(..) = idx
.peel_borrows().kind
{
2866 err
.span_label(idx
.span
, "cannot access tuple elements at a variable index");
2870 "to access tuple elements, use tuple indexing \
2871 syntax (e.g., `tuple.0`)",
2875 let reported
= err
.emit();
2876 self.tcx
.ty_error(reported
)
2882 /// Try to match an implementation of `Index` against a self type, and report
2883 /// the unsatisfied predicates that result from confirming this impl.
2885 /// Given an index expression, sometimes the `Self` type shallowly but does not
2886 /// deeply satisfy an impl predicate. Instead of simply saying that the type
2887 /// does not support being indexed, we want to point out exactly what nested
2888 /// predicates cause this to be, so that the user can add them to fix their code.
2889 fn find_and_report_unsatisfied_index_impl(
2891 base_expr
: &hir
::Expr
<'_
>,
2893 ) -> Option
<(ErrorGuaranteed
, Ty
<'tcx
>, Ty
<'tcx
>)> {
2894 let index_trait_def_id
= self.tcx
.lang_items().index_trait()?
;
2895 let index_trait_output_def_id
= self.tcx
.get_diagnostic_item(sym
::IndexOutput
)?
;
2897 let mut relevant_impls
= vec
![];
2898 self.tcx
.for_each_relevant_impl(index_trait_def_id
, base_ty
, |impl_def_id
| {
2899 relevant_impls
.push(impl_def_id
);
2901 let [impl_def_id
] = relevant_impls
[..] else {
2902 // Only report unsatisfied impl predicates if there's one impl
2906 self.commit_if_ok(|_
| {
2907 let ocx
= ObligationCtxt
::new_in_snapshot(self);
2908 let impl_substs
= self.fresh_substs_for_item(base_expr
.span
, impl_def_id
);
2909 let impl_trait_ref
=
2910 self.tcx
.impl_trait_ref(impl_def_id
).unwrap().subst(self.tcx
, impl_substs
);
2911 let cause
= self.misc(base_expr
.span
);
2913 // Match the impl self type against the base ty. If this fails,
2914 // we just skip this impl, since it's not particularly useful.
2915 let impl_trait_ref
= ocx
.normalize(&cause
, self.param_env
, impl_trait_ref
);
2916 ocx
.eq(&cause
, self.param_env
, impl_trait_ref
.self_ty(), base_ty
)?
;
2918 // Register the impl's predicates. One of these predicates
2919 // must be unsatisfied, or else we wouldn't have gotten here
2920 // in the first place.
2921 ocx
.register_obligations(traits
::predicates_for_generics(
2923 cause
.clone().derived_cause(
2924 ty
::Binder
::dummy(ty
::TraitPredicate
{
2925 trait_ref
: impl_trait_ref
,
2926 polarity
: ty
::ImplPolarity
::Positive
,
2927 constness
: ty
::BoundConstness
::NotConst
,
2930 traits
::ImplDerivedObligation(Box
::new(
2931 traits
::ImplDerivedObligationCause
{
2933 impl_or_alias_def_id
: impl_def_id
,
2934 impl_def_predicate_index
: Some(idx
),
2942 self.tcx
.predicates_of(impl_def_id
).instantiate(self.tcx
, impl_substs
),
2945 // Normalize the output type, which we can use later on as the
2946 // return type of the index expression...
2947 let element_ty
= ocx
.normalize(
2950 self.tcx
.mk_projection(index_trait_output_def_id
, impl_trait_ref
.substs
),
2953 let errors
= ocx
.select_where_possible();
2954 // There should be at least one error reported. If not, we
2955 // will still delay a span bug in `report_fulfillment_errors`.
2956 Ok
::<_
, NoSolution
>((
2957 self.err_ctxt().report_fulfillment_errors(&errors
),
2958 impl_trait_ref
.substs
.type_at(1),
2965 fn point_at_index_if_possible(
2967 errors
: &mut Vec
<traits
::FulfillmentError
<'tcx
>>,
2970 for error
in errors
{
2971 match error
.obligation
.predicate
.kind().skip_binder() {
2972 ty
::PredicateKind
::Clause(ty
::Clause
::Trait(predicate
))
2973 if self.tcx
.is_diagnostic_item(sym
::SliceIndex
, predicate
.trait_ref
.def_id
) => {
2977 error
.obligation
.cause
.span
= span
;
2981 fn check_expr_yield(
2983 value
: &'tcx hir
::Expr
<'tcx
>,
2984 expr
: &'tcx hir
::Expr
<'tcx
>,
2985 src
: &'tcx hir
::YieldSource
,
2987 match self.resume_yield_tys
{
2988 Some((resume_ty
, yield_ty
)) => {
2989 self.check_expr_coercible_to_type(&value
, yield_ty
, None
);
2993 // Given that this `yield` expression was generated as a result of lowering a `.await`,
2994 // we know that the yield type must be `()`; however, the context won't contain this
2995 // information. Hence, we check the source of the yield expression here and check its
2996 // value's type against `()` (this check should always hold).
2997 None
if src
.is_await() => {
2998 self.check_expr_coercible_to_type(&value
, self.tcx
.mk_unit(), None
);
3002 self.tcx
.sess
.emit_err(YieldExprOutsideOfGenerator { span: expr.span }
);
3003 // Avoid expressions without types during writeback (#78653).
3004 self.check_expr(value
);
3010 fn check_expr_asm_operand(&self, expr
: &'tcx hir
::Expr
<'tcx
>, is_input
: bool
) {
3011 let needs
= if is_input { Needs::None }
else { Needs::MutPlace }
;
3012 let ty
= self.check_expr_with_needs(expr
, needs
);
3013 self.require_type_is_sized(ty
, expr
.span
, traits
::InlineAsmSized
);
3015 if !is_input
&& !expr
.is_syntactic_place_expr() {
3016 let mut err
= self.tcx
.sess
.struct_span_err(expr
.span
, "invalid asm output");
3017 err
.span_label(expr
.span
, "cannot assign to this expression");
3021 // If this is an input value, we require its type to be fully resolved
3022 // at this point. This allows us to provide helpful coercions which help
3023 // pass the type candidate list in a later pass.
3025 // We don't require output types to be resolved at this point, which
3026 // allows them to be inferred based on how they are used later in the
3029 let ty
= self.structurally_resolved_type(expr
.span
, ty
);
3032 let fnptr_ty
= self.tcx
.mk_fn_ptr(ty
.fn_sig(self.tcx
));
3033 self.demand_coerce(expr
, ty
, fnptr_ty
, None
, AllowTwoPhase
::No
);
3035 ty
::Ref(_
, base_ty
, mutbl
) => {
3036 let ptr_ty
= self.tcx
.mk_ptr(ty
::TypeAndMut { ty: base_ty, mutbl }
);
3037 self.demand_coerce(expr
, ty
, ptr_ty
, None
, AllowTwoPhase
::No
);
3044 fn check_expr_asm(&self, asm
: &'tcx hir
::InlineAsm
<'tcx
>) -> Ty
<'tcx
> {
3045 for (op
, _op_sp
) in asm
.operands
{
3047 hir
::InlineAsmOperand
::In { expr, .. }
=> {
3048 self.check_expr_asm_operand(expr
, true);
3050 hir
::InlineAsmOperand
::Out { expr: Some(expr), .. }
3051 | hir
::InlineAsmOperand
::InOut { expr, .. }
=> {
3052 self.check_expr_asm_operand(expr
, false);
3054 hir
::InlineAsmOperand
::Out { expr: None, .. }
=> {}
3055 hir
::InlineAsmOperand
::SplitInOut { in_expr, out_expr, .. }
=> {
3056 self.check_expr_asm_operand(in_expr
, true);
3057 if let Some(out_expr
) = out_expr
{
3058 self.check_expr_asm_operand(out_expr
, false);
3061 // `AnonConst`s have their own body and is type-checked separately.
3062 // As they don't flow into the type system we don't need them to
3064 hir
::InlineAsmOperand
::Const { .. }
| hir
::InlineAsmOperand
::SymFn { .. }
=> {}
3065 hir
::InlineAsmOperand
::SymStatic { .. }
=> {}
3068 if asm
.options
.contains(ast
::InlineAsmOptions
::NORETURN
) {
3069 self.tcx
.types
.never
3077 container
: &'tcx hir
::Ty
<'tcx
>,
3079 expr
: &'tcx hir
::Expr
<'tcx
>,
3081 let container
= self.to_ty(container
).normalized
;
3083 let mut field_indices
= Vec
::with_capacity(fields
.len());
3084 let mut current_container
= container
;
3086 for &field
in fields
{
3087 let container
= self.structurally_resolved_type(expr
.span
, current_container
);
3089 match container
.kind() {
3090 ty
::Adt(container_def
, substs
) if !container_def
.is_enum() => {
3091 let block
= self.tcx
.hir().local_def_id_to_hir_id(self.body_id
);
3092 let (ident
, def_scope
) =
3093 self.tcx
.adjust_ident_and_get_scope(field
, container_def
.did(), block
);
3095 let fields
= &container_def
.non_enum_variant().fields
;
3096 if let Some((index
, field
)) = fields
3098 .find(|(_
, f
)| f
.ident(self.tcx
).normalize_to_macros_2_0() == ident
)
3100 let field_ty
= self.field_ty(expr
.span
, field
, substs
);
3102 // FIXME: DSTs with static alignment should be allowed
3103 self.require_type_is_sized(field_ty
, expr
.span
, traits
::MiscObligation
);
3105 if field
.vis
.is_accessible_from(def_scope
, self.tcx
) {
3106 self.tcx
.check_stability(field
.did
, Some(expr
.hir_id
), expr
.span
, None
);
3108 self.private_field_err(ident
, container_def
.did()).emit();
3111 // Save the index of all fields regardless of their visibility in case
3112 // of error recovery.
3113 field_indices
.push(index
);
3114 current_container
= field_ty
;
3120 let fstr
= field
.as_str();
3122 if let Ok(index
) = fstr
.parse
::<usize>() {
3123 if fstr
== index
.to_string() {
3124 if let Some(&field_ty
) = tys
.get(index
) {
3125 field_indices
.push(index
.into());
3126 current_container
= field_ty
;
3136 self.no_such_field_err(field
, container
, expr
.hir_id
).emit();
3143 .offset_of_data_mut()
3144 .insert(expr
.hir_id
, (container
, field_indices
));
3146 self.tcx
.types
.usize