about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2017-11-27 12:25:01 -0300
committerNiko Matsakis <niko@alum.mit.edu>2017-12-13 06:03:26 -0500
commit688ab5af8198f4da45e90f2cf4a2d37ce97d5e8d (patch)
tree71c280feac99efd01027a2126112df66770e306a
parent5010496677ee5eb2bdfcbf104eaaa19130d0dc17 (diff)
downloadrust-688ab5af8198f4da45e90f2cf4a2d37ce97d5e8d.tar.gz
rust-688ab5af8198f4da45e90f2cf4a2d37ce97d5e8d.zip
Check functions predicates
-rw-r--r--src/librustc_mir/transform/type_check.rs44
-rw-r--r--src/test/compile-fail/nll/where_clauses_in_functions.rs28
2 files changed, 70 insertions, 2 deletions
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index 19c22d7017d..e722e583ad2 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -59,7 +59,10 @@ pub fn type_check<'a, 'gcx, 'tcx>(
 }
 
 fn mirbug(tcx: TyCtxt, span: Span, msg: &str) {
-    tcx.sess.diagnostic().span_bug(span, msg);
+    // We sometimes see MIR failures (notably predicate failures) due to
+    // the fact that we check rvalue sized predicates here. So use `delay_span_bug`
+    // to avoid reporting bugs in those cases.
+    tcx.sess.diagnostic().delay_span_bug(span, msg);
 }
 
 macro_rules! span_mirbug {
@@ -171,7 +174,44 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
         );
 
         let expected_ty = match constant.literal {
-            Literal::Value { value } => value.ty,
+            Literal::Value { value } => {
+                if let ConstVal::Function(def_id, ..) = value.val {
+                    let tcx = self.tcx();
+                    let type_checker = &mut self.cx;
+
+                    // FIXME -- For now, use the substitutions from
+                    // `value.ty` rather than `value.val`. The
+                    // renumberer will rewrite them to independent
+                    // sets of regions; in principle, we ought to
+                    // derive the type of the `value.val` from "first
+                    // principles" and equate with value.ty, but as we
+                    // are transitioning to the miri-based system, we
+                    // don't have a handy function for that, so for
+                    // now we just ignore `value.val` regions.
+                    let substs = match value.ty.sty {
+                        ty::TyFnDef(ty_def_id, substs) => {
+                            assert_eq!(def_id, ty_def_id);
+                            substs
+                        }
+                        _ => {
+                            span_bug!(
+                                self.last_span,
+                                "unexpected type for constant function: {:?}",
+                                value.ty
+                            )
+                        }
+                    };
+
+                    let instantiated_predicates =
+                        tcx.predicates_of(def_id).instantiate(tcx, substs);
+                    let predicates =
+                        type_checker.normalize(&instantiated_predicates.predicates, location);
+                    type_checker.prove_predicates(&predicates, location);
+                }
+
+                value.ty
+            }
+
             Literal::Promoted { .. } => {
                 // FIXME -- promoted MIR return types reference
                 // various "free regions" (e.g., scopes and things)
diff --git a/src/test/compile-fail/nll/where_clauses_in_functions.rs b/src/test/compile-fail/nll/where_clauses_in_functions.rs
new file mode 100644
index 00000000000..a13360aeca7
--- /dev/null
+++ b/src/test/compile-fail/nll/where_clauses_in_functions.rs
@@ -0,0 +1,28 @@
+// Copyright 2017 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.
+
+// compile-flags: -Z borrowck=mir -Z nll
+
+#![allow(dead_code)]
+
+fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32)
+where
+    'a: 'b,
+{
+    (x, y)
+}
+
+fn bar<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
+    foo(x, y)
+    //~^ ERROR free region `'_#1r` does not outlive free region `'_#2r`
+    //~| WARNING not reporting region error due to -Znll
+}
+
+fn main() {}