typeck/expr.rs: move check_expr_with_expectation_and_needs here.

This commit is contained in:
Mazdak Farrokhzad 2019-06-15 02:51:45 +02:00
parent 8fd2d12c25
commit a551fe08ef
2 changed files with 60 additions and 60 deletions

View file

@ -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>,

View file

@ -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,