From 8450add8bede7bc5119457e37bbbcc95a5e8b121 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 24 Mar 2017 13:35:49 -0400 Subject: [PATCH] fix `X as !` behavior --- src/librustc_typeck/check/cast.rs | 8 ++++--- src/librustc_typeck/check/mod.rs | 5 +++-- src/test/compile-fail/coerce-to-bang-cast.rs | 23 ++++++++++++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 src/test/compile-fail/coerce-to-bang-cast.rs diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index ea0aad007dd..32b363ed755 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -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() } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 29b83523aed..da15c8f766e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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 diff --git a/src/test/compile-fail/coerce-to-bang-cast.rs b/src/test/compile-fail/coerce-to-bang-cast.rs new file mode 100644 index 00000000000..57d2192e635 --- /dev/null +++ b/src/test/compile-fail/coerce-to-bang-cast.rs @@ -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 or the MIT license +// , 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() { }