]> git.lizzy.rs Git - rust.git/commitdiff
fix `X as !` behavior
authorNiko Matsakis <niko@alum.mit.edu>
Fri, 24 Mar 2017 17:35:49 +0000 (13:35 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Thu, 30 Mar 2017 12:18:02 +0000 (08:18 -0400)
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/mod.rs
src/test/compile-fail/coerce-to-bang-cast.rs [new file with mode: 0644]

index ea0aad007dd73700587d9a93b4b59d22b02e6dc7..32b363ed755f4cca5860c4f333b11db273e72386 100644 (file)
@@ -56,6 +56,7 @@
 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 @@ pub fn new(fcx: &FnCtxt<'a, 'gcx, '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 @@ fn do_check(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Result<CastKind, CastError>
                     // 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 @@ fn check_addr_ptr_cast(&self,
     }
 
     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()
     }
 }
 
index 29b83523aed6b1bd8c50f42258b8b46be6d13bb1..da15c8f766e372920e5283f13c3605a76c5200ff 100644 (file)
@@ -3736,6 +3736,7 @@ fn check_expr_kind(&self,
             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 @@ fn check_expr_kind(&self,
             } 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 @@ fn check_block_with_expected(&self,
                               &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 (file)
index 0000000..57d2192
--- /dev/null
@@ -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() { }