about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-04-12 04:33:40 +0000
committerbors <bors@rust-lang.org>2015-04-12 04:33:40 +0000
commit03f563a0e01bed68a44bf1fab946e0b6620bc153 (patch)
tree44e7851f37cac5c9a7e02af2e8592f7f7a596e7e
parent5afa2704a6fdee62b267a5df9ca0934350dfc3d1 (diff)
parente78f6319dd13e9a12fb4e15c6897913227209611 (diff)
Auto merge of #24109 - sanxiyn:diverging-closure, r=pnkfelix
Fix #23896.
-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 3a1be785580..ddf941198eb 100644
--- a/src/librustc/middle/traits/util.rs
+++ b/src/librustc/middle/traits/util.rs
@@ -477,7 +477,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 9c8f30902ba..952996c90f5 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();
+}