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
::{probe, MethodError, SelfSource}
;
10 use crate::check
::report_unexpected_variant_res
;
11 use crate::check
::BreakableCtxt
;
12 use crate::check
::Diverges
;
13 use crate::check
::Expectation
::{self, ExpectCastableToType, ExpectHasType, NoExpectation}
;
14 use crate::check
::FnCtxt
;
15 use crate::check
::Needs
;
16 use crate::check
::TupleArgumentsFlag
::DontTupleArguments
;
17 use crate::type_error_struct
;
20 use rustc_ast
::util
::lev_distance
::find_best_match_for_name
;
21 use rustc_data_structures
::fx
::FxHashMap
;
22 use rustc_errors
::ErrorReported
;
23 use rustc_errors
::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId}
;
25 use rustc_hir
::def
::{CtorKind, DefKind, Res}
;
26 use rustc_hir
::def_id
::DefId
;
27 use rustc_hir
::lang_items
;
28 use rustc_hir
::{ExprKind, QPath}
;
29 use rustc_infer
::infer
;
30 use rustc_infer
::infer
::type_variable
::{TypeVariableOrigin, TypeVariableOriginKind}
;
32 use rustc_middle
::ty
::adjustment
::{
33 Adjust
, Adjustment
, AllowTwoPhase
, AutoBorrow
, AutoBorrowMutability
,
35 use rustc_middle
::ty
::Ty
;
36 use rustc_middle
::ty
::TypeFoldable
;
37 use rustc_middle
::ty
::{AdtKind, Visibility}
;
38 use rustc_span
::hygiene
::DesugaringKind
;
39 use rustc_span
::source_map
::Span
;
40 use rustc_span
::symbol
::{kw, sym, Symbol}
;
41 use rustc_trait_selection
::traits
::{self, ObligationCauseCode}
;
43 use std
::fmt
::Display
;
45 impl<'a
, 'tcx
> FnCtxt
<'a
, 'tcx
> {
46 fn check_expr_eq_type(&self, expr
: &'tcx hir
::Expr
<'tcx
>, expected
: Ty
<'tcx
>) {
47 let ty
= self.check_expr_with_hint(expr
, expected
);
48 self.demand_eqtype(expr
.span
, expected
, ty
);
51 pub fn check_expr_has_type_or_error(
53 expr
: &'tcx hir
::Expr
<'tcx
>,
55 extend_err
: impl Fn(&mut DiagnosticBuilder
<'_
>),
57 self.check_expr_meets_expectation_or_error(expr
, ExpectHasType(expected
), extend_err
)
60 fn check_expr_meets_expectation_or_error(
62 expr
: &'tcx hir
::Expr
<'tcx
>,
63 expected
: Expectation
<'tcx
>,
64 extend_err
: impl Fn(&mut DiagnosticBuilder
<'_
>),
66 let expected_ty
= expected
.to_option(&self).unwrap_or(self.tcx
.types
.bool
);
67 let mut ty
= self.check_expr_with_expectation(expr
, expected
);
69 // While we don't allow *arbitrary* coercions here, we *do* allow
70 // coercions from ! to `expected`.
73 !self.tables
.borrow().adjustments().contains_key(expr
.hir_id
),
74 "expression with never type wound up being adjusted"
76 let adj_ty
= self.next_diverging_ty_var(TypeVariableOrigin
{
77 kind
: TypeVariableOriginKind
::AdjustmentType
,
80 self.apply_adjustments(
82 vec
![Adjustment { kind: Adjust::NeverToAny, target: adj_ty }
],
87 if let Some(mut err
) = self.demand_suptype_diag(expr
.span
, expected_ty
, ty
) {
88 let expr
= expr
.peel_drop_temps();
89 self.suggest_ref_or_into(&mut err
, expr
, expected_ty
, ty
);
91 // Error possibly reported in `check_assign` so avoid emitting error again.
92 err
.emit_unless(self.is_assign_to_bool(expr
, expected_ty
));
97 pub(super) fn check_expr_coercable_to_type(
99 expr
: &'tcx hir
::Expr
<'tcx
>,
102 let ty
= self.check_expr_with_hint(expr
, expected
);
103 // checks don't need two phase
104 self.demand_coerce(expr
, ty
, expected
, AllowTwoPhase
::No
)
107 pub(super) fn check_expr_with_hint(
109 expr
: &'tcx hir
::Expr
<'tcx
>,
112 self.check_expr_with_expectation(expr
, ExpectHasType(expected
))
115 pub(super) fn check_expr_with_expectation(
117 expr
: &'tcx hir
::Expr
<'tcx
>,
118 expected
: Expectation
<'tcx
>,
120 self.check_expr_with_expectation_and_needs(expr
, expected
, Needs
::None
)
123 pub(super) fn check_expr(&self, expr
: &'tcx hir
::Expr
<'tcx
>) -> Ty
<'tcx
> {
124 self.check_expr_with_expectation(expr
, NoExpectation
)
127 pub(super) fn check_expr_with_needs(
129 expr
: &'tcx hir
::Expr
<'tcx
>,
132 self.check_expr_with_expectation_and_needs(expr
, NoExpectation
, needs
)
136 /// If an expression has any sub-expressions that result in a type error,
137 /// inspecting that expression's type with `ty.references_error()` will return
138 /// true. Likewise, if an expression is known to diverge, inspecting its
139 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
140 /// strict, _|_ can appear in the type of an expression that does not,
141 /// itself, diverge: for example, fn() -> _|_.)
142 /// Note that inspecting a type's structure *directly* may expose the fact
143 /// that there are actually multiple representations for `Error`, so avoid
144 /// that when err needs to be handled differently.
145 fn check_expr_with_expectation_and_needs(
147 expr
: &'tcx hir
::Expr
<'tcx
>,
148 expected
: Expectation
<'tcx
>,
151 debug
!(">> type-checking: expr={:?} expected={:?}", expr
, expected
);
153 // True if `expr` is a `Try::from_ok(())` that is a result of desugaring a try block
154 // without the final expr (e.g. `try { return; }`). We don't want to generate an
155 // unreachable_code lint for it since warnings for autogenerated code are confusing.
156 let is_try_block_generated_unit_expr
= match expr
.kind
{
157 ExprKind
::Call(_
, ref args
) if expr
.span
.is_desugaring(DesugaringKind
::TryBlock
) => {
158 args
.len() == 1 && args
[0].span
.is_desugaring(DesugaringKind
::TryBlock
)
164 // Warn for expressions after diverging siblings.
165 if !is_try_block_generated_unit_expr
{
166 self.warn_if_unreachable(expr
.hir_id
, expr
.span
, "expression");
169 // Hide the outer diverging and has_errors flags.
170 let old_diverges
= self.diverges
.replace(Diverges
::Maybe
);
171 let old_has_errors
= self.has_errors
.replace(false);
173 let ty
= self.check_expr_kind(expr
, expected
, needs
);
175 // Warn for non-block expressions with diverging children.
177 ExprKind
::Block(..) | ExprKind
::Loop(..) | ExprKind
::Match(..) => {}
178 // If `expr` is a result of desugaring the try block and is an ok-wrapped
179 // diverging expression (e.g. it arose from desugaring of `try { return }`),
180 // we skip issuing a warning because it is autogenerated code.
181 ExprKind
::Call(..) if expr
.span
.is_desugaring(DesugaringKind
::TryBlock
) => {}
182 ExprKind
::Call(ref callee
, _
) => {
183 self.warn_if_unreachable(expr
.hir_id
, callee
.span
, "call")
185 ExprKind
::MethodCall(_
, ref span
, _
) => {
186 self.warn_if_unreachable(expr
.hir_id
, *span
, "call")
188 _
=> self.warn_if_unreachable(expr
.hir_id
, expr
.span
, "expression"),
191 // Any expression that produces a value of type `!` must have diverged
193 self.diverges
.set(self.diverges
.get() | Diverges
::always(expr
.span
));
196 // Record the type, which applies it effects.
197 // We need to do this after the warning above, so that
198 // we don't warn for the diverging expression itself.
199 self.write_ty(expr
.hir_id
, ty
);
201 // Combine the diverging and has_error flags.
202 self.diverges
.set(self.diverges
.get() | old_diverges
);
203 self.has_errors
.set(self.has_errors
.get() | old_has_errors
);
205 debug
!("type of {} is...", self.tcx
.hir().node_to_string(expr
.hir_id
));
206 debug
!("... {:?}, expected is {:?}", ty
, expected
);
213 expr
: &'tcx hir
::Expr
<'tcx
>,
214 expected
: Expectation
<'tcx
>,
217 debug
!("check_expr_kind(expr={:?}, expected={:?}, needs={:?})", expr
, expected
, needs
,);
221 ExprKind
::Box(ref subexpr
) => self.check_expr_box(subexpr
, expected
),
222 ExprKind
::Lit(ref lit
) => self.check_lit(&lit
, expected
),
223 ExprKind
::Binary(op
, ref lhs
, ref rhs
) => self.check_binop(expr
, op
, lhs
, rhs
),
224 ExprKind
::Assign(ref lhs
, ref rhs
, ref span
) => {
225 self.check_expr_assign(expr
, expected
, lhs
, rhs
, span
)
227 ExprKind
::AssignOp(op
, ref lhs
, ref rhs
) => self.check_binop_assign(expr
, op
, lhs
, rhs
),
228 ExprKind
::Unary(unop
, ref oprnd
) => {
229 self.check_expr_unary(unop
, oprnd
, expected
, needs
, expr
)
231 ExprKind
::AddrOf(kind
, mutbl
, ref oprnd
) => {
232 self.check_expr_addr_of(kind
, mutbl
, oprnd
, expected
, expr
)
234 ExprKind
::Path(ref qpath
) => self.check_expr_path(qpath
, expr
),
235 ExprKind
::LlvmInlineAsm(ref asm
) => {
236 for expr
in asm
.outputs_exprs
.iter().chain(asm
.inputs_exprs
.iter()) {
237 self.check_expr(expr
);
241 ExprKind
::Break(destination
, ref expr_opt
) => {
242 self.check_expr_break(destination
, expr_opt
.as_deref(), expr
)
244 ExprKind
::Continue(destination
) => {
245 if destination
.target_id
.is_ok() {
248 // There was an error; make type-check fail.
252 ExprKind
::Ret(ref expr_opt
) => self.check_expr_return(expr_opt
.as_deref(), expr
),
253 ExprKind
::Loop(ref body
, _
, source
) => {
254 self.check_expr_loop(body
, source
, expected
, expr
)
256 ExprKind
::Match(ref discrim
, ref arms
, match_src
) => {
257 self.check_match(expr
, &discrim
, arms
, expected
, match_src
)
259 ExprKind
::Closure(capture
, ref decl
, body_id
, _
, gen
) => {
260 self.check_expr_closure(expr
, capture
, &decl
, body_id
, gen
, expected
)
262 ExprKind
::Block(ref body
, _
) => self.check_block_with_expected(&body
, expected
),
263 ExprKind
::Call(ref callee
, ref args
) => self.check_call(expr
, &callee
, args
, expected
),
264 ExprKind
::MethodCall(ref segment
, span
, ref args
) => {
265 self.check_method_call(expr
, segment
, span
, args
, expected
, needs
)
267 ExprKind
::Cast(ref e
, ref t
) => self.check_expr_cast(e
, t
, expr
),
268 ExprKind
::Type(ref e
, ref t
) => {
269 let ty
= self.to_ty_saving_user_provided_ty(&t
);
270 self.check_expr_eq_type(&e
, ty
);
273 ExprKind
::DropTemps(ref e
) => self.check_expr_with_expectation(e
, expected
),
274 ExprKind
::Array(ref args
) => self.check_expr_array(args
, expected
, expr
),
275 ExprKind
::Repeat(ref element
, ref count
) => {
276 self.check_expr_repeat(element
, count
, expected
, expr
)
278 ExprKind
::Tup(ref elts
) => self.check_expr_tuple(elts
, expected
, expr
),
279 ExprKind
::Struct(ref qpath
, fields
, ref base_expr
) => {
280 self.check_expr_struct(expr
, expected
, qpath
, fields
, base_expr
)
282 ExprKind
::Field(ref base
, field
) => self.check_field(expr
, needs
, &base
, field
),
283 ExprKind
::Index(ref base
, ref idx
) => self.check_expr_index(base
, idx
, needs
, expr
),
284 ExprKind
::Yield(ref value
, ref src
) => self.check_expr_yield(value
, expr
, src
),
285 hir
::ExprKind
::Err
=> tcx
.types
.err
,
289 fn check_expr_box(&self, expr
: &'tcx hir
::Expr
<'tcx
>, expected
: Expectation
<'tcx
>) -> Ty
<'tcx
> {
290 let expected_inner
= expected
.to_option(self).map_or(NoExpectation
, |ty
| match ty
.kind
{
291 ty
::Adt(def
, _
) if def
.is_box() => Expectation
::rvalue_hint(self, ty
.boxed_ty()),
294 let referent_ty
= self.check_expr_with_expectation(expr
, expected_inner
);
295 self.tcx
.mk_box(referent_ty
)
301 oprnd
: &'tcx hir
::Expr
<'tcx
>,
302 expected
: Expectation
<'tcx
>,
304 expr
: &'tcx hir
::Expr
<'tcx
>,
307 let expected_inner
= match unop
{
308 hir
::UnOp
::UnNot
| hir
::UnOp
::UnNeg
=> expected
,
309 hir
::UnOp
::UnDeref
=> NoExpectation
,
311 let needs
= match unop
{
312 hir
::UnOp
::UnDeref
=> needs
,
315 let mut oprnd_t
= self.check_expr_with_expectation_and_needs(&oprnd
, expected_inner
, needs
);
317 if !oprnd_t
.references_error() {
318 oprnd_t
= self.structurally_resolved_type(expr
.span
, oprnd_t
);
320 hir
::UnOp
::UnDeref
=> {
321 if let Some(mt
) = oprnd_t
.builtin_deref(true) {
323 } else if let Some(ok
) = self.try_overloaded_deref(expr
.span
, oprnd_t
, needs
) {
324 let method
= self.register_infer_ok_obligations(ok
);
325 if let ty
::Ref(region
, _
, mutbl
) = method
.sig
.inputs()[0].kind
{
326 let mutbl
= match mutbl
{
327 hir
::Mutability
::Not
=> AutoBorrowMutability
::Not
,
328 hir
::Mutability
::Mut
=> AutoBorrowMutability
::Mut
{
329 // (It shouldn't actually matter for unary ops whether
330 // we enable two-phase borrows or not, since a unary
331 // op has no additional operands.)
332 allow_two_phase_borrow
: AllowTwoPhase
::No
,
335 self.apply_adjustments(
338 kind
: Adjust
::Borrow(AutoBorrow
::Ref(region
, mutbl
)),
339 target
: method
.sig
.inputs()[0],
343 oprnd_t
= self.make_overloaded_place_return_type(method
).ty
;
344 self.write_method_call(expr
.hir_id
, method
);
346 let mut err
= type_error_struct
!(
351 "type `{}` cannot be dereferenced",
354 let sp
= tcx
.sess
.source_map().start_point(expr
.span
);
356 tcx
.sess
.parse_sess
.ambiguous_block_expr_parse
.borrow().get(&sp
)
358 tcx
.sess
.parse_sess
.expr_parentheses_needed(&mut err
, *sp
, None
);
361 oprnd_t
= tcx
.types
.err
;
364 hir
::UnOp
::UnNot
=> {
365 let result
= self.check_user_unop(expr
, oprnd_t
, unop
);
366 // If it's builtin, we can reuse the type, this helps inference.
367 if !(oprnd_t
.is_integral() || oprnd_t
.kind
== ty
::Bool
) {
371 hir
::UnOp
::UnNeg
=> {
372 let result
= self.check_user_unop(expr
, oprnd_t
, unop
);
373 // If it's builtin, we can reuse the type, this helps inference.
374 if !oprnd_t
.is_numeric() {
383 fn check_expr_addr_of(
385 kind
: hir
::BorrowKind
,
386 mutbl
: hir
::Mutability
,
387 oprnd
: &'tcx hir
::Expr
<'tcx
>,
388 expected
: Expectation
<'tcx
>,
389 expr
: &'tcx hir
::Expr
<'tcx
>,
391 let hint
= expected
.only_has_type(self).map_or(NoExpectation
, |ty
| {
393 ty
::Ref(_
, ty
, _
) | ty
::RawPtr(ty
::TypeAndMut { ty, .. }
) => {
394 if oprnd
.is_syntactic_place_expr() {
395 // Places may legitimately have unsized types.
396 // For example, dereferences of a fat pointer and
397 // the last field of a struct can be unsized.
400 Expectation
::rvalue_hint(self, ty
)
406 let needs
= Needs
::maybe_mut_place(mutbl
);
407 let ty
= self.check_expr_with_expectation_and_needs(&oprnd
, hint
, needs
);
409 let tm
= ty
::TypeAndMut { ty, mutbl }
;
411 _
if tm
.ty
.references_error() => self.tcx
.types
.err
,
412 hir
::BorrowKind
::Raw
=> {
413 self.check_named_place_expr(oprnd
);
416 hir
::BorrowKind
::Ref
=> {
417 // Note: at this point, we cannot say what the best lifetime
418 // is to use for resulting pointer. We want to use the
419 // shortest lifetime possible so as to avoid spurious borrowck
420 // errors. Moreover, the longest lifetime will depend on the
421 // precise details of the value whose address is being taken
422 // (and how long it is valid), which we don't know yet until
423 // type inference is complete.
425 // Therefore, here we simply generate a region variable. The
426 // region inferencer will then select a suitable value.
427 // Finally, borrowck will infer the value of the region again,
428 // this time with enough precision to check that the value
429 // whose address was taken can actually be made to live as long
430 // as it needs to live.
431 let region
= self.next_region_var(infer
::AddrOfRegion(expr
.span
));
432 self.tcx
.mk_ref(region
, tm
)
437 /// Does this expression refer to a place that either:
438 /// * Is based on a local or static.
439 /// * Contains a dereference
440 /// Note that the adjustments for the children of `expr` should already
441 /// have been resolved.
442 fn check_named_place_expr(&self, oprnd
: &'tcx hir
::Expr
<'tcx
>) {
443 let is_named
= oprnd
.is_place_expr(|base
| {
444 // Allow raw borrows if there are any deref adjustments.
446 // const VAL: (i32,) = (0,);
447 // const REF: &(i32,) = &(0,);
449 // &raw const VAL.0; // ERROR
450 // &raw const REF.0; // OK, same as &raw const (*REF).0;
452 // This is maybe too permissive, since it allows
453 // `let u = &raw const Box::new((1,)).0`, which creates an
454 // immediately dangling raw pointer.
455 self.tables
.borrow().adjustments().get(base
.hir_id
).map_or(false, |x
| {
456 x
.iter().any(|adj
| if let Adjust
::Deref(_
) = adj
.kind { true }
else { false }
)
464 "cannot take address of a temporary"
466 .span_label(oprnd
.span
, "temporary value")
471 fn check_expr_path(&self, qpath
: &hir
::QPath
<'_
>, expr
: &'tcx hir
::Expr
<'tcx
>) -> Ty
<'tcx
> {
473 let (res
, opt_ty
, segs
) = self.resolve_ty_and_res_ufcs(qpath
, expr
.hir_id
, expr
.span
);
476 self.set_tainted_by_errors();
479 Res
::Def(DefKind
::Ctor(_
, CtorKind
::Fictive
), _
) => {
480 report_unexpected_variant_res(tcx
, res
, expr
.span
);
483 _
=> self.instantiate_value_path(segs
, opt_ty
, res
, expr
.span
, expr
.hir_id
).0,
486 if let ty
::FnDef(..) = ty
.kind
{
487 let fn_sig
= ty
.fn_sig(tcx
);
488 if !tcx
.features().unsized_locals
{
489 // We want to remove some Sized bounds from std functions,
490 // but don't want to expose the removal to stable Rust.
491 // i.e., we don't want to allow
497 // to work in stable even if the Sized bound on `drop` is relaxed.
498 for i
in 0..fn_sig
.inputs().skip_binder().len() {
499 // We just want to check sizedness, so instead of introducing
500 // placeholder lifetimes with probing, we just replace higher lifetimes
503 .replace_bound_vars_with_fresh_vars(
505 infer
::LateBoundRegionConversionTime
::FnCall
,
509 self.require_type_is_sized_deferred(
512 traits
::SizedArgumentType
,
516 // Here we want to prevent struct constructors from returning unsized types.
517 // There were two cases this happened: fn pointer coercion in stable
518 // and usual function call in presence of unsized_locals.
519 // Also, as we just want to check sizedness, instead of introducing
520 // placeholder lifetimes with probing, we just replace higher lifetimes
523 .replace_bound_vars_with_fresh_vars(
525 infer
::LateBoundRegionConversionTime
::FnCall
,
529 self.require_type_is_sized_deferred(output
, expr
.span
, traits
::SizedReturnType
);
532 // We always require that the type provided as the value for
533 // a type parameter outlives the moment of instantiation.
534 let substs
= self.tables
.borrow().node_substs(expr
.hir_id
);
535 self.add_wf_bounds(substs
, expr
);
542 destination
: hir
::Destination
,
543 expr_opt
: Option
<&'tcx hir
::Expr
<'tcx
>>,
544 expr
: &'tcx hir
::Expr
<'tcx
>,
547 if let Ok(target_id
) = destination
.target_id
{
549 if let Some(ref e
) = expr_opt
{
550 // If this is a break with a value, we need to type-check
551 // the expression. Get an expected type from the loop context.
552 let opt_coerce_to
= {
553 // We should release `enclosing_breakables` before the `check_expr_with_hint`
554 // below, so can't move this block of code to the enclosing scope and share
555 // `ctxt` with the second `encloding_breakables` borrow below.
556 let mut enclosing_breakables
= self.enclosing_breakables
.borrow_mut();
557 match enclosing_breakables
.opt_find_breakable(target_id
) {
558 Some(ctxt
) => ctxt
.coerce
.as_ref().map(|coerce
| coerce
.expected_ty()),
560 // Avoid ICE when `break` is inside a closure (#65383).
561 self.tcx
.sess
.delay_span_bug(
563 "break was outside loop, but no error was emitted",
565 return tcx
.types
.err
;
570 // If the loop context is not a `loop { }`, then break with
571 // a value is illegal, and `opt_coerce_to` will be `None`.
572 // Just set expectation to error in that case.
573 let coerce_to
= opt_coerce_to
.unwrap_or(tcx
.types
.err
);
575 // Recurse without `enclosing_breakables` borrowed.
576 e_ty
= self.check_expr_with_hint(e
, coerce_to
);
577 cause
= self.misc(e
.span
);
579 // Otherwise, this is a break *without* a value. That's
580 // always legal, and is equivalent to `break ()`.
581 e_ty
= tcx
.mk_unit();
582 cause
= self.misc(expr
.span
);
585 // Now that we have type-checked `expr_opt`, borrow
586 // the `enclosing_loops` field and let's coerce the
587 // type of `expr_opt` into what is expected.
588 let mut enclosing_breakables
= self.enclosing_breakables
.borrow_mut();
589 let ctxt
= match enclosing_breakables
.opt_find_breakable(target_id
) {
592 // Avoid ICE when `break` is inside a closure (#65383).
593 self.tcx
.sess
.delay_span_bug(
595 "break was outside loop, but no error was emitted",
597 return tcx
.types
.err
;
601 if let Some(ref mut coerce
) = ctxt
.coerce
{
602 if let Some(ref e
) = expr_opt
{
603 coerce
.coerce(self, &cause
, e
, e_ty
);
605 assert
!(e_ty
.is_unit());
606 let ty
= coerce
.expected_ty();
607 coerce
.coerce_forced_unit(
611 self.suggest_mismatched_types_on_tail(
612 &mut err
, expr
, ty
, e_ty
, cause
.span
, target_id
,
614 if let Some(val
) = ty_kind_suggestion(ty
) {
615 let label
= destination
617 .map(|l
| format
!(" {}", l
.ident
))
618 .unwrap_or_else(String
::new
);
621 "give it a value of the expected type",
622 format
!("break{} {}", label
, val
),
623 Applicability
::HasPlaceholders
,
631 // If `ctxt.coerce` is `None`, we can just ignore
632 // the type of the expression. This is because
633 // either this was a break *without* a value, in
634 // which case it is always a legal type (`()`), or
635 // else an error would have been flagged by the
636 // `loops` pass for using break with an expression
637 // where you are not supposed to.
638 assert
!(expr_opt
.is_none() || self.tcx
.sess
.has_errors());
641 ctxt
.may_break
= true;
643 // the type of a `break` is always `!`, since it diverges
646 // Otherwise, we failed to find the enclosing loop;
647 // this can only happen if the `break` was not
648 // inside a loop at all, which is caught by the
649 // loop-checking pass.
652 .delay_span_bug(expr
.span
, "break was outside loop, but no error was emitted");
654 // We still need to assign a type to the inner expression to
655 // prevent the ICE in #43162.
656 if let Some(ref e
) = expr_opt
{
657 self.check_expr_with_hint(e
, tcx
.types
.err
);
659 // ... except when we try to 'break rust;'.
660 // ICE this expression in particular (see #43162).
661 if let ExprKind
::Path(QPath
::Resolved(_
, ref path
)) = e
.kind
{
662 if path
.segments
.len() == 1 && path
.segments
[0].ident
.name
== sym
::rust
{
663 fatally_break_rust(self.tcx
.sess
);
667 // There was an error; make type-check fail.
672 fn check_expr_return(
674 expr_opt
: Option
<&'tcx hir
::Expr
<'tcx
>>,
675 expr
: &'tcx hir
::Expr
<'tcx
>,
677 if self.ret_coercion
.is_none() {
682 "return statement outside of function body",
685 } else if let Some(ref e
) = expr_opt
{
686 if self.ret_coercion_span
.borrow().is_none() {
687 *self.ret_coercion_span
.borrow_mut() = Some(e
.span
);
689 self.check_return_expr(e
);
691 let mut coercion
= self.ret_coercion
.as_ref().unwrap().borrow_mut();
692 if self.ret_coercion_span
.borrow().is_none() {
693 *self.ret_coercion_span
.borrow_mut() = Some(expr
.span
);
695 let cause
= self.cause(expr
.span
, ObligationCauseCode
::ReturnNoExpression
);
696 if let Some((fn_decl
, _
)) = self.get_fn_decl(expr
.hir_id
) {
697 coercion
.coerce_forced_unit(
701 let span
= fn_decl
.output
.span();
702 if let Ok(snippet
) = self.tcx
.sess
.source_map().span_to_snippet(span
) {
705 format
!("expected `{}` because of this return type", snippet
),
712 coercion
.coerce_forced_unit(self, &cause
, &mut |_
| (), true);
718 pub(super) fn check_return_expr(&self, return_expr
: &'tcx hir
::Expr
<'tcx
>) {
719 let ret_coercion
= self.ret_coercion
.as_ref().unwrap_or_else(|| {
720 span_bug
!(return_expr
.span
, "check_return_expr called outside fn body")
723 let ret_ty
= ret_coercion
.borrow().expected_ty();
724 let return_expr_ty
= self.check_expr_with_hint(return_expr
, ret_ty
.clone());
725 ret_coercion
.borrow_mut().coerce(
727 &self.cause(return_expr
.span
, ObligationCauseCode
::ReturnValue(return_expr
.hir_id
)),
733 fn is_destructuring_place_expr(&self, expr
: &'tcx hir
::Expr
<'tcx
>) -> bool
{
735 ExprKind
::Array(comps
) | ExprKind
::Tup(comps
) => {
736 comps
.iter().all(|e
| self.is_destructuring_place_expr(e
))
738 ExprKind
::Struct(_path
, fields
, rest
) => {
739 rest
.as_ref().map(|e
| self.is_destructuring_place_expr(e
)).unwrap_or(true)
740 && fields
.iter().all(|f
| self.is_destructuring_place_expr(&f
.expr
))
742 _
=> expr
.is_syntactic_place_expr(),
746 pub(crate) fn check_lhs_assignable(
748 lhs
: &'tcx hir
::Expr
<'tcx
>,
749 err_code
: &'
static str,
752 if !lhs
.is_syntactic_place_expr() {
753 let mut err
= self.tcx
.sess
.struct_span_err_with_code(
755 "invalid left-hand side of assignment",
756 DiagnosticId
::Error(err_code
.into()),
758 err
.span_label(lhs
.span
, "cannot assign to this expression");
759 if self.is_destructuring_place_expr(lhs
) {
760 err
.note("destructuring assignments are not currently supported");
761 err
.note("for more information, see https://github.com/rust-lang/rfcs/issues/372");
767 /// Type check assignment expression `expr` of form `lhs = rhs`.
768 /// The expected type is `()` and is passsed to the function for the purposes of diagnostics.
769 fn check_expr_assign(
771 expr
: &'tcx hir
::Expr
<'tcx
>,
772 expected
: Expectation
<'tcx
>,
773 lhs
: &'tcx hir
::Expr
<'tcx
>,
774 rhs
: &'tcx hir
::Expr
<'tcx
>,
777 let lhs_ty
= self.check_expr_with_needs(&lhs
, Needs
::MutPlace
);
778 let rhs_ty
= self.check_expr_coercable_to_type(&rhs
, lhs_ty
);
780 let expected_ty
= expected
.coercion_target_type(self, expr
.span
);
781 if expected_ty
== self.tcx
.types
.bool
{
782 // The expected type is `bool` but this will result in `()` so we can reasonably
783 // say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.
784 // The likely cause of this is `if foo = bar { .. }`.
785 let actual_ty
= self.tcx
.mk_unit();
786 let mut err
= self.demand_suptype_diag(expr
.span
, expected_ty
, actual_ty
).unwrap();
787 let msg
= "try comparing for equality";
788 let left
= self.tcx
.sess
.source_map().span_to_snippet(lhs
.span
);
789 let right
= self.tcx
.sess
.source_map().span_to_snippet(rhs
.span
);
790 if let (Ok(left
), Ok(right
)) = (left
, right
) {
791 let help
= format
!("{} == {}", left
, right
);
792 err
.span_suggestion(expr
.span
, msg
, help
, Applicability
::MaybeIncorrect
);
798 self.check_lhs_assignable(lhs
, "E0070", span
);
801 self.require_type_is_sized(lhs_ty
, lhs
.span
, traits
::AssignmentLhsSized
);
803 if lhs_ty
.references_error() || rhs_ty
.references_error() {
812 body
: &'tcx hir
::Block
<'tcx
>,
813 source
: hir
::LoopSource
,
814 expected
: Expectation
<'tcx
>,
815 expr
: &'tcx hir
::Expr
<'tcx
>,
817 let coerce
= match source
{
818 // you can only use break with a value from a normal `loop { }`
819 hir
::LoopSource
::Loop
=> {
820 let coerce_to
= expected
.coercion_target_type(self, body
.span
);
821 Some(CoerceMany
::new(coerce_to
))
824 hir
::LoopSource
::While
| hir
::LoopSource
::WhileLet
| hir
::LoopSource
::ForLoop
=> None
,
827 let ctxt
= BreakableCtxt
{
829 may_break
: false, // Will get updated if/when we find a `break`.
832 let (ctxt
, ()) = self.with_breakable_ctxt(expr
.hir_id
, ctxt
, || {
833 self.check_block_no_value(&body
);
837 // No way to know whether it's diverging because
838 // of a `break` or an outer `break` or `return`.
839 self.diverges
.set(Diverges
::Maybe
);
842 // If we permit break with a value, then result type is
843 // the LUB of the breaks (possibly ! if none); else, it
844 // is nil. This makes sense because infinite loops
845 // (which would have type !) are only possible iff we
846 // permit break with a value [1].
847 if ctxt
.coerce
.is_none() && !ctxt
.may_break
{
849 self.tcx
.sess
.delay_span_bug(body
.span
, "no coercion, but loop may not break");
851 ctxt
.coerce
.map(|c
| c
.complete(self)).unwrap_or_else(|| self.tcx
.mk_unit())
854 /// Checks a method call.
855 fn check_method_call(
857 expr
: &'tcx hir
::Expr
<'tcx
>,
858 segment
: &hir
::PathSegment
<'_
>,
860 args
: &'tcx
[hir
::Expr
<'tcx
>],
861 expected
: Expectation
<'tcx
>,
865 let rcvr_t
= self.check_expr_with_needs(&rcvr
, needs
);
866 // no need to check for bot/err -- callee does that
867 let rcvr_t
= self.structurally_resolved_type(args
[0].span
, rcvr_t
);
869 let method
= match self.lookup_method(rcvr_t
, segment
, span
, expr
, rcvr
) {
871 // We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to
872 // trigger this codepath causing `structuraly_resolved_type` to emit an error.
874 self.write_method_call(expr
.hir_id
, method
);
878 if segment
.ident
.name
!= kw
::Invalid
{
879 self.report_extended_method_error(segment
, span
, args
, rcvr_t
, error
);
885 // Call the generic checker.
886 self.check_method_argument_types(
896 fn report_extended_method_error(
898 segment
: &hir
::PathSegment
<'_
>,
900 args
: &'tcx
[hir
::Expr
<'tcx
>],
902 error
: MethodError
<'tcx
>,
905 let try_alt_rcvr
= |err
: &mut DiagnosticBuilder
<'_
>, new_rcvr_t
| {
906 if let Some(new_rcvr_t
) = new_rcvr_t
{
907 if let Ok(pick
) = self.lookup_probe(
912 probe
::ProbeScope
::AllTraits
,
915 pick
.item
.ident
.span
,
916 &format
!("the method is available for `{}` here", new_rcvr_t
),
922 if let Some(mut err
) = self.report_method_error(
926 SelfSource
::MethodCall(rcvr
),
930 if let ty
::Adt(..) = rcvr_t
.kind
{
931 // Try alternative arbitrary self types that could fulfill this call.
932 // FIXME: probe for all types that *could* be arbitrary self-types, not
933 // just this whitelist.
934 try_alt_rcvr(&mut err
, self.tcx
.mk_lang_item(rcvr_t
, lang_items
::OwnedBoxLangItem
));
935 try_alt_rcvr(&mut err
, self.tcx
.mk_lang_item(rcvr_t
, lang_items
::PinTypeLangItem
));
936 try_alt_rcvr(&mut err
, self.tcx
.mk_diagnostic_item(rcvr_t
, sym
::Arc
));
937 try_alt_rcvr(&mut err
, self.tcx
.mk_diagnostic_item(rcvr_t
, sym
::Rc
));
945 e
: &'tcx hir
::Expr
<'tcx
>,
946 t
: &'tcx hir
::Ty
<'tcx
>,
947 expr
: &'tcx hir
::Expr
<'tcx
>,
949 // Find the type of `e`. Supply hints based on the type we are casting to,
951 let t_cast
= self.to_ty_saving_user_provided_ty(t
);
952 let t_cast
= self.resolve_vars_if_possible(&t_cast
);
953 let t_expr
= self.check_expr_with_expectation(e
, ExpectCastableToType(t_cast
));
954 let t_cast
= self.resolve_vars_if_possible(&t_cast
);
956 // Eagerly check for some obvious errors.
957 if t_expr
.references_error() || t_cast
.references_error() {
960 // Defer other checks until we're done type checking.
961 let mut deferred_cast_checks
= self.deferred_cast_checks
.borrow_mut();
962 match cast
::CastCheck
::new(self, e
, t_expr
, t_cast
, t
.span
, expr
.span
) {
964 deferred_cast_checks
.push(cast_check
);
967 Err(ErrorReported
) => self.tcx
.types
.err
,
974 args
: &'tcx
[hir
::Expr
<'tcx
>],
975 expected
: Expectation
<'tcx
>,
976 expr
: &'tcx hir
::Expr
<'tcx
>,
978 let element_ty
= if !args
.is_empty() {
979 let coerce_to
= expected
981 .and_then(|uty
| match uty
.kind
{
982 ty
::Array(ty
, _
) | ty
::Slice(ty
) => Some(ty
),
986 self.next_ty_var(TypeVariableOrigin
{
987 kind
: TypeVariableOriginKind
::TypeInference
,
991 let mut coerce
= CoerceMany
::with_coercion_sites(coerce_to
, args
);
992 assert_eq
!(self.diverges
.get(), Diverges
::Maybe
);
994 let e_ty
= self.check_expr_with_hint(e
, coerce_to
);
995 let cause
= self.misc(e
.span
);
996 coerce
.coerce(self, &cause
, e
, e_ty
);
998 coerce
.complete(self)
1000 self.next_ty_var(TypeVariableOrigin
{
1001 kind
: TypeVariableOriginKind
::TypeInference
,
1005 self.tcx
.mk_array(element_ty
, args
.len() as u64)
1008 fn check_expr_repeat(
1010 element
: &'tcx hir
::Expr
<'tcx
>,
1011 count
: &'tcx hir
::AnonConst
,
1012 expected
: Expectation
<'tcx
>,
1013 _expr
: &'tcx hir
::Expr
<'tcx
>,
1016 let count
= self.to_const(count
);
1018 let uty
= match expected
{
1019 ExpectHasType(uty
) => match uty
.kind
{
1020 ty
::Array(ty
, _
) | ty
::Slice(ty
) => Some(ty
),
1026 let (element_ty
, t
) = match uty
{
1028 self.check_expr_coercable_to_type(&element
, uty
);
1032 let ty
= self.next_ty_var(TypeVariableOrigin
{
1033 kind
: TypeVariableOriginKind
::MiscVariable
,
1036 let element_ty
= self.check_expr_has_type_or_error(&element
, ty
, |_
| {}
);
1041 if element_ty
.references_error() {
1042 return tcx
.types
.err
;
1045 tcx
.mk_ty(ty
::Array(t
, count
))
1048 fn check_expr_tuple(
1050 elts
: &'tcx
[hir
::Expr
<'tcx
>],
1051 expected
: Expectation
<'tcx
>,
1052 expr
: &'tcx hir
::Expr
<'tcx
>,
1054 let flds
= expected
.only_has_type(self).and_then(|ty
| {
1055 let ty
= self.resolve_vars_with_obligations(ty
);
1057 ty
::Tuple(ref flds
) => Some(&flds
[..]),
1062 let elt_ts_iter
= elts
.iter().enumerate().map(|(i
, e
)| match flds
{
1063 Some(ref fs
) if i
< fs
.len() => {
1064 let ety
= fs
[i
].expect_ty();
1065 self.check_expr_coercable_to_type(&e
, ety
);
1068 _
=> self.check_expr_with_expectation(&e
, NoExpectation
),
1070 let tuple
= self.tcx
.mk_tup(elt_ts_iter
);
1071 if tuple
.references_error() {
1074 self.require_type_is_sized(tuple
, expr
.span
, traits
::TupleInitializerSized
);
1079 fn check_expr_struct(
1081 expr
: &hir
::Expr
<'_
>,
1082 expected
: Expectation
<'tcx
>,
1084 fields
: &'tcx
[hir
::Field
<'tcx
>],
1085 base_expr
: &'tcx Option
<&'tcx hir
::Expr
<'tcx
>>,
1087 // Find the relevant variant
1088 let (variant
, adt_ty
) = if let Some(variant_ty
) = self.check_struct_path(qpath
, expr
.hir_id
)
1092 self.check_struct_fields_on_error(fields
, base_expr
);
1093 return self.tcx
.types
.err
;
1096 let path_span
= match *qpath
{
1097 QPath
::Resolved(_
, ref path
) => path
.span
,
1098 QPath
::TypeRelative(ref qself
, _
) => qself
.span
,
1101 // Prohibit struct expressions when non-exhaustive flag is set.
1102 let adt
= adt_ty
.ty_adt_def().expect("`check_struct_path` returned non-ADT type");
1103 if !adt
.did
.is_local() && variant
.is_field_list_non_exhaustive() {
1108 "cannot create non-exhaustive {} using struct expression",
1114 let error_happened
= self.check_expr_struct_fields(
1121 base_expr
.is_none(),
1123 if let &Some(ref base_expr
) = base_expr
{
1124 // If check_expr_struct_fields hit an error, do not attempt to populate
1125 // the fields with the base_expr. This could cause us to hit errors later
1126 // when certain fields are assumed to exist that in fact do not.
1127 if !error_happened
{
1128 self.check_expr_has_type_or_error(base_expr
, adt_ty
, |_
| {}
);
1130 ty
::Adt(adt
, substs
) if adt
.is_struct() => {
1131 let fru_field_types
= adt
1136 self.normalize_associated_types_in(
1138 &f
.ty(self.tcx
, substs
),
1145 .fru_field_types_mut()
1146 .insert(expr
.hir_id
, fru_field_types
);
1153 "functional record update syntax requires a struct"
1160 self.require_type_is_sized(adt_ty
, expr
.span
, traits
::StructInitializerSized
);
1164 fn check_expr_struct_fields(
1167 expected
: Expectation
<'tcx
>,
1168 expr_id
: hir
::HirId
,
1170 variant
: &'tcx ty
::VariantDef
,
1171 ast_fields
: &'tcx
[hir
::Field
<'tcx
>],
1172 check_completeness
: bool
,
1176 let adt_ty_hint
= self
1177 .expected_inputs_for_expected_output(span
, expected
, adt_ty
, &[adt_ty
])
1181 // re-link the regions that EIfEO can erase.
1182 self.demand_eqtype(span
, adt_ty_hint
, adt_ty
);
1184 let (substs
, adt_kind
, kind_name
) = match &adt_ty
.kind
{
1185 &ty
::Adt(adt
, substs
) => (substs
, adt
.adt_kind(), adt
.variant_descr()),
1186 _
=> span_bug
!(span
, "non-ADT passed to check_expr_struct_fields"),
1189 let mut remaining_fields
= variant
1193 .map(|(i
, field
)| (field
.ident
.normalize_to_macros_2_0(), (i
, field
)))
1194 .collect
::<FxHashMap
<_
, _
>>();
1196 let mut seen_fields
= FxHashMap
::default();
1198 let mut error_happened
= false;
1200 // Type-check each field.
1201 for field
in ast_fields
{
1202 let ident
= tcx
.adjust_ident(field
.ident
, variant
.def_id
);
1203 let field_type
= if let Some((i
, v_field
)) = remaining_fields
.remove(&ident
) {
1204 seen_fields
.insert(ident
, field
.span
);
1205 self.write_field_index(field
.hir_id
, i
);
1207 // We don't look at stability attributes on
1208 // struct-like enums (yet...), but it's definitely not
1209 // a bug to have constructed one.
1210 if adt_kind
!= AdtKind
::Enum
{
1211 tcx
.check_stability(v_field
.did
, Some(expr_id
), field
.span
);
1214 self.field_ty(field
.span
, v_field
, substs
)
1216 error_happened
= true;
1217 if let Some(prev_span
) = seen_fields
.get(&ident
) {
1218 let mut err
= struct_span_err
!(
1222 "field `{}` specified more than once",
1226 err
.span_label(field
.ident
.span
, "used more than once");
1227 err
.span_label(*prev_span
, format
!("first use of `{}`", ident
));
1231 self.report_unknown_field(adt_ty
, variant
, field
, ast_fields
, kind_name
, span
);
1237 // Make sure to give a type to the field even if there's
1238 // an error, so we can continue type-checking.
1239 self.check_expr_coercable_to_type(&field
.expr
, field_type
);
1242 // Make sure the programmer specified correct number of fields.
1243 if kind_name
== "union" {
1244 if ast_fields
.len() != 1 {
1245 tcx
.sess
.span_err(span
, "union expressions should have exactly one field");
1247 } else if check_completeness
&& !error_happened
&& !remaining_fields
.is_empty() {
1248 let len
= remaining_fields
.len();
1250 let mut displayable_field_names
=
1251 remaining_fields
.keys().map(|ident
| ident
.as_str()).collect
::<Vec
<_
>>();
1253 displayable_field_names
.sort();
1255 let truncated_fields_error
= if len
<= 3 {
1258 format
!(" and {} other field{}", (len
- 3), if len
- 3 == 1 { "" }
else { "s" }
)
1261 let remaining_fields_names
= displayable_field_names
1264 .map(|n
| format
!("`{}`", n
))
1265 .collect
::<Vec
<_
>>()
1272 "missing field{} {}{} in initializer of `{}`",
1273 pluralize
!(remaining_fields
.len()),
1274 remaining_fields_names
,
1275 truncated_fields_error
,
1280 format
!("missing {}{}", remaining_fields_names
, truncated_fields_error
),
1287 fn check_struct_fields_on_error(
1289 fields
: &'tcx
[hir
::Field
<'tcx
>],
1290 base_expr
: &'tcx Option
<&'tcx hir
::Expr
<'tcx
>>,
1292 for field
in fields
{
1293 self.check_expr(&field
.expr
);
1295 if let Some(ref base
) = *base_expr
{
1296 self.check_expr(&base
);
1300 fn report_unknown_field(
1303 variant
: &'tcx ty
::VariantDef
,
1304 field
: &hir
::Field
<'_
>,
1305 skip_fields
: &[hir
::Field
<'_
>],
1309 if variant
.recovered
{
1310 self.set_tainted_by_errors();
1313 let mut err
= self.type_error_struct_with_diag(
1315 |actual
| match ty
.kind
{
1316 ty
::Adt(adt
, ..) if adt
.is_enum() => struct_span_err
!(
1320 "{} `{}::{}` has no field named `{}`",
1326 _
=> struct_span_err
!(
1330 "{} `{}` has no field named `{}`",
1338 match variant
.ctor_kind
{
1340 err
.span_label(variant
.ident
.span
, format
!("`{adt}` defined here", adt
= ty
));
1341 err
.span_label(field
.ident
.span
, "field does not exist");
1345 "`{adt}` is a tuple {kind_name}, \
1346 use the appropriate syntax: `{adt}(/* fields */)`",
1348 kind_name
= kind_name
1353 // prevent all specified fields from being suggested
1354 let skip_fields
= skip_fields
.iter().map(|ref x
| x
.ident
.name
);
1355 if let Some(field_name
) =
1356 Self::suggest_field_name(variant
, &field
.ident
.as_str(), skip_fields
.collect())
1358 err
.span_suggestion(
1360 "a field with a similar name exists",
1361 field_name
.to_string(),
1362 Applicability
::MaybeIncorrect
,
1366 ty
::Adt(adt
, ..) => {
1370 format
!("`{}::{}` does not have this field", ty
, variant
.ident
),
1375 format
!("`{}` does not have this field", ty
),
1378 let available_field_names
= self.available_field_names(variant
);
1379 if !available_field_names
.is_empty() {
1381 "available fields are: {}",
1382 self.name_series_display(available_field_names
)
1386 _
=> bug
!("non-ADT passed to report_unknown_field"),
1394 // Return an hint about the closest match in field names
1395 fn suggest_field_name(
1396 variant
: &'tcx ty
::VariantDef
,
1399 ) -> Option
<Symbol
> {
1400 let names
= variant
.fields
.iter().filter_map(|field
| {
1401 // ignore already set fields and private fields from non-local crates
1402 if skip
.iter().any(|&x
| x
== field
.ident
.name
)
1403 || (!variant
.def_id
.is_local() && field
.vis
!= Visibility
::Public
)
1407 Some(&field
.ident
.name
)
1411 find_best_match_for_name(names
, field
, None
)
1414 fn available_field_names(&self, variant
: &'tcx ty
::VariantDef
) -> Vec
<ast
::Name
> {
1419 let def_scope
= self
1421 .adjust_ident_and_get_scope(field
.ident
, variant
.def_id
, self.body_id
)
1423 field
.vis
.is_accessible_from(def_scope
, self.tcx
)
1425 .map(|field
| field
.ident
.name
)
1429 fn name_series_display(&self, names
: Vec
<ast
::Name
>) -> String
{
1430 // dynamic limit, to never omit just one field
1431 let limit
= if names
.len() == 6 { 6 }
else { 5 }
;
1433 names
.iter().take(limit
).map(|n
| format
!("`{}`", n
)).collect
::<Vec
<_
>>().join(", ");
1434 if names
.len() > limit
{
1435 display
= format
!("{} ... and {} others", display
, names
.len() - limit
);
1440 // Check field access expressions
1443 expr
: &'tcx hir
::Expr
<'tcx
>,
1445 base
: &'tcx hir
::Expr
<'tcx
>,
1448 let expr_t
= self.check_expr_with_needs(base
, needs
);
1449 let expr_t
= self.structurally_resolved_type(base
.span
, expr_t
);
1450 let mut private_candidate
= None
;
1451 let mut autoderef
= self.autoderef(expr
.span
, expr_t
);
1452 while let Some((base_t
, _
)) = autoderef
.next() {
1454 ty
::Adt(base_def
, substs
) if !base_def
.is_enum() => {
1455 debug
!("struct named {:?}", base_t
);
1456 let (ident
, def_scope
) =
1457 self.tcx
.adjust_ident_and_get_scope(field
, base_def
.did
, self.body_id
);
1458 let fields
= &base_def
.non_enum_variant().fields
;
1459 if let Some(index
) =
1460 fields
.iter().position(|f
| f
.ident
.normalize_to_macros_2_0() == ident
)
1462 let field
= &fields
[index
];
1463 let field_ty
= self.field_ty(expr
.span
, field
, substs
);
1464 // Save the index of all fields regardless of their visibility in case
1465 // of error recovery.
1466 self.write_field_index(expr
.hir_id
, index
);
1467 if field
.vis
.is_accessible_from(def_scope
, self.tcx
) {
1468 let adjustments
= autoderef
.adjust_steps(self, needs
);
1469 self.apply_adjustments(base
, adjustments
);
1470 autoderef
.finalize(self);
1472 self.tcx
.check_stability(field
.did
, Some(expr
.hir_id
), expr
.span
);
1475 private_candidate
= Some((base_def
.did
, field_ty
));
1478 ty
::Tuple(ref tys
) => {
1479 let fstr
= field
.as_str();
1480 if let Ok(index
) = fstr
.parse
::<usize>() {
1481 if fstr
== index
.to_string() {
1482 if let Some(field_ty
) = tys
.get(index
) {
1483 let adjustments
= autoderef
.adjust_steps(self, needs
);
1484 self.apply_adjustments(base
, adjustments
);
1485 autoderef
.finalize(self);
1487 self.write_field_index(expr
.hir_id
, index
);
1488 return field_ty
.expect_ty();
1496 autoderef
.unambiguous_final_ty(self);
1498 if let Some((did
, field_ty
)) = private_candidate
{
1499 self.ban_private_field_access(expr
, expr_t
, field
, did
);
1503 if field
.name
== kw
::Invalid
{
1504 } else if self.method_exists(field
, expr_t
, expr
.hir_id
, true) {
1505 self.ban_take_value_of_method(expr
, expr_t
, field
);
1506 } else if !expr_t
.is_primitive_ty() {
1507 self.ban_nonexisting_field(field
, base
, expr
, expr_t
);
1514 "`{}` is a primitive type and therefore doesn't have fields",
1520 self.tcx().types
.err
1523 fn ban_nonexisting_field(
1526 base
: &'tcx hir
::Expr
<'tcx
>,
1527 expr
: &'tcx hir
::Expr
<'tcx
>,
1530 let mut err
= self.no_such_field_err(field
.span
, field
, expr_t
);
1532 match expr_t
.peel_refs().kind
{
1533 ty
::Array(_
, len
) => {
1534 self.maybe_suggest_array_indexing(&mut err
, expr
, base
, field
, len
);
1537 self.suggest_first_deref_field(&mut err
, expr
, base
, field
);
1539 ty
::Adt(def
, _
) if !def
.is_enum() => {
1540 self.suggest_fields_on_recordish(&mut err
, def
, field
);
1542 ty
::Param(param_ty
) => {
1543 self.point_at_param_definition(&mut err
, param_ty
);
1548 if field
.name
== kw
::Await
{
1549 // We know by construction that `<expr>.await` is either on Rust 2015
1550 // or results in `ExprKind::Await`. Suggest switching the edition to 2018.
1551 err
.note("to `.await` a `Future`, switch to Rust 2018");
1552 err
.help("set `edition = \"2018\"` in `Cargo.toml`");
1553 err
.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
1559 fn ban_private_field_access(
1561 expr
: &hir
::Expr
<'_
>,
1566 let struct_path
= self.tcx().def_path_str(base_did
);
1567 let kind_name
= match self.tcx().def_kind(base_did
) {
1568 Some(def_kind
) => def_kind
.descr(base_did
),
1571 let mut err
= struct_span_err
!(
1575 "field `{}` of {} `{}` is private",
1580 err
.span_label(field
.span
, "private field");
1581 // Also check if an accessible method exists, which is often what is meant.
1582 if self.method_exists(field
, expr_t
, expr
.hir_id
, false) && !self.expr_in_place(expr
.hir_id
)
1584 self.suggest_method_call(
1586 &format
!("a method `{}` also exists, call it with parentheses", field
),
1595 fn ban_take_value_of_method(&self, expr
: &hir
::Expr
<'_
>, expr_t
: Ty
<'tcx
>, field
: ast
::Ident
) {
1596 let mut err
= type_error_struct
!(
1601 "attempted to take value of method `{}` on type `{}`",
1605 err
.span_label(field
.span
, "method, not a field");
1606 if !self.expr_in_place(expr
.hir_id
) {
1607 self.suggest_method_call(
1609 "use parentheses to call the method",
1615 err
.help("methods are immutable and cannot be assigned to");
1621 fn point_at_param_definition(&self, err
: &mut DiagnosticBuilder
<'_
>, param
: ty
::ParamTy
) {
1622 let generics
= self.tcx
.generics_of(self.body_id
.owner
.to_def_id());
1623 let generic_param
= generics
.type_param(¶m
, self.tcx
);
1624 if let ty
::GenericParamDefKind
::Type { synthetic: Some(..), .. }
= generic_param
.kind
{
1627 let param_def_id
= generic_param
.def_id
;
1628 let param_hir_id
= match self.tcx
.hir().as_local_hir_id(param_def_id
) {
1632 let param_span
= self.tcx
.hir().span(param_hir_id
);
1633 let param_name
= self.tcx
.hir().ty_param_name(param_hir_id
);
1635 err
.span_label(param_span
, &format
!("type parameter '{}' declared here", param_name
));
1638 fn suggest_fields_on_recordish(
1640 err
: &mut DiagnosticBuilder
<'_
>,
1641 def
: &'tcx ty
::AdtDef
,
1644 if let Some(suggested_field_name
) =
1645 Self::suggest_field_name(def
.non_enum_variant(), &field
.as_str(), vec
![])
1647 err
.span_suggestion(
1649 "a field with a similar name exists",
1650 suggested_field_name
.to_string(),
1651 Applicability
::MaybeIncorrect
,
1654 err
.span_label(field
.span
, "unknown field");
1655 let struct_variant_def
= def
.non_enum_variant();
1656 let field_names
= self.available_field_names(struct_variant_def
);
1657 if !field_names
.is_empty() {
1659 "available fields are: {}",
1660 self.name_series_display(field_names
),
1666 fn maybe_suggest_array_indexing(
1668 err
: &mut DiagnosticBuilder
<'_
>,
1669 expr
: &hir
::Expr
<'_
>,
1670 base
: &hir
::Expr
<'_
>,
1672 len
: &ty
::Const
<'tcx
>,
1674 if let (Some(len
), Ok(user_index
)) =
1675 (len
.try_eval_usize(self.tcx
, self.param_env
), field
.as_str().parse
::<u64>())
1677 if let Ok(base
) = self.tcx
.sess
.source_map().span_to_snippet(base
.span
) {
1678 let help
= "instead of using tuple indexing, use array indexing";
1679 let suggestion
= format
!("{}[{}]", base
, field
);
1680 let applicability
= if len
< user_index
{
1681 Applicability
::MachineApplicable
1683 Applicability
::MaybeIncorrect
1685 err
.span_suggestion(expr
.span
, help
, suggestion
, applicability
);
1690 fn suggest_first_deref_field(
1692 err
: &mut DiagnosticBuilder
<'_
>,
1693 expr
: &hir
::Expr
<'_
>,
1694 base
: &hir
::Expr
<'_
>,
1697 if let Ok(base
) = self.tcx
.sess
.source_map().span_to_snippet(base
.span
) {
1698 let msg
= format
!("`{}` is a raw pointer; try dereferencing it", base
);
1699 let suggestion
= format
!("(*{}).{}", base
, field
);
1700 err
.span_suggestion(expr
.span
, &msg
, suggestion
, Applicability
::MaybeIncorrect
);
1704 fn no_such_field_err
<T
: Display
>(
1708 expr_t
: &ty
::TyS
<'_
>,
1709 ) -> DiagnosticBuilder
<'_
> {
1715 "no field `{}` on type `{}`",
1721 fn check_expr_index(
1723 base
: &'tcx hir
::Expr
<'tcx
>,
1724 idx
: &'tcx hir
::Expr
<'tcx
>,
1726 expr
: &'tcx hir
::Expr
<'tcx
>,
1728 let base_t
= self.check_expr_with_needs(&base
, needs
);
1729 let idx_t
= self.check_expr(&idx
);
1731 if base_t
.references_error() {
1733 } else if idx_t
.references_error() {
1736 let base_t
= self.structurally_resolved_type(base
.span
, base_t
);
1737 match self.lookup_indexing(expr
, base
, base_t
, idx_t
, needs
) {
1738 Some((index_ty
, element_ty
)) => {
1739 // two-phase not needed because index_ty is never mutable
1740 self.demand_coerce(idx
, idx_t
, index_ty
, AllowTwoPhase
::No
);
1744 let mut err
= type_error_struct
!(
1749 "cannot index into a value of type `{}`",
1752 // Try to give some advice about indexing tuples.
1753 if let ty
::Tuple(..) = base_t
.kind
{
1754 let mut needs_note
= true;
1755 // If the index is an integer, we can show the actual
1756 // fixed expression:
1757 if let ExprKind
::Lit(ref lit
) = idx
.kind
{
1758 if let ast
::LitKind
::Int(i
, ast
::LitIntType
::Unsuffixed
) = lit
.node
{
1759 let snip
= self.tcx
.sess
.source_map().span_to_snippet(base
.span
);
1760 if let Ok(snip
) = snip
{
1761 err
.span_suggestion(
1763 "to access tuple elements, use",
1764 format
!("{}.{}", snip
, i
),
1765 Applicability
::MachineApplicable
,
1773 "to access tuple elements, use tuple indexing \
1774 syntax (e.g., `tuple.0`)",
1785 fn check_expr_yield(
1787 value
: &'tcx hir
::Expr
<'tcx
>,
1788 expr
: &'tcx hir
::Expr
<'tcx
>,
1789 src
: &'tcx hir
::YieldSource
,
1791 match self.resume_yield_tys
{
1792 Some((resume_ty
, yield_ty
)) => {
1793 self.check_expr_coercable_to_type(&value
, yield_ty
);
1797 // Given that this `yield` expression was generated as a result of lowering a `.await`,
1798 // we know that the yield type must be `()`; however, the context won't contain this
1799 // information. Hence, we check the source of the yield expression here and check its
1800 // value's type against `()` (this check should always hold).
1801 None
if src
.is_await() => {
1802 self.check_expr_coercable_to_type(&value
, self.tcx
.mk_unit());
1810 "yield expression outside of generator literal"
1819 pub(super) fn ty_kind_suggestion(ty
: Ty
<'_
>) -> Option
<&'
static str> {
1820 Some(match ty
.kind
{
1823 ty
::Int(_
) | ty
::Uint(_
) => "42",
1824 ty
::Float(_
) => "3.14159",
1825 ty
::Error
| ty
::Never
=> return None
,