Auto merge of #50351 - varkor:vestigial-never-conversion, r=nikomatsakis

Remove vestigial diverging !-coercion

Such conversions are no longer permitted. Fixes #50350.

r? @nikomatsakis
This commit is contained in:
bors 2018-05-15 10:34:45 +00:00
commit eca0da5985
4 changed files with 18 additions and 45 deletions

View File

@ -688,7 +688,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
arm_span: arm.body.span,
source: match_src
});
coercion.coerce(self, &cause, &arm.body, arm_ty, self.diverges.get());
coercion.coerce(self, &cause, &arm.body, arm_ty);
}
}

View File

@ -60,7 +60,7 @@
//! sort of a minor point so I've opted to leave it for later---after all
//! we may want to adjust precisely when coercions occur.
use check::{Diverges, FnCtxt, Needs};
use check::{FnCtxt, Needs};
use rustc::hir;
use rustc::hir::def_id::DefId;
@ -800,8 +800,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
exprs: &[E],
prev_ty: Ty<'tcx>,
new: &hir::Expr,
new_ty: Ty<'tcx>,
new_diverges: Diverges)
new_ty: Ty<'tcx>)
-> RelateResult<'tcx, Ty<'tcx>>
where E: AsCoercionSite
{
@ -809,13 +808,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let new_ty = self.resolve_type_vars_with_obligations(new_ty);
debug!("coercion::try_find_coercion_lub({:?}, {:?})", prev_ty, new_ty);
// Special-ish case: we can coerce any type `T` into the `!`
// type, but only if the source expression diverges.
if prev_ty.is_never() && new_diverges.always() {
debug!("permit coercion to `!` because expr diverges");
return Ok(prev_ty);
}
// Special-case that coercion alone cannot handle:
// Two function item types of differing IDs or Substs.
if let (&ty::TyFnDef(..), &ty::TyFnDef(..)) = (&prev_ty.sty, &new_ty.sty) {
@ -1054,14 +1046,12 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
fcx: &FnCtxt<'a, 'gcx, 'tcx>,
cause: &ObligationCause<'tcx>,
expression: &'gcx hir::Expr,
expression_ty: Ty<'tcx>,
expression_diverges: Diverges)
expression_ty: Ty<'tcx>)
{
self.coerce_inner(fcx,
cause,
Some(expression),
expression_ty,
expression_diverges,
None, false)
}
@ -1087,7 +1077,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
cause,
None,
fcx.tcx.mk_nil(),
Diverges::Maybe,
Some(augment_error),
label_unit_as_expected)
}
@ -1100,7 +1089,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
cause: &ObligationCause<'tcx>,
expression: Option<&'gcx hir::Expr>,
mut expression_ty: Ty<'tcx>,
expression_diverges: Diverges,
augment_error: Option<&mut FnMut(&mut DiagnosticBuilder)>,
label_expression_as_expected: bool)
{
@ -1134,15 +1122,13 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
exprs,
self.merged_ty(),
expression,
expression_ty,
expression_diverges),
expression_ty),
Expressions::UpFront(ref coercion_sites) =>
fcx.try_find_coercion_lub(cause,
&coercion_sites[0..self.pushed],
self.merged_ty(),
expression,
expression_ty,
expression_diverges),
expression_ty),
}
}
} else {

View File

@ -542,7 +542,7 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
/// you get indicates whether any subexpression that was
/// evaluating up to and including `X` diverged.
///
/// We use this flag for two purposes:
/// We currently use this flag only for diagnostic purposes:
///
/// - To warn about unreachable code: if, after processing a
/// sub-expression but before we have applied the effects of the
@ -556,16 +556,8 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
/// foo();}` or `{return; 22}`, where we would warn on the
/// `foo()` or `22`.
///
/// - To permit assignment into a local variable or other place
/// (including the "return slot") of type `!`. This is allowed
/// if **either** the type of value being assigned is `!`, which
/// means the current code is dead, **or** the expression's
/// diverging flag is true, which means that a diverging value was
/// wrapped (e.g., `let x: ! = foo(return)`).
///
/// To repeat the last point: an expression represents dead-code
/// if, after checking it, **either** its type is `!` OR the
/// diverges flag is set to something other than `Maybe`.
/// An expression represents dead-code if, after checking it,
/// the diverges flag is set to something other than `Maybe`.
diverges: Cell<Diverges>,
/// Whether any child nodes have any type errors.
@ -3002,8 +2994,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
&self.cause(return_expr.span,
ObligationCauseCode::ReturnType(return_expr.id)),
return_expr,
return_expr_ty,
self.diverges.get());
return_expr_ty);
}
@ -3034,13 +3025,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let mut coerce: DynamicCoerceMany = CoerceMany::new(coerce_to_ty);
let if_cause = self.cause(sp, ObligationCauseCode::IfExpression);
coerce.coerce(self, &if_cause, then_expr, then_ty, then_diverges);
coerce.coerce(self, &if_cause, then_expr, then_ty);
if let Some(else_expr) = opt_else_expr {
let else_ty = self.check_expr_with_expectation(else_expr, expected);
let else_diverges = self.diverges.get();
coerce.coerce(self, &if_cause, else_expr, else_ty, else_diverges);
coerce.coerce(self, &if_cause, else_expr, else_ty);
// We won't diverge unless both branches do (or the condition does).
self.diverges.set(cond_diverges | then_diverges & else_diverges);
@ -3733,7 +3724,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
hir::ExprBreak(destination, ref expr_opt) => {
if let Some(target_id) = destination.target_id.opt_id() {
let (e_ty, e_diverges, cause);
let (e_ty, cause);
if let Some(ref e) = *expr_opt {
// If this is a break with a value, we need to type-check
// the expression. Get an expected type from the loop context.
@ -3752,13 +3743,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Recurse without `enclosing_breakables` borrowed.
e_ty = self.check_expr_with_hint(e, coerce_to);
e_diverges = self.diverges.get();
cause = self.misc(e.span);
} else {
// Otherwise, this is a break *without* a value. That's
// always legal, and is equivalent to `break ()`.
e_ty = tcx.mk_nil();
e_diverges = Diverges::Maybe;
cause = self.misc(expr.span);
}
@ -3769,7 +3758,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let ctxt = enclosing_breakables.find_breakable(target_id);
if let Some(ref mut coerce) = ctxt.coerce {
if let Some(ref e) = *expr_opt {
coerce.coerce(self, &cause, e, e_ty, e_diverges);
coerce.coerce(self, &cause, e, e_ty);
} else {
assert!(e_ty.is_nil());
coerce.coerce_forced_unit(self, &cause, &mut |_| (), true);
@ -3975,7 +3964,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
for e in args {
let e_ty = self.check_expr_with_hint(e, coerce_to);
let cause = self.misc(e.span);
coerce.coerce(self, &cause, e, e_ty, self.diverges.get());
coerce.coerce(self, &cause, e, e_ty);
}
coerce.complete(self)
} else {
@ -4386,8 +4375,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
coerce.coerce(self,
&cause,
tail_expr,
tail_expr_ty,
self.diverges.get());
tail_expr_ty);
} else {
// Subtle: if there is no explicit tail expression,
// that is typically equivalent to a tail expression

View File

@ -56,9 +56,8 @@ fn call_foo_f() {
}
fn array_a() {
// Accepted: return is coerced to `!` just fine, and then `22` can be
// because we already diverged.
let x: [!; 2] = [return, 22];
// Return is coerced to `!` just fine, but `22` cannot be.
let x: [!; 2] = [return, 22]; //~ ERROR mismatched types
}
fn array_b() {