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> {
expr: &'tcx hir::Expr,
expr_ty: Ty<'tcx>,
expr_diverges: Diverges,
cast_ty: Ty<'tcx>,
cast_span: Span,
span: Span,
@ -115,6 +116,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
expr: &'tcx hir::Expr,
expr_ty: Ty<'tcx>,
expr_diverges: Diverges,
cast_ty: Ty<'tcx>,
cast_span: Span,
span: Span)
@ -122,6 +124,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
let check = CastCheck {
expr: expr,
expr_ty: expr_ty,
expr_diverges: expr_diverges,
cast_ty: cast_ty,
cast_span: cast_span,
span: span,
@ -378,7 +381,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
// Attempt a coercion to a fn pointer type.
let res = fcx.try_coerce(self.expr,
self.expr_ty,
Diverges::Maybe, // TODO
self.expr_diverges,
fcx.tcx.mk_fn_ptr(f));
if !res.is_ok() {
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 {
// TODO
fcx.try_coerce(self.expr, self.expr_ty, Diverges::Maybe, self.cast_ty).is_ok()
fcx.try_coerce(self.expr, self.expr_ty, self.expr_diverges, 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_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));
let t_cast = self.resolve_type_vars_if_possible(&t_cast);
let diverges = self.diverges.get();
// Eagerly check for some obvious errors.
if t_expr.references_error() || t_cast.references_error() {
@ -3743,7 +3744,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} else {
// Defer other checks until we're done type checking.
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) => {
deferred_cast_checks.push(cast_check);
t_cast
@ -4158,7 +4159,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
&self.misc(tail_expr.span),
tail_expr,
tail_expr_ty,
self.diverges.get()); // TODO
self.diverges.get());
} else {
// Subtle: if there is no explicit 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() { }