about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSeo Sanghyeon <sanxiyn@gmail.com>2015-04-06 22:17:35 +0900
committerSeo Sanghyeon <sanxiyn@gmail.com>2015-04-06 22:17:35 +0900
commite78f6319dd13e9a12fb4e15c6897913227209611 (patch)
treecb6fdf33a172261c3da45ab1c32c8a0757f162a8
parent1169693f03d73e422866d9c412328a031ed0e4df (diff)
downloadrust-e78f6319dd13e9a12fb4e15c6897913227209611.tar.gz
rust-e78f6319dd13e9a12fb4e15c6897913227209611.zip
Fix diverging closures
-rw-r--r--src/librustc/middle/traits/util.rs2
-rw-r--r--src/librustc/middle/ty.rs7
-rw-r--r--src/librustc_typeck/check/callee.rs5
-rw-r--r--src/test/run-fail/diverging-closure.rs18
4 files changed, 29 insertions, 3 deletions
diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs
index 297cea13207..a8a1ce28067 100644
--- a/src/librustc/middle/traits/util.rs
+++ b/src/librustc/middle/traits/util.rs
@@ -506,7 +506,7 @@ pub fn closure_trait_ref_and_return_type<'tcx>(
         def_id: fn_trait_def_id,
         substs: tcx.mk_substs(trait_substs),
     });
-    ty::Binder((trait_ref, sig.0.output.unwrap()))
+    ty::Binder((trait_ref, sig.0.output.unwrap_or(ty::mk_nil(tcx))))
 }
 
 impl<'tcx,O:Repr<'tcx>> Repr<'tcx> for super::Obligation<'tcx, O> {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 1123c923631..6f213b57134 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -1092,6 +1092,13 @@ impl<'tcx> FnOutput<'tcx> {
             ty::FnDiverging => unreachable!()
         }
     }
+
+    pub fn unwrap_or(self, def: Ty<'tcx>) -> Ty<'tcx> {
+        match self {
+            ty::FnConverging(t) => t,
+            ty::FnDiverging => def
+        }
+    }
 }
 
 pub type PolyFnOutput<'tcx> = Binder<FnOutput<'tcx>>;
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 3f9c14e0afe..f54c0b7f8c4 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -387,10 +387,11 @@ impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> {
                     demand::eqtype(fcx, self.call_expr.span, self_arg_ty, method_arg_ty);
                 }
 
+                let nilty = ty::mk_nil(fcx.tcx());
                 demand::eqtype(fcx,
                                self.call_expr.span,
-                               method_sig.output.unwrap(),
-                               self.fn_sig.output.unwrap());
+                               method_sig.output.unwrap_or(nilty),
+                               self.fn_sig.output.unwrap_or(nilty));
 
                 write_overloaded_call_method_map(fcx, self.call_expr, method_callee);
             }
diff --git a/src/test/run-fail/diverging-closure.rs b/src/test/run-fail/diverging-closure.rs
new file mode 100644
index 00000000000..6b98e0397b5
--- /dev/null
+++ b/src/test/run-fail/diverging-closure.rs
@@ -0,0 +1,18 @@
+// Copyright 2015 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.
+
+// error-pattern:oops
+
+fn main() {
+    let func = || -> ! {
+        panic!("oops");
+    };
+    func();
+}