From a551fe08ef404ec0944aa91e3a368dc14e97153a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 15 Jun 2019 02:51:45 +0200 Subject: [PATCH] typeck/expr.rs: move check_expr_with_expectation_and_needs here. --- src/librustc_typeck/check/expr.rs | 61 ++++++++++++++++++++++++++++++- src/librustc_typeck/check/mod.rs | 59 ------------------------------ 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 3b755293a48a..f5102ae33c6d 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -34,7 +34,66 @@ use rustc::ty::subst::InternalSubsts; use rustc::traits::{self, ObligationCauseCode}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub(super) fn check_expr_kind( + /// Invariant: + /// If an expression has any sub-expressions that result in a type error, + /// inspecting that expression's type with `ty.references_error()` will return + /// true. Likewise, if an expression is known to diverge, inspecting its + /// type with `ty::type_is_bot` will return true (n.b.: since Rust is + /// strict, _|_ can appear in the type of an expression that does not, + /// itself, diverge: for example, fn() -> _|_.) + /// Note that inspecting a type's structure *directly* may expose the fact + /// that there are actually multiple representations for `Error`, so avoid + /// that when err needs to be handled differently. + pub(super) fn check_expr_with_expectation_and_needs( + &self, + expr: &'tcx hir::Expr, + expected: Expectation<'tcx>, + needs: Needs, + ) -> Ty<'tcx> { + debug!(">> type-checking: expr={:?} expected={:?}", + expr, expected); + + // Warn for expressions after diverging siblings. + self.warn_if_unreachable(expr.hir_id, expr.span, "expression"); + + // Hide the outer diverging and has_errors flags. + let old_diverges = self.diverges.get(); + let old_has_errors = self.has_errors.get(); + self.diverges.set(Diverges::Maybe); + self.has_errors.set(false); + + let ty = self.check_expr_kind(expr, expected, needs); + + // Warn for non-block expressions with diverging children. + match expr.node { + ExprKind::Block(..) | + ExprKind::Loop(..) | ExprKind::While(..) | + ExprKind::Match(..) => {} + + _ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression") + } + + // Any expression that produces a value of type `!` must have diverged + if ty.is_never() { + self.diverges.set(self.diverges.get() | Diverges::Always); + } + + // Record the type, which applies it effects. + // We need to do this after the warning above, so that + // we don't warn for the diverging expression itself. + self.write_ty(expr.hir_id, ty); + + // Combine the diverging and has_error flags. + self.diverges.set(self.diverges.get() | old_diverges); + self.has_errors.set(self.has_errors.get() | old_has_errors); + + debug!("type of {} is...", self.tcx.hir().hir_to_string(expr.hir_id)); + debug!("... {:?}, expected is {:?}", ty, expected); + + ty + } + + fn check_expr_kind( &self, expr: &'tcx hir::Expr, expected: Expectation<'tcx>, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 96654400eea2..8a3518c24dab 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3864,65 +3864,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - /// Invariant: - /// If an expression has any sub-expressions that result in a type error, - /// inspecting that expression's type with `ty.references_error()` will return - /// true. Likewise, if an expression is known to diverge, inspecting its - /// type with `ty::type_is_bot` will return true (n.b.: since Rust is - /// strict, _|_ can appear in the type of an expression that does not, - /// itself, diverge: for example, fn() -> _|_.) - /// Note that inspecting a type's structure *directly* may expose the fact - /// that there are actually multiple representations for `Error`, so avoid - /// that when err needs to be handled differently. - fn check_expr_with_expectation_and_needs( - &self, - expr: &'tcx hir::Expr, - expected: Expectation<'tcx>, - needs: Needs, - ) -> Ty<'tcx> { - debug!(">> type-checking: expr={:?} expected={:?}", - expr, expected); - - // Warn for expressions after diverging siblings. - self.warn_if_unreachable(expr.hir_id, expr.span, "expression"); - - // Hide the outer diverging and has_errors flags. - let old_diverges = self.diverges.get(); - let old_has_errors = self.has_errors.get(); - self.diverges.set(Diverges::Maybe); - self.has_errors.set(false); - - let ty = self.check_expr_kind(expr, expected, needs); - - // Warn for non-block expressions with diverging children. - match expr.node { - ExprKind::Block(..) | - ExprKind::Loop(..) | ExprKind::While(..) | - ExprKind::Match(..) => {} - - _ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression") - } - - // Any expression that produces a value of type `!` must have diverged - if ty.is_never() { - self.diverges.set(self.diverges.get() | Diverges::Always); - } - - // Record the type, which applies it effects. - // We need to do this after the warning above, so that - // we don't warn for the diverging expression itself. - self.write_ty(expr.hir_id, ty); - - // Combine the diverging and has_error flags. - self.diverges.set(self.diverges.get() | old_diverges); - self.has_errors.set(self.has_errors.get() | old_has_errors); - - debug!("type of {} is...", self.tcx.hir().hir_to_string(expr.hir_id)); - debug!("... {:?}, expected is {:?}", ty, expected); - - ty - } - // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary. // The newly resolved definition is written into `type_dependent_defs`. fn finish_resolving_struct_path(&self,