Auto merge of #52488 - nikomatsakis:nll-issue-48071-universe-and-sub, r=pnkfelix

introduce universes to NLL type check

This branch aims to fix #48071 and also advance chalk integration a bit at the same time. It re-implements the subtyping/type-equating check so that NLL doesn't "piggy back" on the subtyping code of the old type checker.

This new code uses the "universe-based" approach to handling higher-ranked lifetimes, which sidesteps some of the limitations of the current "leak-based" scheme. This avoids the ICE in #48071.

At the same time, I aim for this to potentially be a kind of optimization. This NLL code is (currently) not cached, but it also generates constraints without doing as much instantiation, substitution, and folding. Right now, though, it still piggy backs on the `relate_tys` trait, which is a bit unfortunate -- it means we are doing more hashing and things than we have to. I want to measure the see the perf. Refactoring that trait is something I'd prefer to leave for follow-up work.

r? @pnkfelix -- but I want to measure perf etc first
This commit is contained in:
bors 2018-07-26 15:23:50 +00:00
commit bfbf8375d7
79 changed files with 2049 additions and 771 deletions

View file

@ -2,28 +2,37 @@ error[E0499]: cannot borrow `*arg` as mutable more than once at a time
--> $DIR/mut-borrow-in-loop.rs:20:25
|
LL | (self.func)(arg) //~ ERROR cannot borrow
| ------------^^^-
| | |
| | mutable borrow starts here in previous iteration of loop
| borrow later used here
| ^^^ mutable borrow starts here in previous iteration of loop
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 17:6...
--> $DIR/mut-borrow-in-loop.rs:17:6
|
LL | impl<'a, T : 'a> FuncWrapper<'a, T> {
| ^^
error[E0499]: cannot borrow `*arg` as mutable more than once at a time
--> $DIR/mut-borrow-in-loop.rs:26:25
|
LL | (self.func)(arg) //~ ERROR cannot borrow
| ------------^^^-
| | |
| | mutable borrow starts here in previous iteration of loop
| borrow later used here
| ^^^ mutable borrow starts here in previous iteration of loop
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 17:6...
--> $DIR/mut-borrow-in-loop.rs:17:6
|
LL | impl<'a, T : 'a> FuncWrapper<'a, T> {
| ^^
error[E0499]: cannot borrow `*arg` as mutable more than once at a time
--> $DIR/mut-borrow-in-loop.rs:33:25
|
LL | (self.func)(arg) //~ ERROR cannot borrow
| ------------^^^-
| | |
| | mutable borrow starts here in previous iteration of loop
| borrow later used here
| ^^^ mutable borrow starts here in previous iteration of loop
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 17:6...
--> $DIR/mut-borrow-in-loop.rs:17:6
|
LL | impl<'a, T : 'a> FuncWrapper<'a, T> {
| ^^
error: aborting due to 3 previous errors

View file

@ -10,19 +10,21 @@ warning: not reporting region error due to nll
LL | self.x.iter().map(|a| a.0)
| ^^^^
error: unsatisfied lifetime constraints
error: borrowed data escapes outside of closure
--> $DIR/static-return-lifetime-infered.rs:17:9
|
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
| - let's call the lifetime of this reference `'1`
| ----- `self` is a reference that is only valid in the closure body
LL | self.x.iter().map(|a| a.0)
| ^^^^^^ cast requires that `'1` must outlive `'static`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` escapes the closure body here
error: unsatisfied lifetime constraints
error: borrowed data escapes outside of closure
--> $DIR/static-return-lifetime-infered.rs:21:9
|
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
| -------- `self` is a reference that is only valid in the closure body
LL | self.x.iter().map(|a| a.0)
| ^^^^^^ cast requires that `'a` must outlive `'static`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` escapes the closure body here
error: aborting due to 2 previous errors

View file

@ -35,20 +35,22 @@ LL | let mut out = Struct { head: x, _tail: [()] };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0621]: explicit lifetime required in the type of `y`
--> $DIR/issue-40288-2.rs:14:9
--> $DIR/issue-40288-2.rs:17:9
|
LL | fn lifetime_transmute_slice<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T {
| - consider changing the type of `y` to `&'a T`
LL | let mut out = [x];
| ^^^^^^^ lifetime `'a` required
...
LL | slice[0] = y;
| ^^^^^^^^^^^^ lifetime `'a` required
error[E0621]: explicit lifetime required in the type of `y`
--> $DIR/issue-40288-2.rs:29:9
--> $DIR/issue-40288-2.rs:32:9
|
LL | fn lifetime_transmute_struct<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T {
| - consider changing the type of `y` to `&'a T`
LL | let mut out = Struct { head: x, _tail: [()] };
| ^^^^^^^ lifetime `'a` required
...
LL | dst.head = y;
| ^^^^^^^^^^^^ lifetime `'a` required
error: aborting due to 2 previous errors

View file

@ -5,12 +5,12 @@ LL | if x > y { x } else { y } //~ ERROR explicit lifetime
| ^
error[E0621]: explicit lifetime required in parameter type
--> $DIR/ex1-return-one-existing-name-if-else-3.rs:11:13
--> $DIR/ex1-return-one-existing-name-if-else-3.rs:11:16
|
LL | fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 {
| -^----
| ||
| |lifetime `'a` required
| ----^-
| | |
| | lifetime `'a` required
| consider changing type to `(&'a i32, &'a i32)`
error: aborting due to previous error

View file

@ -10,7 +10,7 @@ error[E0621]: explicit lifetime required in the type of `x`
LL | fn foo<'a>(x: Ref<i32>, y: &mut Vec<Ref<'a, i32>>) {
| - consider changing the type of `x` to `Ref<'a, i32>`
LL | y.push(x); //~ ERROR explicit lifetime
| ^ lifetime `'a` required
| ^^^^^^^^^ lifetime `'a` required
error: aborting due to previous error

View file

@ -10,7 +10,7 @@ error[E0621]: explicit lifetime required in the type of `y`
LL | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
| - consider changing the type of `y` to `Ref<'a, i32>`
LL | x.push(y); //~ ERROR explicit lifetime
| ^ lifetime `'a` required
| ^^^^^^^^^ lifetime `'a` required
error: aborting due to previous error

View file

@ -10,7 +10,7 @@ error[E0623]: lifetime mismatch
LL | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
| -------- -------- these two types are declared with different lifetimes...
LL | x.push(y); //~ ERROR lifetime mismatch
| ^ ...but data from `y` flows into `x` here
| ^^^^^^^^^ ...but data from `y` flows into `x` here
error: aborting due to previous error

View file

@ -5,12 +5,13 @@ LL | let z = Ref { data: y.data };
| ^^^
error[E0623]: lifetime mismatch
--> $DIR/ex2c-push-inference-variable.rs:16:9
--> $DIR/ex2c-push-inference-variable.rs:17:5
|
LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
| ------------ ------------ these two types are declared with different lifetimes...
LL | let z = Ref { data: y.data };
| ^ ...but data from `y` flows into `x` here
LL | x.push(z); //~ ERROR lifetime mismatch
| ^^^^^^^^^ ...but data from `y` flows into `x` here
error: aborting due to previous error

View file

@ -5,12 +5,13 @@ LL | let b = Ref { data: y.data };
| ^^^
error[E0623]: lifetime mismatch
--> $DIR/ex2d-push-inference-variable-2.rs:16:9
--> $DIR/ex2d-push-inference-variable-2.rs:18:5
|
LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
| ------------ ------------ these two types are declared with different lifetimes...
LL | let a: &mut Vec<Ref<i32>> = x; //~ ERROR lifetime mismatch
| ^ ...but data from `y` flows into `x` here
...
LL | a.push(b);
| ^^^^^^^^^ ...but data from `y` flows into `x` here
error: aborting due to previous error

View file

@ -5,12 +5,13 @@ LL | let b = Ref { data: y.data };
| ^^^
error[E0623]: lifetime mismatch
--> $DIR/ex2e-push-inference-variable-3.rs:16:9
--> $DIR/ex2e-push-inference-variable-3.rs:18:5
|
LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
| ------------ ------------ these two types are declared with different lifetimes...
LL | let a: &mut Vec<Ref<i32>> = x; //~ ERROR lifetime mismatch
| ^ ...but data from `y` flows into `x` here
...
LL | Vec::push(a, b);
| ^^^^^^^^^^^^^^^ ...but data from `y` flows into `x` here
error: aborting due to previous error

View file

@ -5,12 +5,12 @@ LL | *v = x; //~ ERROR lifetime mismatch
| ^
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-2.rs:11:14
--> $DIR/ex3-both-anon-regions-2.rs:12:5
|
LL | fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) {
| ^^^^^^^^^ --- --- these two types are declared with different lifetimes...
| |
| ...but data from `x` flows here
| --- --- these two types are declared with different lifetimes...
LL | *v = x; //~ ERROR lifetime mismatch
| ^^^^^^ ...but data from `x` flows here
error: aborting due to previous error

View file

@ -11,20 +11,20 @@ LL | z.push((x,y)); //~ ERROR lifetime mismatch
| ^
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-3.rs:11:33
--> $DIR/ex3-both-anon-regions-3.rs:12:5
|
LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
| --- ^ --- these two types are declared with different lifetimes...
| |
| ...but data flows into `z` here
| --- --- these two types are declared with different lifetimes...
LL | z.push((x,y)); //~ ERROR lifetime mismatch
| ^^^^^^^^^^^^^ ...but data flows into `z` here
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-3.rs:11:33
--> $DIR/ex3-both-anon-regions-3.rs:12:5
|
LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
| --- ^ --- these two types are declared with different lifetimes...
| |
| ...but data flows into `z` here
| --- --- these two types are declared with different lifetimes...
LL | z.push((x,y)); //~ ERROR lifetime mismatch
| ^^^^^^^^^^^^^ ...but data flows into `z` here
error: aborting due to 2 previous errors

View file

@ -11,7 +11,7 @@ LL | fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>)
| ------- ------- these two types are declared with different lifetimes...
...
LL | x.push(y); //~ ERROR lifetime mismatch
| ^ ...but data from `y` flows into `x` here
| ^^^^^^^^^ ...but data from `y` flows into `x` here
error: aborting due to previous error

View file

@ -10,7 +10,7 @@ error[E0623]: lifetime mismatch
LL | fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>) {
| ------- ------- these two types are declared with different lifetimes...
LL | x.push(y); //~ ERROR lifetime mismatch
| ^ ...but data from `y` flows into `x` here
| ^^^^^^^^^ ...but data from `y` flows into `x` here
error: aborting due to previous error

View file

@ -10,7 +10,7 @@ error[E0623]: lifetime mismatch
LL | fn foo(mut x: Vec<Ref>, y: Ref) {
| --- --- these two types are declared with different lifetimes...
LL | x.push(y); //~ ERROR lifetime mismatch
| ^ ...but data from `y` flows into `x` here
| ^^^^^^^^^ ...but data from `y` flows into `x` here
error: aborting due to previous error

View file

@ -10,7 +10,7 @@ error[E0623]: lifetime mismatch
LL | fn foo<'a,'b>(x: &mut Vec<&'a u8>, y: &'b u8) {
| ------ ------ these two types are declared with different lifetimes...
LL | x.push(y); //~ ERROR lifetime mismatch
| ^ ...but data from `y` flows into `x` here
| ^^^^^^^^^ ...but data from `y` flows into `x` here
error: aborting due to previous error

View file

@ -10,7 +10,7 @@ error[E0623]: lifetime mismatch
LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) {
| --- --- these two types are declared with different lifetimes...
LL | y.push(z); //~ ERROR lifetime mismatch
| ^ ...but data from `z` flows into `y` here
| ^^^^^^^^^ ...but data from `z` flows into `y` here
error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
--> $DIR/ex3-both-anon-regions-using-fn-items.rs:11:3

View file

@ -10,7 +10,7 @@ error[E0623]: lifetime mismatch
LL | fn foo(x: &mut Vec<&u8>, y: &u8) {
| --- --- these two types are declared with different lifetimes...
LL | x.push(y); //~ ERROR lifetime mismatch
| ^ ...but data from `y` flows into `x` here
| ^^^^^^^^^ ...but data from `y` flows into `x` here
error: aborting due to previous error

View file

@ -10,7 +10,7 @@ error[E0623]: lifetime mismatch
LL | fn foo(x:Box<Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
| --- --- these two types are declared with different lifetimes...
LL | y.push(z); //~ ERROR lifetime mismatch
| ^ ...but data from `z` flows into `y` here
| ^^^^^^^^^ ...but data from `z` flows into `y` here
error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
--> $DIR/ex3-both-anon-regions-using-trait-objects.rs:11:3

View file

@ -10,7 +10,7 @@ error[E0623]: lifetime mismatch
LL | fn foo(x: &mut Vec<&u8>, y: &u8) {
| --- --- these two types are declared with different lifetimes...
LL | x.push(y); //~ ERROR lifetime mismatch
| ^ ...but data from `y` flows into `x` here
| ^^^^^^^^^ ...but data from `y` flows into `x` here
error: aborting due to previous error

View file

@ -52,9 +52,9 @@ fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell
cell_c,
|_outlives1, _outlives2, _outlives3, x, y| {
// Only works if 'x: 'y:
let p = x.get(); //~ ERROR
let p = x.get();
//~^ WARN not reporting region error due to nll
demand_y(x, y, p)
demand_y(x, y, p) //~ ERROR
},
);
}

View file

@ -1,28 +1,28 @@
warning: not reporting region error due to nll
--> $DIR/propagate-approximated-fail-no-postdom.rs:55:21
|
LL | let p = x.get(); //~ ERROR
LL | let p = x.get();
| ^^^^^^^
error: unsatisfied lifetime constraints
--> $DIR/propagate-approximated-fail-no-postdom.rs:55:21
--> $DIR/propagate-approximated-fail-no-postdom.rs:57:13
|
LL | |_outlives1, _outlives2, _outlives3, x, y| {
| ---------- ---------- lifetime `'2` appears in this argument
| |
| lifetime `'1` appears in this argument
LL | // Only works if 'x: 'y:
LL | let p = x.get(); //~ ERROR
| ^^^^^^^ argument requires that `'1` must outlive `'2`
...
LL | demand_y(x, y, p) //~ ERROR
| ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
note: No external requirements
--> $DIR/propagate-approximated-fail-no-postdom.rs:53:9
|
LL | / |_outlives1, _outlives2, _outlives3, x, y| {
LL | | // Only works if 'x: 'y:
LL | | let p = x.get(); //~ ERROR
LL | | let p = x.get();
LL | | //~^ WARN not reporting region error due to nll
LL | | demand_y(x, y, p)
LL | | demand_y(x, y, p) //~ ERROR
LL | | },
| |_________^
|

View file

@ -24,14 +24,19 @@ LL | | });
= note: where '_#1r: '_#2r
error[E0623]: lifetime mismatch
--> $DIR/propagate-approximated-ref.rs:53:29
--> $DIR/propagate-approximated-ref.rs:53:5
|
LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| ------- -------
| |
| these two types are declared with different lifetimes...
LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
| ^^^^^^^ ...but data from `cell_a` flows into `cell_b` here
LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| ------- -------
| |
| these two types are declared with different lifetimes...
LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
LL | | //~^ ERROR lifetime mismatch
LL | |
LL | | // Only works if 'x: 'y:
LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
LL | | });
| |______^ ...but data from `cell_a` flows into `cell_b` here
note: No external requirements
--> $DIR/propagate-approximated-ref.rs:52:1

View file

@ -5,7 +5,7 @@ LL | foo(cell, |cell_a, cell_x| {
| ^^^
error: borrowed data escapes outside of closure
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:20
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:9
|
LL | foo(cell, |cell_a, cell_x| {
| ------ ------ `cell_x` is a reference that is only valid in the closure body
@ -13,7 +13,7 @@ LL | foo(cell, |cell_a, cell_x| {
| `cell_a` is declared here, outside of the closure body
LL | //~^ WARNING not reporting region error due to nll
LL | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
| ^^^^^^^^^^^^ `cell_x` escapes the closure body here
| ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here
note: No external requirements
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:31:15

View file

@ -24,14 +24,19 @@ LL | | });
= note: where '_#1r: '_#2r
error[E0623]: lifetime mismatch
--> $DIR/propagate-approximated-val.rs:46:29
--> $DIR/propagate-approximated-val.rs:46:5
|
LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| ------- -------
| |
| these two types are declared with different lifetimes...
LL | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
| ^^^^^^ ...but data from `cell_a` flows into `cell_b` here
LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| ------- -------
| |
| these two types are declared with different lifetimes...
LL | / establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
LL | | //~^ ERROR lifetime mismatch
LL | |
LL | | // Only works if 'x: 'y:
LL | | demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to nll
LL | | });
| |______^ ...but data from `cell_a` flows into `cell_b` here
note: No external requirements
--> $DIR/propagate-approximated-val.rs:45:1

View file

@ -5,7 +5,7 @@ LL | demand_y(x, y, x.get())
| ^^^^^^^^^^^^^^^^^^^^^^^
error: unsatisfied lifetime constraints
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:24
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9
|
LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
| --------- - lifetime `'1` appears in this argument
@ -13,7 +13,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
| lifetime `'2` appears in this argument
LL | // Only works if 'x: 'y:
LL | demand_y(x, y, x.get())
| ^^^^^^^ argument requires that `'1` must outlive `'2`
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
note: No external requirements
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:45:47

View file

@ -5,7 +5,7 @@ LL | demand_y(x, y, x.get())
| ^^^^^^^^^^^^^^^^^^^^^^^
error: unsatisfied lifetime constraints
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:24
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9
|
LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
| ---------- ---------- lifetime `'2` appears in this argument
@ -13,7 +13,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
| lifetime `'1` appears in this argument
LL | // Only works if 'x: 'y:
LL | demand_y(x, y, x.get())
| ^^^^^^^ argument requires that `'1` must outlive `'2`
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
note: No external requirements
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:49:47

View file

@ -0,0 +1,22 @@
// 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
#![allow(dead_code)]
fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 {
let g: fn(_, _) -> _ = |_x, y| y;
//~^ ERROR unsatisfied lifetime constraints
g
//~^ WARNING not reporting region error due to nll
}
fn main() {}

View file

@ -0,0 +1,14 @@
warning: not reporting region error due to nll
--> $DIR/mir_check_cast_closure.rs:18:5
|
LL | g
| ^
error: unsatisfied lifetime constraints
--> $DIR/mir_check_cast_closure.rs:16:28
|
LL | let g: fn(_, _) -> _ = |_x, y| y;
| ^^^^^^^^^ cast requires that `'b` must outlive `'a`
error: aborting due to previous error

View file

@ -0,0 +1,52 @@
// 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: -Zborrowck=mir
#![allow(dead_code)]
// Test that we relate the type of the fn type to the type of the fn
// ptr when doing a `ReifyFnPointer` cast.
//
// This test is a bit tortured, let me explain:
//
// The `where 'a: 'a` clause here ensures that `'a` is early bound,
// which is needed below to ensure that this test hits the path we are
// concerned with.
fn foo<'a>(x: &'a u32) -> &'a u32
where
'a: 'a,
{
panic!()
}
fn bar<'a>(x: &'a u32) -> &'static u32 {
// Here, the type of `foo` is `typeof(foo::<'x>)` for some fresh variable `'x`.
// During NLL region analysis, this will get renumbered to `typeof(foo::<'?0>)`
// where `'?0` is a new region variable.
//
// (Note that if `'a` on `foo` were late-bound, the type would be
// `typeof(foo)`, which would interact differently with because
// the renumbering later.)
//
// This type is then coerced to a fn type `fn(&'?1 u32) -> &'?2
// u32`. Here, the `'?1` and `'?2` will have been created during
// the NLL region renumbering.
//
// The MIR type checker must therefore relate `'?0` to `'?1` and `'?2`
// as part of checking the `ReifyFnPointer`.
let f: fn(_) -> _ = foo;
//~^ WARNING not reporting region error due to nll
f(x)
//~^ ERROR
}
fn main() {}

View file

@ -0,0 +1,17 @@
warning: not reporting region error due to nll
--> $DIR/mir_check_cast_reify.rs:46:25
|
LL | let f: fn(_) -> _ = foo;
| ^^^
error: borrowed data escapes outside of closure
--> $DIR/mir_check_cast_reify.rs:48:5
|
LL | fn bar<'a>(x: &'a u32) -> &'static u32 {
| - `x` is a reference that is only valid in the closure body
...
LL | f(x)
| ^^^^ `x` escapes the closure body here
error: aborting due to previous error

View file

@ -0,0 +1,24 @@
// 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: -Zborrowck=mir
#![allow(dead_code)]
fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 {
// Here the NLL checker must relate the types in `f` to the types
// in `g`. These are related via the `UnsafeFnPointer` cast.
let g: unsafe fn(_) -> _ = f;
//~^ WARNING not reporting region error due to nll
unsafe { g(input) }
//~^ ERROR
}
fn main() {}

View file

@ -0,0 +1,17 @@
warning: not reporting region error due to nll
--> $DIR/mir_check_cast_unsafe_fn.rs:18:32
|
LL | let g: unsafe fn(_) -> _ = f;
| ^
error: borrowed data escapes outside of closure
--> $DIR/mir_check_cast_unsafe_fn.rs:20:14
|
LL | fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 {
| ----- `input` is a reference that is only valid in the closure body
...
LL | unsafe { g(input) }
| ^^^^^^^^ `input` escapes the closure body here
error: aborting due to previous error

View file

@ -0,0 +1,23 @@
// 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
#![allow(dead_code)]
use std::fmt::Debug;
fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
//~^ ERROR unsatisfied lifetime constraints
x
//~^ WARNING not reporting region error due to nll
}
fn main() {}

View file

@ -0,0 +1,19 @@
warning: not reporting region error due to nll
--> $DIR/mir_check_cast_unsize.rs:19:5
|
LL | x
| ^
error: unsatisfied lifetime constraints
--> $DIR/mir_check_cast_unsize.rs:17:46
|
LL | fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
| ______________________________________________^
LL | | //~^ ERROR unsatisfied lifetime constraints
LL | | x
LL | | //~^ WARNING not reporting region error due to nll
LL | | }
| |_^ return requires that `'a` must outlive `'static`
error: aborting due to previous error

View file

@ -0,0 +1,27 @@
// 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.
// Test that the NLL `relate_tys` code correctly deduces that a
// function returning either argument CANNOT be upcast to one
// that returns always its first argument.
//
// compile-flags:-Zno-leak-check
#![feature(nll)]
fn make_it() -> for<'a> fn(&'a u32, &'a u32) -> &'a u32 {
panic!()
}
fn main() {
let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
//~^ ERROR higher-ranked subtype error
drop(a);
}

View file

@ -0,0 +1,8 @@
error: higher-ranked subtype error
--> $DIR/hr-fn-aaa-as-aba.rs:24:58
|
LL | let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
| ^^^^^^^^^
error: aborting due to previous error

View file

@ -0,0 +1,38 @@
// 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.
// Test an interesting corner case that ought to be legal (though the
// current code actually gets it wrong, see below): a fn that takes
// two arguments that are references with the same lifetime is in fact
// equivalent to a fn that takes two references with distinct
// lifetimes. This is true because the two functions can call one
// another -- effectively, the single lifetime `'a` is just inferred
// to be the intersection of the two distinct lifetimes.
//
// FIXME: However, we currently reject this example with an error,
// because of how we handle binders and equality in `relate_tys`.
//
// compile-flags:-Zno-leak-check
#![feature(nll)]
use std::cell::Cell;
fn make_cell_aa() -> Cell<for<'a> fn(&'a u32, &'a u32)> {
panic!()
}
fn aa_eq_ab() {
let a: Cell<for<'a, 'b> fn(&'a u32, &'b u32)> = make_cell_aa();
//~^ ERROR higher-ranked subtype error
drop(a);
}
fn main() { }

View file

@ -0,0 +1,8 @@
error: higher-ranked subtype error
--> $DIR/hr-fn-aau-eq-abu.rs:33:53
|
LL | let a: Cell<for<'a, 'b> fn(&'a u32, &'b u32)> = make_cell_aa();
| ^^^^^^^^^^^^^^
error: aborting due to previous error

View file

@ -0,0 +1,27 @@
// 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.
// Test that the NLL `relate_tys` code correctly deduces that a
// function returning always its first argument can be upcast to one
// that returns either first or second argument.
//
// compile-pass
// compile-flags:-Zno-leak-check
#![feature(nll)]
fn make_it() -> for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 {
panic!()
}
fn main() {
let a: for<'a> fn(&'a u32, &'a u32) -> &'a u32 = make_it();
drop(a);
}

View file

@ -0,0 +1,38 @@
// Copyright 2018 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.
// Regression test for #48071. This test used to ICE because -- in
// the leak-check -- it would pass since we knew that the return type
// was `'static`, and hence `'static: 'a` was legal even for a
// placeholder region, but in NLL land it would fail because we had
// rewritten `'static` to a region variable.
//
// compile-pass
#![allow(warnings)]
#![feature(dyn_trait)]
#![feature(nll)]
trait Foo {
fn foo(&self) { }
}
impl Foo for () {
}
type MakeFooFn = for<'a> fn(&'a u8) -> Box<dyn Foo + 'a>;
fn make_foo(x: &u8) -> Box<dyn Foo + 'static> {
Box::new(())
}
fn main() {
let x: MakeFooFn = make_foo as MakeFooFn;
}

View file

@ -23,13 +23,16 @@ LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
| ^^^^^^^^^^^^^^^^^^^^^^
error: unsatisfied lifetime constraints
--> $DIR/dyn-trait-underscore.rs:18:5
--> $DIR/dyn-trait-underscore.rs:16:52
|
LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
| - let's call the lifetime of this reference `'1`
LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
| ^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static`
LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
| ________________-___________________________________^
| | |
| | let's call the lifetime of this reference `'1`
LL | | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
LL | | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
LL | | }
| |_^ return requires that `'1` must outlive `'static`
error: aborting due to previous error