Skip to content

Commit

Permalink
typeck/expr.rs: move check_expr_with_expectation_and_needs here.
Browse files Browse the repository at this point in the history
  • Loading branch information
Centril committed Jun 15, 2019
1 parent 8fd2d12 commit a551fe0
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 60 deletions.
61 changes: 60 additions & 1 deletion src/librustc_typeck/check/expr.rs
Expand Up @@ -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>,
Expand Down
59 changes: 0 additions & 59 deletions src/librustc_typeck/check/mod.rs
Expand Up @@ -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,
Expand Down

0 comments on commit a551fe0

Please sign in to comment.