fix `X as !` behavior

This commit is contained in:
Niko Matsakis 2017-03-24 13:35:49 -04:00
parent 7eeddb4093
commit 8450add8be
3 changed files with 31 additions and 5 deletions

View File

@ -56,6 +56,7 @@ use util::common::ErrorReported;
pub struct CastCheck<'tcx> { pub struct CastCheck<'tcx> {
expr: &'tcx hir::Expr, expr: &'tcx hir::Expr,
expr_ty: Ty<'tcx>, expr_ty: Ty<'tcx>,
expr_diverges: Diverges,
cast_ty: Ty<'tcx>, cast_ty: Ty<'tcx>,
cast_span: Span, cast_span: Span,
span: Span, span: Span,
@ -115,6 +116,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>, pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
expr: &'tcx hir::Expr, expr: &'tcx hir::Expr,
expr_ty: Ty<'tcx>, expr_ty: Ty<'tcx>,
expr_diverges: Diverges,
cast_ty: Ty<'tcx>, cast_ty: Ty<'tcx>,
cast_span: Span, cast_span: Span,
span: Span) span: Span)
@ -122,6 +124,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
let check = CastCheck { let check = CastCheck {
expr: expr, expr: expr,
expr_ty: expr_ty, expr_ty: expr_ty,
expr_diverges: expr_diverges,
cast_ty: cast_ty, cast_ty: cast_ty,
cast_span: cast_span, cast_span: cast_span,
span: span, span: span,
@ -378,7 +381,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
// Attempt a coercion to a fn pointer type. // Attempt a coercion to a fn pointer type.
let res = fcx.try_coerce(self.expr, let res = fcx.try_coerce(self.expr,
self.expr_ty, self.expr_ty,
Diverges::Maybe, // TODO self.expr_diverges,
fcx.tcx.mk_fn_ptr(f)); fcx.tcx.mk_fn_ptr(f));
if !res.is_ok() { if !res.is_ok() {
return Err(CastError::NonScalar); return Err(CastError::NonScalar);
@ -545,8 +548,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
} }
fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> bool { fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> bool {
// TODO fcx.try_coerce(self.expr, self.expr_ty, self.expr_diverges, self.cast_ty).is_ok()
fcx.try_coerce(self.expr, self.expr_ty, Diverges::Maybe, self.cast_ty).is_ok()
} }
} }

View File

@ -3736,6 +3736,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let t_cast = self.resolve_type_vars_if_possible(&t_cast); let t_cast = self.resolve_type_vars_if_possible(&t_cast);
let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast)); let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));
let t_cast = self.resolve_type_vars_if_possible(&t_cast); let t_cast = self.resolve_type_vars_if_possible(&t_cast);
let diverges = self.diverges.get();
// Eagerly check for some obvious errors. // Eagerly check for some obvious errors.
if t_expr.references_error() || t_cast.references_error() { if t_expr.references_error() || t_cast.references_error() {
@ -3743,7 +3744,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} else { } else {
// Defer other checks until we're done type checking. // Defer other checks until we're done type checking.
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) { match cast::CastCheck::new(self, e, t_expr, diverges, t_cast, t.span, expr.span) {
Ok(cast_check) => { Ok(cast_check) => {
deferred_cast_checks.push(cast_check); deferred_cast_checks.push(cast_check);
t_cast t_cast
@ -4158,7 +4159,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
&self.misc(tail_expr.span), &self.misc(tail_expr.span),
tail_expr, tail_expr,
tail_expr_ty, tail_expr_ty,
self.diverges.get()); // TODO self.diverges.get());
} else { } else {
// Subtle: if there is no explicit tail expression, // Subtle: if there is no explicit tail expression,
// that is typically equivalent to a tail expression // that is typically equivalent to a tail expression

View File

@ -0,0 +1,23 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(never_type)]
fn foo(x: usize, y: !, z: usize) { }
fn cast_a() {
let y = {return; 22} as !;
}
fn cast_b() {
let y = 22 as !; //~ ERROR non-scalar cast
}
fn main() { }