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
;
18 FieldMultiplySpecifiedInInitializer
, FunctionalRecordUpdateOnNonStruct
,
19 YieldExprOutsideOfGenerator
,
21 use crate::type_error_struct
;
23 use crate::errors
::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive}
;
25 use rustc_ast
::util
::lev_distance
::find_best_match_for_name
;
26 use rustc_data_structures
::fx
::FxHashMap
;
27 use rustc_data_structures
::stack
::ensure_sufficient_stack
;
28 use rustc_errors
::ErrorReported
;
29 use rustc_errors
::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId}
;
31 use rustc_hir
::def
::{CtorKind, DefKind, Res}
;
32 use rustc_hir
::def_id
::DefId
;
33 use rustc_hir
::lang_items
::LangItem
;
34 use rustc_hir
::{ExprKind, QPath}
;
35 use rustc_infer
::infer
;
36 use rustc_infer
::infer
::type_variable
::{TypeVariableOrigin, TypeVariableOriginKind}
;
38 use rustc_middle
::ty
::adjustment
::{Adjust, Adjustment, AllowTwoPhase}
;
39 use rustc_middle
::ty
::Ty
;
40 use rustc_middle
::ty
::TypeFoldable
;
41 use rustc_middle
::ty
::{AdtKind, Visibility}
;
42 use rustc_span
::hygiene
::DesugaringKind
;
43 use rustc_span
::source_map
::Span
;
44 use rustc_span
::symbol
::{kw, sym, Ident, Symbol}
;
45 use rustc_trait_selection
::traits
::{self, ObligationCauseCode}
;
47 use std
::fmt
::Display
;
49 impl<'a
, 'tcx
> FnCtxt
<'a
, 'tcx
> {
50 fn check_expr_eq_type(&self, expr
: &'tcx hir
::Expr
<'tcx
>, expected
: Ty
<'tcx
>) {
51 let ty
= self.check_expr_with_hint(expr
, expected
);
52 self.demand_eqtype(expr
.span
, expected
, ty
);
55 pub fn check_expr_has_type_or_error(
57 expr
: &'tcx hir
::Expr
<'tcx
>,
59 extend_err
: impl Fn(&mut DiagnosticBuilder
<'_
>),
61 self.check_expr_meets_expectation_or_error(expr
, ExpectHasType(expected
), extend_err
)
64 fn check_expr_meets_expectation_or_error(
66 expr
: &'tcx hir
::Expr
<'tcx
>,
67 expected
: Expectation
<'tcx
>,
68 extend_err
: impl Fn(&mut DiagnosticBuilder
<'_
>),
70 let expected_ty
= expected
.to_option(&self).unwrap_or(self.tcx
.types
.bool
);
71 let mut ty
= self.check_expr_with_expectation(expr
, expected
);
73 // While we don't allow *arbitrary* coercions here, we *do* allow
74 // coercions from ! to `expected`.
77 !self.typeck_results
.borrow().adjustments().contains_key(expr
.hir_id
),
78 "expression with never type wound up being adjusted"
80 let adj_ty
= self.next_diverging_ty_var(TypeVariableOrigin
{
81 kind
: TypeVariableOriginKind
::AdjustmentType
,
84 self.apply_adjustments(
86 vec
![Adjustment { kind: Adjust::NeverToAny, target: adj_ty }
],
91 if let Some(mut err
) = self.demand_suptype_diag(expr
.span
, expected_ty
, ty
) {
92 let expr
= expr
.peel_drop_temps();
93 self.suggest_deref_ref_or_into(&mut err
, expr
, expected_ty
, ty
, None
);
95 // Error possibly reported in `check_assign` so avoid emitting error again.
96 err
.emit_unless(self.is_assign_to_bool(expr
, expected_ty
));
101 pub(super) fn check_expr_coercable_to_type(
103 expr
: &'tcx hir
::Expr
<'tcx
>,
105 expected_ty_expr
: Option
<&'tcx hir
::Expr
<'tcx
>>,
107 let ty
= self.check_expr_with_hint(expr
, expected
);
108 // checks don't need two phase
109 self.demand_coerce(expr
, ty
, expected
, expected_ty_expr
, AllowTwoPhase
::No
)
112 pub(super) fn check_expr_with_hint(
114 expr
: &'tcx hir
::Expr
<'tcx
>,
117 self.check_expr_with_expectation(expr
, ExpectHasType(expected
))
120 fn check_expr_with_expectation_and_needs(
122 expr
: &'tcx hir
::Expr
<'tcx
>,
123 expected
: Expectation
<'tcx
>,
126 let ty
= self.check_expr_with_expectation(expr
, expected
);
128 // If the expression is used in a place whether mutable place is required
129 // e.g. LHS of assignment, perform the conversion.
130 if let Needs
::MutPlace
= needs
{
131 self.convert_place_derefs_to_mutable(expr
);
137 pub(super) fn check_expr(&self, expr
: &'tcx hir
::Expr
<'tcx
>) -> Ty
<'tcx
> {
138 self.check_expr_with_expectation(expr
, NoExpectation
)
141 pub(super) fn check_expr_with_needs(
143 expr
: &'tcx hir
::Expr
<'tcx
>,
146 self.check_expr_with_expectation_and_needs(expr
, NoExpectation
, needs
)
150 /// If an expression has any sub-expressions that result in a type error,
151 /// inspecting that expression's type with `ty.references_error()` will return
152 /// true. Likewise, if an expression is known to diverge, inspecting its
153 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
154 /// strict, _|_ can appear in the type of an expression that does not,
155 /// itself, diverge: for example, fn() -> _|_.)
156 /// Note that inspecting a type's structure *directly* may expose the fact
157 /// that there are actually multiple representations for `Error`, so avoid
158 /// that when err needs to be handled differently.
159 pub(super) fn check_expr_with_expectation(
161 expr
: &'tcx hir
::Expr
<'tcx
>,
162 expected
: Expectation
<'tcx
>,
164 debug
!(">> type-checking: expr={:?} expected={:?}", expr
, expected
);
166 // True if `expr` is a `Try::from_ok(())` that is a result of desugaring a try block
167 // without the final expr (e.g. `try { return; }`). We don't want to generate an
168 // unreachable_code lint for it since warnings for autogenerated code are confusing.
169 let is_try_block_generated_unit_expr
= match expr
.kind
{
170 ExprKind
::Call(_
, ref args
) if expr
.span
.is_desugaring(DesugaringKind
::TryBlock
) => {
171 args
.len() == 1 && args
[0].span
.is_desugaring(DesugaringKind
::TryBlock
)
177 // Warn for expressions after diverging siblings.
178 if !is_try_block_generated_unit_expr
{
179 self.warn_if_unreachable(expr
.hir_id
, expr
.span
, "expression");
182 // Hide the outer diverging and has_errors flags.
183 let old_diverges
= self.diverges
.replace(Diverges
::Maybe
);
184 let old_has_errors
= self.has_errors
.replace(false);
186 let ty
= ensure_sufficient_stack(|| self.check_expr_kind(expr
, expected
));
188 // Warn for non-block expressions with diverging children.
190 ExprKind
::Block(..) | ExprKind
::Loop(..) | ExprKind
::Match(..) => {}
191 // If `expr` is a result of desugaring the try block and is an ok-wrapped
192 // diverging expression (e.g. it arose from desugaring of `try { return }`),
193 // we skip issuing a warning because it is autogenerated code.
194 ExprKind
::Call(..) if expr
.span
.is_desugaring(DesugaringKind
::TryBlock
) => {}
195 ExprKind
::Call(ref callee
, _
) => {
196 self.warn_if_unreachable(expr
.hir_id
, callee
.span
, "call")
198 ExprKind
::MethodCall(_
, ref span
, _
, _
) => {
199 self.warn_if_unreachable(expr
.hir_id
, *span
, "call")
201 _
=> self.warn_if_unreachable(expr
.hir_id
, expr
.span
, "expression"),
204 // Any expression that produces a value of type `!` must have diverged
206 self.diverges
.set(self.diverges
.get() | Diverges
::always(expr
.span
));
209 // Record the type, which applies it effects.
210 // We need to do this after the warning above, so that
211 // we don't warn for the diverging expression itself.
212 self.write_ty(expr
.hir_id
, ty
);
214 // Combine the diverging and has_error flags.
215 self.diverges
.set(self.diverges
.get() | old_diverges
);
216 self.has_errors
.set(self.has_errors
.get() | old_has_errors
);
218 debug
!("type of {} is...", self.tcx
.hir().node_to_string(expr
.hir_id
));
219 debug
!("... {:?}, expected is {:?}", ty
, expected
);
226 expr
: &'tcx hir
::Expr
<'tcx
>,
227 expected
: Expectation
<'tcx
>,
229 debug
!("check_expr_kind(expr={:?}, expected={:?})", expr
, expected
);
233 ExprKind
::Box(ref subexpr
) => self.check_expr_box(subexpr
, expected
),
234 ExprKind
::Lit(ref lit
) => self.check_lit(&lit
, expected
),
235 ExprKind
::Binary(op
, ref lhs
, ref rhs
) => self.check_binop(expr
, op
, lhs
, rhs
),
236 ExprKind
::Assign(ref lhs
, ref rhs
, ref span
) => {
237 self.check_expr_assign(expr
, expected
, lhs
, rhs
, span
)
239 ExprKind
::AssignOp(op
, ref lhs
, ref rhs
) => self.check_binop_assign(expr
, op
, lhs
, rhs
),
240 ExprKind
::Unary(unop
, ref oprnd
) => self.check_expr_unary(unop
, oprnd
, expected
, expr
),
241 ExprKind
::AddrOf(kind
, mutbl
, ref oprnd
) => {
242 self.check_expr_addr_of(kind
, mutbl
, oprnd
, expected
, expr
)
244 ExprKind
::Path(QPath
::LangItem(lang_item
, _
)) => {
245 self.check_lang_item_path(lang_item
, expr
)
247 ExprKind
::Path(ref qpath
) => self.check_expr_path(qpath
, expr
),
248 ExprKind
::InlineAsm(asm
) => self.check_expr_asm(asm
),
249 ExprKind
::LlvmInlineAsm(ref asm
) => {
250 for expr
in asm
.outputs_exprs
.iter().chain(asm
.inputs_exprs
.iter()) {
251 self.check_expr(expr
);
255 ExprKind
::Break(destination
, ref expr_opt
) => {
256 self.check_expr_break(destination
, expr_opt
.as_deref(), expr
)
258 ExprKind
::Continue(destination
) => {
259 if destination
.target_id
.is_ok() {
262 // There was an error; make type-check fail.
266 ExprKind
::Ret(ref expr_opt
) => self.check_expr_return(expr_opt
.as_deref(), expr
),
267 ExprKind
::Loop(ref body
, _
, source
) => {
268 self.check_expr_loop(body
, source
, expected
, expr
)
270 ExprKind
::Match(ref discrim
, ref arms
, match_src
) => {
271 self.check_match(expr
, &discrim
, arms
, expected
, match_src
)
273 ExprKind
::Closure(capture
, ref decl
, body_id
, _
, gen
) => {
274 self.check_expr_closure(expr
, capture
, &decl
, body_id
, gen
, expected
)
276 ExprKind
::Block(ref body
, _
) => self.check_block_with_expected(&body
, expected
),
277 ExprKind
::Call(ref callee
, ref args
) => self.check_call(expr
, &callee
, args
, expected
),
278 ExprKind
::MethodCall(ref segment
, span
, ref args
, _
) => {
279 self.check_method_call(expr
, segment
, span
, args
, expected
)
281 ExprKind
::Cast(ref e
, ref t
) => self.check_expr_cast(e
, t
, expr
),
282 ExprKind
::Type(ref e
, ref t
) => {
283 let ty
= self.to_ty_saving_user_provided_ty(&t
);
284 self.check_expr_eq_type(&e
, ty
);
287 ExprKind
::DropTemps(ref e
) => self.check_expr_with_expectation(e
, expected
),
288 ExprKind
::Array(ref args
) => self.check_expr_array(args
, expected
, expr
),
289 ExprKind
::ConstBlock(ref anon_const
) => self.to_const(anon_const
).ty
,
290 ExprKind
::Repeat(ref element
, ref count
) => {
291 self.check_expr_repeat(element
, count
, expected
, expr
)
293 ExprKind
::Tup(ref elts
) => self.check_expr_tuple(elts
, expected
, expr
),
294 ExprKind
::Struct(ref qpath
, fields
, ref base_expr
) => {
295 self.check_expr_struct(expr
, expected
, qpath
, fields
, base_expr
)
297 ExprKind
::Field(ref base
, field
) => self.check_field(expr
, &base
, field
),
298 ExprKind
::Index(ref base
, ref idx
) => self.check_expr_index(base
, idx
, expr
),
299 ExprKind
::Yield(ref value
, ref src
) => self.check_expr_yield(value
, expr
, src
),
300 hir
::ExprKind
::Err
=> tcx
.ty_error(),
304 fn check_expr_box(&self, expr
: &'tcx hir
::Expr
<'tcx
>, expected
: Expectation
<'tcx
>) -> Ty
<'tcx
> {
305 let expected_inner
= expected
.to_option(self).map_or(NoExpectation
, |ty
| match ty
.kind() {
306 ty
::Adt(def
, _
) if def
.is_box() => Expectation
::rvalue_hint(self, ty
.boxed_ty()),
309 let referent_ty
= self.check_expr_with_expectation(expr
, expected_inner
);
310 self.tcx
.mk_box(referent_ty
)
316 oprnd
: &'tcx hir
::Expr
<'tcx
>,
317 expected
: Expectation
<'tcx
>,
318 expr
: &'tcx hir
::Expr
<'tcx
>,
321 let expected_inner
= match unop
{
322 hir
::UnOp
::UnNot
| hir
::UnOp
::UnNeg
=> expected
,
323 hir
::UnOp
::UnDeref
=> NoExpectation
,
325 let mut oprnd_t
= self.check_expr_with_expectation(&oprnd
, expected_inner
);
327 if !oprnd_t
.references_error() {
328 oprnd_t
= self.structurally_resolved_type(expr
.span
, oprnd_t
);
330 hir
::UnOp
::UnDeref
=> {
331 if let Some(ty
) = self.lookup_derefing(expr
, oprnd
, oprnd_t
) {
334 let mut err
= type_error_struct
!(
339 "type `{}` cannot be dereferenced",
342 let sp
= tcx
.sess
.source_map().start_point(expr
.span
);
344 tcx
.sess
.parse_sess
.ambiguous_block_expr_parse
.borrow().get(&sp
)
346 tcx
.sess
.parse_sess
.expr_parentheses_needed(&mut err
, *sp
, None
);
349 oprnd_t
= tcx
.ty_error();
352 hir
::UnOp
::UnNot
=> {
353 let result
= self.check_user_unop(expr
, oprnd_t
, unop
);
354 // If it's builtin, we can reuse the type, this helps inference.
355 if !(oprnd_t
.is_integral() || *oprnd_t
.kind() == ty
::Bool
) {
359 hir
::UnOp
::UnNeg
=> {
360 let result
= self.check_user_unop(expr
, oprnd_t
, unop
);
361 // If it's builtin, we can reuse the type, this helps inference.
362 if !oprnd_t
.is_numeric() {
371 fn check_expr_addr_of(
373 kind
: hir
::BorrowKind
,
374 mutbl
: hir
::Mutability
,
375 oprnd
: &'tcx hir
::Expr
<'tcx
>,
376 expected
: Expectation
<'tcx
>,
377 expr
: &'tcx hir
::Expr
<'tcx
>,
379 let hint
= expected
.only_has_type(self).map_or(NoExpectation
, |ty
| {
381 ty
::Ref(_
, ty
, _
) | ty
::RawPtr(ty
::TypeAndMut { ty, .. }
) => {
382 if oprnd
.is_syntactic_place_expr() {
383 // Places may legitimately have unsized types.
384 // For example, dereferences of a fat pointer and
385 // the last field of a struct can be unsized.
388 Expectation
::rvalue_hint(self, ty
)
395 self.check_expr_with_expectation_and_needs(&oprnd
, hint
, Needs
::maybe_mut_place(mutbl
));
397 let tm
= ty
::TypeAndMut { ty, mutbl }
;
399 _
if tm
.ty
.references_error() => self.tcx
.ty_error(),
400 hir
::BorrowKind
::Raw
=> {
401 self.check_named_place_expr(oprnd
);
404 hir
::BorrowKind
::Ref
=> {
405 // Note: at this point, we cannot say what the best lifetime
406 // is to use for resulting pointer. We want to use the
407 // shortest lifetime possible so as to avoid spurious borrowck
408 // errors. Moreover, the longest lifetime will depend on the
409 // precise details of the value whose address is being taken
410 // (and how long it is valid), which we don't know yet until
411 // type inference is complete.
413 // Therefore, here we simply generate a region variable. The
414 // region inferencer will then select a suitable value.
415 // Finally, borrowck will infer the value of the region again,
416 // this time with enough precision to check that the value
417 // whose address was taken can actually be made to live as long
418 // as it needs to live.
419 let region
= self.next_region_var(infer
::AddrOfRegion(expr
.span
));
420 self.tcx
.mk_ref(region
, tm
)
425 /// Does this expression refer to a place that either:
426 /// * Is based on a local or static.
427 /// * Contains a dereference
428 /// Note that the adjustments for the children of `expr` should already
429 /// have been resolved.
430 fn check_named_place_expr(&self, oprnd
: &'tcx hir
::Expr
<'tcx
>) {
431 let is_named
= oprnd
.is_place_expr(|base
| {
432 // Allow raw borrows if there are any deref adjustments.
434 // const VAL: (i32,) = (0,);
435 // const REF: &(i32,) = &(0,);
437 // &raw const VAL.0; // ERROR
438 // &raw const REF.0; // OK, same as &raw const (*REF).0;
440 // This is maybe too permissive, since it allows
441 // `let u = &raw const Box::new((1,)).0`, which creates an
442 // immediately dangling raw pointer.
447 .map_or(false, |x
| x
.iter().any(|adj
| matches
!(adj
.kind
, Adjust
::Deref(_
))))
450 self.tcx
.sess
.emit_err(AddressOfTemporaryTaken { span: oprnd.span }
)
454 fn check_lang_item_path(
456 lang_item
: hir
::LangItem
,
457 expr
: &'tcx hir
::Expr
<'tcx
>,
459 self.resolve_lang_item_path(lang_item
, expr
.span
, expr
.hir_id
).1
462 fn check_expr_path(&self, qpath
: &hir
::QPath
<'_
>, expr
: &'tcx hir
::Expr
<'tcx
>) -> Ty
<'tcx
> {
464 let (res
, opt_ty
, segs
) = self.resolve_ty_and_res_ufcs(qpath
, expr
.hir_id
, expr
.span
);
467 self.set_tainted_by_errors();
470 Res
::Def(DefKind
::Ctor(_
, CtorKind
::Fictive
), _
) => {
471 report_unexpected_variant_res(tcx
, res
, expr
.span
);
474 _
=> self.instantiate_value_path(segs
, opt_ty
, res
, expr
.span
, expr
.hir_id
).0,
477 if let ty
::FnDef(..) = ty
.kind() {
478 let fn_sig
= ty
.fn_sig(tcx
);
479 if !tcx
.features().unsized_fn_params
{
480 // We want to remove some Sized bounds from std functions,
481 // but don't want to expose the removal to stable Rust.
482 // i.e., we don't want to allow
488 // to work in stable even if the Sized bound on `drop` is relaxed.
489 for i
in 0..fn_sig
.inputs().skip_binder().len() {
490 // We just want to check sizedness, so instead of introducing
491 // placeholder lifetimes with probing, we just replace higher lifetimes
494 .replace_bound_vars_with_fresh_vars(
496 infer
::LateBoundRegionConversionTime
::FnCall
,
500 self.require_type_is_sized_deferred(
503 traits
::SizedArgumentType(None
),
507 // Here we want to prevent struct constructors from returning unsized types.
508 // There were two cases this happened: fn pointer coercion in stable
509 // and usual function call in presence of unsized_locals.
510 // Also, as we just want to check sizedness, instead of introducing
511 // placeholder lifetimes with probing, we just replace higher lifetimes
514 .replace_bound_vars_with_fresh_vars(
516 infer
::LateBoundRegionConversionTime
::FnCall
,
520 self.require_type_is_sized_deferred(output
, expr
.span
, traits
::SizedReturnType
);
523 // We always require that the type provided as the value for
524 // a type parameter outlives the moment of instantiation.
525 let substs
= self.typeck_results
.borrow().node_substs(expr
.hir_id
);
526 self.add_wf_bounds(substs
, expr
);
533 destination
: hir
::Destination
,
534 expr_opt
: Option
<&'tcx hir
::Expr
<'tcx
>>,
535 expr
: &'tcx hir
::Expr
<'tcx
>,
538 if let Ok(target_id
) = destination
.target_id
{
540 if let Some(ref e
) = expr_opt
{
541 // If this is a break with a value, we need to type-check
542 // the expression. Get an expected type from the loop context.
543 let opt_coerce_to
= {
544 // We should release `enclosing_breakables` before the `check_expr_with_hint`
545 // below, so can't move this block of code to the enclosing scope and share
546 // `ctxt` with the second `encloding_breakables` borrow below.
547 let mut enclosing_breakables
= self.enclosing_breakables
.borrow_mut();
548 match enclosing_breakables
.opt_find_breakable(target_id
) {
549 Some(ctxt
) => ctxt
.coerce
.as_ref().map(|coerce
| coerce
.expected_ty()),
551 // Avoid ICE when `break` is inside a closure (#65383).
552 return tcx
.ty_error_with_message(
554 "break was outside loop, but no error was emitted",
560 // If the loop context is not a `loop { }`, then break with
561 // a value is illegal, and `opt_coerce_to` will be `None`.
562 // Just set expectation to error in that case.
563 let coerce_to
= opt_coerce_to
.unwrap_or_else(|| tcx
.ty_error());
565 // Recurse without `enclosing_breakables` borrowed.
566 e_ty
= self.check_expr_with_hint(e
, coerce_to
);
567 cause
= self.misc(e
.span
);
569 // Otherwise, this is a break *without* a value. That's
570 // always legal, and is equivalent to `break ()`.
571 e_ty
= tcx
.mk_unit();
572 cause
= self.misc(expr
.span
);
575 // Now that we have type-checked `expr_opt`, borrow
576 // the `enclosing_loops` field and let's coerce the
577 // type of `expr_opt` into what is expected.
578 let mut enclosing_breakables
= self.enclosing_breakables
.borrow_mut();
579 let ctxt
= match enclosing_breakables
.opt_find_breakable(target_id
) {
582 // Avoid ICE when `break` is inside a closure (#65383).
583 return tcx
.ty_error_with_message(
585 "break was outside loop, but no error was emitted",
590 if let Some(ref mut coerce
) = ctxt
.coerce
{
591 if let Some(ref e
) = expr_opt
{
592 coerce
.coerce(self, &cause
, e
, e_ty
);
594 assert
!(e_ty
.is_unit());
595 let ty
= coerce
.expected_ty();
596 coerce
.coerce_forced_unit(
600 self.suggest_mismatched_types_on_tail(
601 &mut err
, expr
, ty
, e_ty
, cause
.span
, target_id
,
603 if let Some(val
) = ty_kind_suggestion(ty
) {
604 let label
= destination
606 .map(|l
| format
!(" {}", l
.ident
))
607 .unwrap_or_else(String
::new
);
610 "give it a value of the expected type",
611 format
!("break{} {}", label
, val
),
612 Applicability
::HasPlaceholders
,
620 // If `ctxt.coerce` is `None`, we can just ignore
621 // the type of the expression. This is because
622 // either this was a break *without* a value, in
623 // which case it is always a legal type (`()`), or
624 // else an error would have been flagged by the
625 // `loops` pass for using break with an expression
626 // where you are not supposed to.
627 assert
!(expr_opt
.is_none() || self.tcx
.sess
.has_errors());
630 // If we encountered a `break`, then (no surprise) it may be possible to break from the
631 // loop... unless the value being returned from the loop diverges itself, e.g.
632 // `break return 5` or `break loop {}`.
633 ctxt
.may_break
|= !self.diverges
.get().is_always();
635 // the type of a `break` is always `!`, since it diverges
638 // Otherwise, we failed to find the enclosing loop;
639 // this can only happen if the `break` was not
640 // inside a loop at all, which is caught by the
641 // loop-checking pass.
642 let err
= self.tcx
.ty_error_with_message(
644 "break was outside loop, but no error was emitted",
647 // We still need to assign a type to the inner expression to
648 // prevent the ICE in #43162.
649 if let Some(ref e
) = expr_opt
{
650 self.check_expr_with_hint(e
, err
);
652 // ... except when we try to 'break rust;'.
653 // ICE this expression in particular (see #43162).
654 if let ExprKind
::Path(QPath
::Resolved(_
, ref path
)) = e
.kind
{
655 if path
.segments
.len() == 1 && path
.segments
[0].ident
.name
== sym
::rust
{
656 fatally_break_rust(self.tcx
.sess
);
661 // There was an error; make type-check fail.
666 fn check_expr_return(
668 expr_opt
: Option
<&'tcx hir
::Expr
<'tcx
>>,
669 expr
: &'tcx hir
::Expr
<'tcx
>,
671 if self.ret_coercion
.is_none() {
672 self.tcx
.sess
.emit_err(ReturnStmtOutsideOfFnBody { span: expr.span }
);
673 } else if let Some(ref e
) = expr_opt
{
674 if self.ret_coercion_span
.borrow().is_none() {
675 *self.ret_coercion_span
.borrow_mut() = Some(e
.span
);
677 self.check_return_expr(e
);
679 let mut coercion
= self.ret_coercion
.as_ref().unwrap().borrow_mut();
680 if self.ret_coercion_span
.borrow().is_none() {
681 *self.ret_coercion_span
.borrow_mut() = Some(expr
.span
);
683 let cause
= self.cause(expr
.span
, ObligationCauseCode
::ReturnNoExpression
);
684 if let Some((fn_decl
, _
)) = self.get_fn_decl(expr
.hir_id
) {
685 coercion
.coerce_forced_unit(
689 let span
= fn_decl
.output
.span();
690 if let Ok(snippet
) = self.tcx
.sess
.source_map().span_to_snippet(span
) {
693 format
!("expected `{}` because of this return type", snippet
),
700 coercion
.coerce_forced_unit(self, &cause
, &mut |_
| (), true);
706 pub(super) fn check_return_expr(&self, return_expr
: &'tcx hir
::Expr
<'tcx
>) {
707 let ret_coercion
= self.ret_coercion
.as_ref().unwrap_or_else(|| {
708 span_bug
!(return_expr
.span
, "check_return_expr called outside fn body")
711 let ret_ty
= ret_coercion
.borrow().expected_ty();
712 let return_expr_ty
= self.check_expr_with_hint(return_expr
, ret_ty
.clone());
713 ret_coercion
.borrow_mut().coerce(
715 &self.cause(return_expr
.span
, ObligationCauseCode
::ReturnValue(return_expr
.hir_id
)),
721 pub(crate) fn check_lhs_assignable(
723 lhs
: &'tcx hir
::Expr
<'tcx
>,
724 err_code
: &'
static str,
727 if lhs
.is_syntactic_place_expr() {
731 // FIXME: Make this use SessionDiagnostic once error codes can be dynamically set.
732 let mut err
= self.tcx
.sess
.struct_span_err_with_code(
734 "invalid left-hand side of assignment",
735 DiagnosticId
::Error(err_code
.into()),
737 err
.span_label(lhs
.span
, "cannot assign to this expression");
741 /// Type check assignment expression `expr` of form `lhs = rhs`.
742 /// The expected type is `()` and is passsed to the function for the purposes of diagnostics.
743 fn check_expr_assign(
745 expr
: &'tcx hir
::Expr
<'tcx
>,
746 expected
: Expectation
<'tcx
>,
747 lhs
: &'tcx hir
::Expr
<'tcx
>,
748 rhs
: &'tcx hir
::Expr
<'tcx
>,
751 let expected_ty
= expected
.coercion_target_type(self, expr
.span
);
752 if expected_ty
== self.tcx
.types
.bool
{
753 // The expected type is `bool` but this will result in `()` so we can reasonably
754 // say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.
755 // The likely cause of this is `if foo = bar { .. }`.
756 let actual_ty
= self.tcx
.mk_unit();
757 let mut err
= self.demand_suptype_diag(expr
.span
, expected_ty
, actual_ty
).unwrap();
758 let lhs_ty
= self.check_expr(&lhs
);
759 let rhs_ty
= self.check_expr(&rhs
);
760 let (applicability
, eq
) = if self.can_coerce(rhs_ty
, lhs_ty
) {
761 (Applicability
::MachineApplicable
, true)
763 (Applicability
::MaybeIncorrect
, false)
765 if !lhs
.is_syntactic_place_expr() {
766 // Do not suggest `if let x = y` as `==` is way more likely to be the intention.
767 if let hir
::Node
::Expr(hir
::Expr
{
772 hir
::MatchSource
::IfDesugar { .. }
| hir
::MatchSource
::WhileDesugar
,
775 }) = self.tcx
.hir().get(
776 self.tcx
.hir().get_parent_node(self.tcx
.hir().get_parent_node(expr
.hir_id
)),
778 // Likely `if let` intended.
779 err
.span_suggestion_verbose(
780 expr
.span
.shrink_to_lo(),
781 "you might have meant to use pattern matching",
788 err
.span_suggestion_verbose(
790 "you might have meant to compare for equality",
796 if self.sess().if_let_suggestions
.borrow().get(&expr
.span
).is_some() {
797 // We already emitted an `if let` suggestion due to an identifier not found.
802 return self.tcx
.ty_error();
805 self.check_lhs_assignable(lhs
, "E0070", span
);
807 let lhs_ty
= self.check_expr_with_needs(&lhs
, Needs
::MutPlace
);
808 let rhs_ty
= self.check_expr_coercable_to_type(&rhs
, lhs_ty
, Some(lhs
));
810 self.require_type_is_sized(lhs_ty
, lhs
.span
, traits
::AssignmentLhsSized
);
812 if lhs_ty
.references_error() || rhs_ty
.references_error() {
821 body
: &'tcx hir
::Block
<'tcx
>,
822 source
: hir
::LoopSource
,
823 expected
: Expectation
<'tcx
>,
824 expr
: &'tcx hir
::Expr
<'tcx
>,
826 let coerce
= match source
{
827 // you can only use break with a value from a normal `loop { }`
828 hir
::LoopSource
::Loop
=> {
829 let coerce_to
= expected
.coercion_target_type(self, body
.span
);
830 Some(CoerceMany
::new(coerce_to
))
833 hir
::LoopSource
::While
| hir
::LoopSource
::WhileLet
| hir
::LoopSource
::ForLoop
=> None
,
836 let ctxt
= BreakableCtxt
{
838 may_break
: false, // Will get updated if/when we find a `break`.
841 let (ctxt
, ()) = self.with_breakable_ctxt(expr
.hir_id
, ctxt
, || {
842 self.check_block_no_value(&body
);
846 // No way to know whether it's diverging because
847 // of a `break` or an outer `break` or `return`.
848 self.diverges
.set(Diverges
::Maybe
);
851 // If we permit break with a value, then result type is
852 // the LUB of the breaks (possibly ! if none); else, it
853 // is nil. This makes sense because infinite loops
854 // (which would have type !) are only possible iff we
855 // permit break with a value [1].
856 if ctxt
.coerce
.is_none() && !ctxt
.may_break
{
858 self.tcx
.sess
.delay_span_bug(body
.span
, "no coercion, but loop may not break");
860 ctxt
.coerce
.map(|c
| c
.complete(self)).unwrap_or_else(|| self.tcx
.mk_unit())
863 /// Checks a method call.
864 fn check_method_call(
866 expr
: &'tcx hir
::Expr
<'tcx
>,
867 segment
: &hir
::PathSegment
<'_
>,
869 args
: &'tcx
[hir
::Expr
<'tcx
>],
870 expected
: Expectation
<'tcx
>,
873 let rcvr_t
= self.check_expr(&rcvr
);
874 // no need to check for bot/err -- callee does that
875 let rcvr_t
= self.structurally_resolved_type(args
[0].span
, rcvr_t
);
877 let method
= match self.lookup_method(rcvr_t
, segment
, span
, expr
, rcvr
) {
879 // We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to
880 // trigger this codepath causing `structuraly_resolved_type` to emit an error.
882 self.write_method_call(expr
.hir_id
, method
);
886 if segment
.ident
.name
!= kw
::Invalid
{
887 self.report_extended_method_error(segment
, span
, args
, rcvr_t
, error
);
893 // Call the generic checker.
894 self.check_method_argument_types(
904 fn report_extended_method_error(
906 segment
: &hir
::PathSegment
<'_
>,
908 args
: &'tcx
[hir
::Expr
<'tcx
>],
910 error
: MethodError
<'tcx
>,
913 let try_alt_rcvr
= |err
: &mut DiagnosticBuilder
<'_
>, new_rcvr_t
| {
914 if let Some(new_rcvr_t
) = new_rcvr_t
{
915 if let Ok(pick
) = self.lookup_probe(
920 probe
::ProbeScope
::AllTraits
,
922 debug
!("try_alt_rcvr: pick candidate {:?}", pick
);
923 // Make sure the method is defined for the *actual* receiver:
924 // we don't want to treat `Box<Self>` as a receiver if
925 // it only works because of an autoderef to `&self`
926 if pick
.autoderefs
== 0 {
928 pick
.item
.ident
.span
,
929 &format
!("the method is available for `{}` here", new_rcvr_t
),
936 if let Some(mut err
) = self.report_method_error(
940 SelfSource
::MethodCall(rcvr
),
944 if let ty
::Adt(..) = rcvr_t
.kind() {
945 // Try alternative arbitrary self types that could fulfill this call.
946 // FIXME: probe for all types that *could* be arbitrary self-types, not
948 try_alt_rcvr(&mut err
, self.tcx
.mk_lang_item(rcvr_t
, LangItem
::OwnedBox
));
949 try_alt_rcvr(&mut err
, self.tcx
.mk_lang_item(rcvr_t
, LangItem
::Pin
));
950 try_alt_rcvr(&mut err
, self.tcx
.mk_diagnostic_item(rcvr_t
, sym
::Arc
));
951 try_alt_rcvr(&mut err
, self.tcx
.mk_diagnostic_item(rcvr_t
, sym
::Rc
));
959 e
: &'tcx hir
::Expr
<'tcx
>,
960 t
: &'tcx hir
::Ty
<'tcx
>,
961 expr
: &'tcx hir
::Expr
<'tcx
>,
963 // Find the type of `e`. Supply hints based on the type we are casting to,
965 let t_cast
= self.to_ty_saving_user_provided_ty(t
);
966 let t_cast
= self.resolve_vars_if_possible(&t_cast
);
967 let t_expr
= self.check_expr_with_expectation(e
, ExpectCastableToType(t_cast
));
968 let t_cast
= self.resolve_vars_if_possible(&t_cast
);
970 // Eagerly check for some obvious errors.
971 if t_expr
.references_error() || t_cast
.references_error() {
974 // Defer other checks until we're done type checking.
975 let mut deferred_cast_checks
= self.deferred_cast_checks
.borrow_mut();
976 match cast
::CastCheck
::new(self, e
, t_expr
, t_cast
, t
.span
, expr
.span
) {
978 deferred_cast_checks
.push(cast_check
);
981 Err(ErrorReported
) => self.tcx
.ty_error(),
988 args
: &'tcx
[hir
::Expr
<'tcx
>],
989 expected
: Expectation
<'tcx
>,
990 expr
: &'tcx hir
::Expr
<'tcx
>,
992 let element_ty
= if !args
.is_empty() {
993 let coerce_to
= expected
995 .and_then(|uty
| match *uty
.kind() {
996 ty
::Array(ty
, _
) | ty
::Slice(ty
) => Some(ty
),
1000 self.next_ty_var(TypeVariableOrigin
{
1001 kind
: TypeVariableOriginKind
::TypeInference
,
1005 let mut coerce
= CoerceMany
::with_coercion_sites(coerce_to
, args
);
1006 assert_eq
!(self.diverges
.get(), Diverges
::Maybe
);
1008 let e_ty
= self.check_expr_with_hint(e
, coerce_to
);
1009 let cause
= self.misc(e
.span
);
1010 coerce
.coerce(self, &cause
, e
, e_ty
);
1012 coerce
.complete(self)
1014 self.next_ty_var(TypeVariableOrigin
{
1015 kind
: TypeVariableOriginKind
::TypeInference
,
1019 self.tcx
.mk_array(element_ty
, args
.len() as u64)
1022 fn check_expr_repeat(
1024 element
: &'tcx hir
::Expr
<'tcx
>,
1025 count
: &'tcx hir
::AnonConst
,
1026 expected
: Expectation
<'tcx
>,
1027 _expr
: &'tcx hir
::Expr
<'tcx
>,
1030 let count
= self.to_const(count
);
1032 let uty
= match expected
{
1033 ExpectHasType(uty
) => match *uty
.kind() {
1034 ty
::Array(ty
, _
) | ty
::Slice(ty
) => Some(ty
),
1040 let (element_ty
, t
) = match uty
{
1042 self.check_expr_coercable_to_type(&element
, uty
, None
);
1046 let ty
= self.next_ty_var(TypeVariableOrigin
{
1047 kind
: TypeVariableOriginKind
::MiscVariable
,
1050 let element_ty
= self.check_expr_has_type_or_error(&element
, ty
, |_
| {}
);
1055 if element_ty
.references_error() {
1056 return tcx
.ty_error();
1059 tcx
.mk_ty(ty
::Array(t
, count
))
1062 fn check_expr_tuple(
1064 elts
: &'tcx
[hir
::Expr
<'tcx
>],
1065 expected
: Expectation
<'tcx
>,
1066 expr
: &'tcx hir
::Expr
<'tcx
>,
1068 let flds
= expected
.only_has_type(self).and_then(|ty
| {
1069 let ty
= self.resolve_vars_with_obligations(ty
);
1071 ty
::Tuple(ref flds
) => Some(&flds
[..]),
1076 let elt_ts_iter
= elts
.iter().enumerate().map(|(i
, e
)| match flds
{
1077 Some(ref fs
) if i
< fs
.len() => {
1078 let ety
= fs
[i
].expect_ty();
1079 self.check_expr_coercable_to_type(&e
, ety
, None
);
1082 _
=> self.check_expr_with_expectation(&e
, NoExpectation
),
1084 let tuple
= self.tcx
.mk_tup(elt_ts_iter
);
1085 if tuple
.references_error() {
1088 self.require_type_is_sized(tuple
, expr
.span
, traits
::TupleInitializerSized
);
1093 fn check_expr_struct(
1095 expr
: &hir
::Expr
<'_
>,
1096 expected
: Expectation
<'tcx
>,
1098 fields
: &'tcx
[hir
::Field
<'tcx
>],
1099 base_expr
: &'tcx Option
<&'tcx hir
::Expr
<'tcx
>>,
1101 // Find the relevant variant
1102 let (variant
, adt_ty
) = if let Some(variant_ty
) = self.check_struct_path(qpath
, expr
.hir_id
)
1106 self.check_struct_fields_on_error(fields
, base_expr
);
1107 return self.tcx
.ty_error();
1110 // Prohibit struct expressions when non-exhaustive flag is set.
1111 let adt
= adt_ty
.ty_adt_def().expect("`check_struct_path` returned non-ADT type");
1112 if !adt
.did
.is_local() && variant
.is_field_list_non_exhaustive() {
1115 .emit_err(StructExprNonExhaustive { span: expr.span, what: adt.variant_descr() }
);
1118 let error_happened
= self.check_expr_struct_fields(
1125 base_expr
.is_none(),
1127 if let &Some(ref base_expr
) = base_expr
{
1128 // If check_expr_struct_fields hit an error, do not attempt to populate
1129 // the fields with the base_expr. This could cause us to hit errors later
1130 // when certain fields are assumed to exist that in fact do not.
1131 if !error_happened
{
1132 self.check_expr_has_type_or_error(base_expr
, adt_ty
, |_
| {}
);
1133 match adt_ty
.kind() {
1134 ty
::Adt(adt
, substs
) if adt
.is_struct() => {
1135 let fru_field_types
= adt
1140 self.normalize_associated_types_in(
1142 &f
.ty(self.tcx
, substs
),
1149 .fru_field_types_mut()
1150 .insert(expr
.hir_id
, fru_field_types
);
1155 .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span }
);
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 tcx
.sess
.emit_err(FieldMultiplySpecifiedInInitializer
{
1219 span
: field
.ident
.span
,
1220 prev_span
: *prev_span
,
1224 self.report_unknown_field(adt_ty
, variant
, field
, ast_fields
, kind_name
, span
);
1230 // Make sure to give a type to the field even if there's
1231 // an error, so we can continue type-checking.
1232 self.check_expr_coercable_to_type(&field
.expr
, field_type
, None
);
1235 // Make sure the programmer specified correct number of fields.
1236 if kind_name
== "union" {
1237 if ast_fields
.len() != 1 {
1238 tcx
.sess
.span_err(span
, "union expressions should have exactly one field");
1240 } else if check_completeness
&& !error_happened
&& !remaining_fields
.is_empty() {
1241 let no_accessible_remaining_fields
= remaining_fields
1243 .find(|(_
, (_
, field
))| {
1244 field
.vis
.is_accessible_from(tcx
.parent_module(expr_id
).to_def_id(), tcx
)
1248 if no_accessible_remaining_fields
{
1249 self.report_no_accessible_fields(adt_ty
, span
);
1251 self.report_missing_field(adt_ty
, span
, remaining_fields
);
1258 fn check_struct_fields_on_error(
1260 fields
: &'tcx
[hir
::Field
<'tcx
>],
1261 base_expr
: &'tcx Option
<&'tcx hir
::Expr
<'tcx
>>,
1263 for field
in fields
{
1264 self.check_expr(&field
.expr
);
1266 if let Some(ref base
) = *base_expr
{
1267 self.check_expr(&base
);
1271 /// Report an error for a struct field expression when there are fields which aren't provided.
1274 /// error: missing field `you_can_use_this_field` in initializer of `foo::Foo`
1275 /// --> src/main.rs:8:5
1277 /// 8 | foo::Foo {};
1278 /// | ^^^^^^^^ missing `you_can_use_this_field`
1280 /// error: aborting due to previous error
1282 fn report_missing_field(
1286 remaining_fields
: FxHashMap
<Ident
, (usize, &ty
::FieldDef
)>,
1289 let len
= remaining_fields
.len();
1291 let mut displayable_field_names
=
1292 remaining_fields
.keys().map(|ident
| ident
.as_str()).collect
::<Vec
<_
>>();
1294 displayable_field_names
.sort();
1296 let truncated_fields_error
= if len
<= 3 {
1299 format
!(" and {} other field{}", (len
- 3), if len
- 3 == 1 { "" }
else { "s" }
)
1302 let remaining_fields_names
= displayable_field_names
1305 .map(|n
| format
!("`{}`", n
))
1306 .collect
::<Vec
<_
>>()
1313 "missing field{} {}{} in initializer of `{}`",
1314 pluralize
!(remaining_fields
.len()),
1315 remaining_fields_names
,
1316 truncated_fields_error
,
1319 .span_label(span
, format
!("missing {}{}", remaining_fields_names
, truncated_fields_error
))
1323 /// Report an error for a struct field expression when there are no visible fields.
1326 /// error: cannot construct `Foo` with struct literal syntax due to inaccessible fields
1327 /// --> src/main.rs:8:5
1329 /// 8 | foo::Foo {};
1332 /// error: aborting due to previous error
1334 fn report_no_accessible_fields(&self, adt_ty
: Ty
<'tcx
>, span
: Span
) {
1335 self.tcx
.sess
.span_err(
1338 "cannot construct `{}` with struct literal syntax due to inaccessible fields",
1344 fn report_unknown_field(
1347 variant
: &'tcx ty
::VariantDef
,
1348 field
: &hir
::Field
<'_
>,
1349 skip_fields
: &[hir
::Field
<'_
>],
1353 if variant
.is_recovered() {
1354 self.set_tainted_by_errors();
1357 let mut err
= self.type_error_struct_with_diag(
1359 |actual
| match ty
.kind() {
1360 ty
::Adt(adt
, ..) if adt
.is_enum() => struct_span_err
!(
1364 "{} `{}::{}` has no field named `{}`",
1370 _
=> struct_span_err
!(
1374 "{} `{}` has no field named `{}`",
1382 match variant
.ctor_kind
{
1384 err
.span_label(variant
.ident
.span
, format
!("`{adt}` defined here", adt
= ty
));
1385 err
.span_label(field
.ident
.span
, "field does not exist");
1389 "`{adt}` is a tuple {kind_name}, \
1390 use the appropriate syntax: `{adt}(/* fields */)`",
1392 kind_name
= kind_name
1397 // prevent all specified fields from being suggested
1398 let skip_fields
= skip_fields
.iter().map(|ref x
| x
.ident
.name
);
1399 if let Some(field_name
) =
1400 Self::suggest_field_name(variant
, field
.ident
.name
, skip_fields
.collect())
1402 err
.span_suggestion(
1404 "a field with a similar name exists",
1405 field_name
.to_string(),
1406 Applicability
::MaybeIncorrect
,
1410 ty
::Adt(adt
, ..) => {
1414 format
!("`{}::{}` does not have this field", ty
, variant
.ident
),
1419 format
!("`{}` does not have this field", ty
),
1422 let available_field_names
= self.available_field_names(variant
);
1423 if !available_field_names
.is_empty() {
1425 "available fields are: {}",
1426 self.name_series_display(available_field_names
)
1430 _
=> bug
!("non-ADT passed to report_unknown_field"),
1438 // Return an hint about the closest match in field names
1439 fn suggest_field_name(
1440 variant
: &'tcx ty
::VariantDef
,
1443 ) -> Option
<Symbol
> {
1444 let names
= variant
.fields
.iter().filter_map(|field
| {
1445 // ignore already set fields and private fields from non-local crates
1446 if skip
.iter().any(|&x
| x
== field
.ident
.name
)
1447 || (!variant
.def_id
.is_local() && field
.vis
!= Visibility
::Public
)
1451 Some(&field
.ident
.name
)
1455 find_best_match_for_name(names
, field
, None
)
1458 fn available_field_names(&self, variant
: &'tcx ty
::VariantDef
) -> Vec
<Symbol
> {
1463 let def_scope
= self
1465 .adjust_ident_and_get_scope(field
.ident
, variant
.def_id
, self.body_id
)
1467 field
.vis
.is_accessible_from(def_scope
, self.tcx
)
1469 .map(|field
| field
.ident
.name
)
1473 fn name_series_display(&self, names
: Vec
<Symbol
>) -> String
{
1474 // dynamic limit, to never omit just one field
1475 let limit
= if names
.len() == 6 { 6 }
else { 5 }
;
1477 names
.iter().take(limit
).map(|n
| format
!("`{}`", n
)).collect
::<Vec
<_
>>().join(", ");
1478 if names
.len() > limit
{
1479 display
= format
!("{} ... and {} others", display
, names
.len() - limit
);
1484 // Check field access expressions
1487 expr
: &'tcx hir
::Expr
<'tcx
>,
1488 base
: &'tcx hir
::Expr
<'tcx
>,
1491 let expr_t
= self.check_expr(base
);
1492 let expr_t
= self.structurally_resolved_type(base
.span
, expr_t
);
1493 let mut private_candidate
= None
;
1494 let mut autoderef
= self.autoderef(expr
.span
, expr_t
);
1495 while let Some((base_t
, _
)) = autoderef
.next() {
1496 match base_t
.kind() {
1497 ty
::Adt(base_def
, substs
) if !base_def
.is_enum() => {
1498 debug
!("struct named {:?}", base_t
);
1499 let (ident
, def_scope
) =
1500 self.tcx
.adjust_ident_and_get_scope(field
, base_def
.did
, self.body_id
);
1501 let fields
= &base_def
.non_enum_variant().fields
;
1502 if let Some(index
) =
1503 fields
.iter().position(|f
| f
.ident
.normalize_to_macros_2_0() == ident
)
1505 let field
= &fields
[index
];
1506 let field_ty
= self.field_ty(expr
.span
, field
, substs
);
1507 // Save the index of all fields regardless of their visibility in case
1508 // of error recovery.
1509 self.write_field_index(expr
.hir_id
, index
);
1510 if field
.vis
.is_accessible_from(def_scope
, self.tcx
) {
1511 let adjustments
= self.adjust_steps(&autoderef
);
1512 self.apply_adjustments(base
, adjustments
);
1513 self.register_predicates(autoderef
.into_obligations());
1515 self.tcx
.check_stability(field
.did
, Some(expr
.hir_id
), expr
.span
);
1518 private_candidate
= Some((base_def
.did
, field_ty
));
1521 ty
::Tuple(ref tys
) => {
1522 let fstr
= field
.as_str();
1523 if let Ok(index
) = fstr
.parse
::<usize>() {
1524 if fstr
== index
.to_string() {
1525 if let Some(field_ty
) = tys
.get(index
) {
1526 let adjustments
= self.adjust_steps(&autoderef
);
1527 self.apply_adjustments(base
, adjustments
);
1528 self.register_predicates(autoderef
.into_obligations());
1530 self.write_field_index(expr
.hir_id
, index
);
1531 return field_ty
.expect_ty();
1539 self.structurally_resolved_type(autoderef
.span(), autoderef
.final_ty(false));
1541 if let Some((did
, field_ty
)) = private_candidate
{
1542 self.ban_private_field_access(expr
, expr_t
, field
, did
);
1546 if field
.name
== kw
::Invalid
{
1547 } else if self.method_exists(field
, expr_t
, expr
.hir_id
, true) {
1548 self.ban_take_value_of_method(expr
, expr_t
, field
);
1549 } else if !expr_t
.is_primitive_ty() {
1550 self.ban_nonexisting_field(field
, base
, expr
, expr_t
);
1557 "`{}` is a primitive type and therefore doesn't have fields",
1563 self.tcx().ty_error()
1566 fn suggest_await_on_field_access(
1568 err
: &mut DiagnosticBuilder
<'_
>,
1570 base
: &'tcx hir
::Expr
<'tcx
>,
1573 let output_ty
= match self.infcx
.get_impl_future_output_ty(ty
) {
1574 Some(output_ty
) => self.resolve_vars_if_possible(&output_ty
),
1577 let mut add_label
= true;
1578 if let ty
::Adt(def
, _
) = output_ty
.kind() {
1579 // no field access on enum type
1581 if def
.non_enum_variant().fields
.iter().any(|field
| field
.ident
== field_ident
) {
1585 "field not available in `impl Future`, but it is available in its `Output`",
1587 err
.span_suggestion_verbose(
1588 base
.span
.shrink_to_hi(),
1589 "consider `await`ing on the `Future` and access the field of its `Output`",
1590 ".await".to_string(),
1591 Applicability
::MaybeIncorrect
,
1597 err
.span_label(field_ident
.span
, &format
!("field not found in `{}`", ty
));
1601 fn ban_nonexisting_field(
1604 base
: &'tcx hir
::Expr
<'tcx
>,
1605 expr
: &'tcx hir
::Expr
<'tcx
>,
1609 "ban_nonexisting_field: field={:?}, base={:?}, expr={:?}, expr_ty={:?}",
1610 field
, base
, expr
, expr_t
1612 let mut err
= self.no_such_field_err(field
.span
, field
, expr_t
);
1614 match *expr_t
.peel_refs().kind() {
1615 ty
::Array(_
, len
) => {
1616 self.maybe_suggest_array_indexing(&mut err
, expr
, base
, field
, len
);
1619 self.suggest_first_deref_field(&mut err
, expr
, base
, field
);
1621 ty
::Adt(def
, _
) if !def
.is_enum() => {
1622 self.suggest_fields_on_recordish(&mut err
, def
, field
);
1624 ty
::Param(param_ty
) => {
1625 self.point_at_param_definition(&mut err
, param_ty
);
1627 ty
::Opaque(_
, _
) => {
1628 self.suggest_await_on_field_access(&mut err
, field
, base
, expr_t
.peel_refs());
1633 if field
.name
== kw
::Await
{
1634 // We know by construction that `<expr>.await` is either on Rust 2015
1635 // or results in `ExprKind::Await`. Suggest switching the edition to 2018.
1636 err
.note("to `.await` a `Future`, switch to Rust 2018");
1637 err
.help("set `edition = \"2018\"` in `Cargo.toml`");
1638 err
.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
1644 fn ban_private_field_access(
1646 expr
: &hir
::Expr
<'_
>,
1651 let struct_path
= self.tcx().def_path_str(base_did
);
1652 let kind_name
= self.tcx().def_kind(base_did
).descr(base_did
);
1653 let mut err
= struct_span_err
!(
1657 "field `{}` of {} `{}` is private",
1662 err
.span_label(field
.span
, "private field");
1663 // Also check if an accessible method exists, which is often what is meant.
1664 if self.method_exists(field
, expr_t
, expr
.hir_id
, false) && !self.expr_in_place(expr
.hir_id
)
1666 self.suggest_method_call(
1668 &format
!("a method `{}` also exists, call it with parentheses", field
),
1677 fn ban_take_value_of_method(&self, expr
: &hir
::Expr
<'_
>, expr_t
: Ty
<'tcx
>, field
: Ident
) {
1678 let mut err
= type_error_struct
!(
1683 "attempted to take value of method `{}` on type `{}`",
1687 err
.span_label(field
.span
, "method, not a field");
1688 if !self.expr_in_place(expr
.hir_id
) {
1689 self.suggest_method_call(
1691 "use parentheses to call the method",
1697 err
.help("methods are immutable and cannot be assigned to");
1703 fn point_at_param_definition(&self, err
: &mut DiagnosticBuilder
<'_
>, param
: ty
::ParamTy
) {
1704 let generics
= self.tcx
.generics_of(self.body_id
.owner
.to_def_id());
1705 let generic_param
= generics
.type_param(¶m
, self.tcx
);
1706 if let ty
::GenericParamDefKind
::Type { synthetic: Some(..), .. }
= generic_param
.kind
{
1709 let param_def_id
= generic_param
.def_id
;
1710 let param_hir_id
= match param_def_id
.as_local() {
1711 Some(x
) => self.tcx
.hir().local_def_id_to_hir_id(x
),
1714 let param_span
= self.tcx
.hir().span(param_hir_id
);
1715 let param_name
= self.tcx
.hir().ty_param_name(param_hir_id
);
1717 err
.span_label(param_span
, &format
!("type parameter '{}' declared here", param_name
));
1720 fn suggest_fields_on_recordish(
1722 err
: &mut DiagnosticBuilder
<'_
>,
1723 def
: &'tcx ty
::AdtDef
,
1726 if let Some(suggested_field_name
) =
1727 Self::suggest_field_name(def
.non_enum_variant(), field
.name
, vec
![])
1729 err
.span_suggestion(
1731 "a field with a similar name exists",
1732 suggested_field_name
.to_string(),
1733 Applicability
::MaybeIncorrect
,
1736 err
.span_label(field
.span
, "unknown field");
1737 let struct_variant_def
= def
.non_enum_variant();
1738 let field_names
= self.available_field_names(struct_variant_def
);
1739 if !field_names
.is_empty() {
1741 "available fields are: {}",
1742 self.name_series_display(field_names
),
1748 fn maybe_suggest_array_indexing(
1750 err
: &mut DiagnosticBuilder
<'_
>,
1751 expr
: &hir
::Expr
<'_
>,
1752 base
: &hir
::Expr
<'_
>,
1754 len
: &ty
::Const
<'tcx
>,
1756 if let (Some(len
), Ok(user_index
)) =
1757 (len
.try_eval_usize(self.tcx
, self.param_env
), field
.as_str().parse
::<u64>())
1759 if let Ok(base
) = self.tcx
.sess
.source_map().span_to_snippet(base
.span
) {
1760 let help
= "instead of using tuple indexing, use array indexing";
1761 let suggestion
= format
!("{}[{}]", base
, field
);
1762 let applicability
= if len
< user_index
{
1763 Applicability
::MachineApplicable
1765 Applicability
::MaybeIncorrect
1767 err
.span_suggestion(expr
.span
, help
, suggestion
, applicability
);
1772 fn suggest_first_deref_field(
1774 err
: &mut DiagnosticBuilder
<'_
>,
1775 expr
: &hir
::Expr
<'_
>,
1776 base
: &hir
::Expr
<'_
>,
1779 if let Ok(base
) = self.tcx
.sess
.source_map().span_to_snippet(base
.span
) {
1780 let msg
= format
!("`{}` is a raw pointer; try dereferencing it", base
);
1781 let suggestion
= format
!("(*{}).{}", base
, field
);
1782 err
.span_suggestion(expr
.span
, &msg
, suggestion
, Applicability
::MaybeIncorrect
);
1786 fn no_such_field_err
<T
: Display
>(
1790 expr_t
: &ty
::TyS
<'_
>,
1791 ) -> DiagnosticBuilder
<'_
> {
1797 "no field `{}` on type `{}`",
1803 fn check_expr_index(
1805 base
: &'tcx hir
::Expr
<'tcx
>,
1806 idx
: &'tcx hir
::Expr
<'tcx
>,
1807 expr
: &'tcx hir
::Expr
<'tcx
>,
1809 let base_t
= self.check_expr(&base
);
1810 let idx_t
= self.check_expr(&idx
);
1812 if base_t
.references_error() {
1814 } else if idx_t
.references_error() {
1817 let base_t
= self.structurally_resolved_type(base
.span
, base_t
);
1818 match self.lookup_indexing(expr
, base
, base_t
, idx_t
) {
1819 Some((index_ty
, element_ty
)) => {
1820 // two-phase not needed because index_ty is never mutable
1821 self.demand_coerce(idx
, idx_t
, index_ty
, None
, AllowTwoPhase
::No
);
1825 let mut err
= type_error_struct
!(
1830 "cannot index into a value of type `{}`",
1833 // Try to give some advice about indexing tuples.
1834 if let ty
::Tuple(..) = base_t
.kind() {
1835 let mut needs_note
= true;
1836 // If the index is an integer, we can show the actual
1837 // fixed expression:
1838 if let ExprKind
::Lit(ref lit
) = idx
.kind
{
1839 if let ast
::LitKind
::Int(i
, ast
::LitIntType
::Unsuffixed
) = lit
.node
{
1840 let snip
= self.tcx
.sess
.source_map().span_to_snippet(base
.span
);
1841 if let Ok(snip
) = snip
{
1842 err
.span_suggestion(
1844 "to access tuple elements, use",
1845 format
!("{}.{}", snip
, i
),
1846 Applicability
::MachineApplicable
,
1854 "to access tuple elements, use tuple indexing \
1855 syntax (e.g., `tuple.0`)",
1866 fn check_expr_yield(
1868 value
: &'tcx hir
::Expr
<'tcx
>,
1869 expr
: &'tcx hir
::Expr
<'tcx
>,
1870 src
: &'tcx hir
::YieldSource
,
1872 match self.resume_yield_tys
{
1873 Some((resume_ty
, yield_ty
)) => {
1874 self.check_expr_coercable_to_type(&value
, yield_ty
, None
);
1878 // Given that this `yield` expression was generated as a result of lowering a `.await`,
1879 // we know that the yield type must be `()`; however, the context won't contain this
1880 // information. Hence, we check the source of the yield expression here and check its
1881 // value's type against `()` (this check should always hold).
1882 None
if src
.is_await() => {
1883 self.check_expr_coercable_to_type(&value
, self.tcx
.mk_unit(), None
);
1887 self.tcx
.sess
.emit_err(YieldExprOutsideOfGenerator { span: expr.span }
);
1893 fn check_expr_asm_operand(&self, expr
: &'tcx hir
::Expr
<'tcx
>, is_input
: bool
) {
1894 let needs
= if is_input { Needs::None }
else { Needs::MutPlace }
;
1895 let ty
= self.check_expr_with_needs(expr
, needs
);
1896 self.require_type_is_sized(ty
, expr
.span
, traits
::InlineAsmSized
);
1898 if !is_input
&& !expr
.is_syntactic_place_expr() {
1899 let mut err
= self.tcx
.sess
.struct_span_err(expr
.span
, "invalid asm output");
1900 err
.span_label(expr
.span
, "cannot assign to this expression");
1904 // If this is an input value, we require its type to be fully resolved
1905 // at this point. This allows us to provide helpful coercions which help
1906 // pass the type candidate list in a later pass.
1908 // We don't require output types to be resolved at this point, which
1909 // allows them to be inferred based on how they are used later in the
1912 let ty
= self.structurally_resolved_type(expr
.span
, &ty
);
1915 let fnptr_ty
= self.tcx
.mk_fn_ptr(ty
.fn_sig(self.tcx
));
1916 self.demand_coerce(expr
, ty
, fnptr_ty
, None
, AllowTwoPhase
::No
);
1918 ty
::Ref(_
, base_ty
, mutbl
) => {
1919 let ptr_ty
= self.tcx
.mk_ptr(ty
::TypeAndMut { ty: base_ty, mutbl }
);
1920 self.demand_coerce(expr
, ty
, ptr_ty
, None
, AllowTwoPhase
::No
);
1927 fn check_expr_asm(&self, asm
: &'tcx hir
::InlineAsm
<'tcx
>) -> Ty
<'tcx
> {
1928 for op
in asm
.operands
{
1930 hir
::InlineAsmOperand
::In { expr, .. }
| hir
::InlineAsmOperand
::Const { expr }
=> {
1931 self.check_expr_asm_operand(expr
, true);
1933 hir
::InlineAsmOperand
::Out { expr, .. }
=> {
1934 if let Some(expr
) = expr
{
1935 self.check_expr_asm_operand(expr
, false);
1938 hir
::InlineAsmOperand
::InOut { expr, .. }
=> {
1939 self.check_expr_asm_operand(expr
, false);
1941 hir
::InlineAsmOperand
::SplitInOut { in_expr, out_expr, .. }
=> {
1942 self.check_expr_asm_operand(in_expr
, true);
1943 if let Some(out_expr
) = out_expr
{
1944 self.check_expr_asm_operand(out_expr
, false);
1947 hir
::InlineAsmOperand
::Sym { expr }
=> {
1948 self.check_expr(expr
);
1952 if asm
.options
.contains(ast
::InlineAsmOptions
::NORETURN
) {
1953 self.tcx
.types
.never
1960 pub(super) fn ty_kind_suggestion(ty
: Ty
<'_
>) -> Option
<&'
static str> {
1961 Some(match ty
.kind() {
1964 ty
::Int(_
) | ty
::Uint(_
) => "42",
1965 ty
::Float(_
) => "3.14159",
1966 ty
::Error(_
) | ty
::Never
=> return None
,