Skip to content

Commit

Permalink
modify leak-check to track only outgoing edges from placeholders
Browse files Browse the repository at this point in the history
Also, update the affected tests. This seems strictly better but it is
actually more permissive than I initially intended. In particular it
accepts this

```
forall<'a, 'b> {
  exists<'intersection> {
    'a: 'intersection,
    'b: 'intersection,
  }
}
```

and I'm not sure I want to accept that. It implies that we have a
`'empty` in the new universe intoduced by the `forall`.
  • Loading branch information
nikomatsakis committed Jun 22, 2020
1 parent 1a4e2b6 commit bcc0a9c
Show file tree
Hide file tree
Showing 30 changed files with 219 additions and 201 deletions.
21 changes: 17 additions & 4 deletions src/librustc_infer/infer/region_constraints/leak_check.rs
Expand Up @@ -42,10 +42,23 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
_ => bug!("leak_check: expected placeholder found {:?}", placeholder_region,),
};

// Find all regions that are related to this placeholder
// in some way. This means any region that either outlives
// or is outlived by a placeholder.
let mut taint_set = TaintSet::new(TaintDirections::both(), placeholder_region);
// Find all regions that this placeholder `!p` must outlive -- i.e.,
// any region `r` where `!p: r` must hold. It is an error if any
// such region `r` is another placeholder or in a universe that
// can't see the placeholder. (This is actually incorrect, because
// we don't take into account the possibility of bounds in
// environment that tell us that the placeholder may be related to
// other regions).
//
// Note that we *don't* look for cases like `r: !p`. This is
// because:
//
// * If `r` is some other placeholder `!p1`, then we'll find the
// error when we search the regions that `!p1` must outlive.
// * If `r` is a variable in some outer universe, then it can
// potentially be assigned to `'static`, so this relation could
// hold.
let mut taint_set = TaintSet::new(TaintDirections::outgoing(), placeholder_region);
taint_set.fixed_point(
tcx,
self.undo_log.region_constraints(),
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/closure-expected-type/expect-fn-supply-fn.rs
Expand Up @@ -28,14 +28,14 @@ fn expect_free_supply_bound() {
// Here, we are given a function whose region is bound at closure level,
// but we expect one bound in the argument. Error results.
with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
//~^ ERROR type mismatch
//~^ ERROR mismatched types
}

fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) {
// Here, we are given a `fn(&u32)` but we expect a `fn(&'x
// u32)`. In principle, this could be ok, but we demand equality.
with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
//~^ ERROR type mismatch
//~^ ERROR mismatched types
}

fn expect_bound_supply_free_from_closure() {
Expand All @@ -44,7 +44,7 @@ fn expect_bound_supply_free_from_closure() {
// the argument level.
type Foo<'a> = fn(&'a u32);
with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
//~^ ERROR type mismatch
//~^ ERROR mismatched types
});
}

Expand Down
51 changes: 19 additions & 32 deletions src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr
Expand Up @@ -36,46 +36,33 @@ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the b
LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
| ^^^^^^^^^^^^^^^^^^^^^^

error[E0631]: type mismatch in closure arguments
--> $DIR/expect-fn-supply-fn.rs:30:5
error[E0308]: mismatched types
--> $DIR/expect-fn-supply-fn.rs:30:52
|
LL | fn with_closure_expecting_fn_with_free_region<F>(_: F)
| ------------------------------------------ required by a bound in this
LL | where F: for<'a> FnOnce(fn(&'a u32), &i32)
| ------------------------- required by this bound in `with_closure_expecting_fn_with_free_region`
...
LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _`
| |
| expected signature of `fn(fn(&'a u32), &i32) -> _`
| ^^^^^^^^ one type is more general than the other
|
= note: expected fn pointer `fn(&u32)`
found fn pointer `for<'r> fn(&'r u32)`

error[E0631]: type mismatch in closure arguments
--> $DIR/expect-fn-supply-fn.rs:37:5
error[E0308]: mismatched types
--> $DIR/expect-fn-supply-fn.rs:37:53
|
LL | fn with_closure_expecting_fn_with_bound_region<F>(_: F)
| ------------------------------------------- required by a bound in this
LL | where F: FnOnce(fn(&u32), &i32)
| ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region`
...
LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _`
| |
| expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
| ^^^^^^^^^^^ one type is more general than the other
|
= note: expected fn pointer `for<'r> fn(&'r u32)`
found fn pointer `fn(&'x u32)`

error[E0631]: type mismatch in closure arguments
--> $DIR/expect-fn-supply-fn.rs:46:5
error[E0308]: mismatched types
--> $DIR/expect-fn-supply-fn.rs:46:53
|
LL | fn with_closure_expecting_fn_with_bound_region<F>(_: F)
| ------------------------------------------- required by a bound in this
LL | where F: FnOnce(fn(&u32), &i32)
| ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region`
...
LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _`
| |
| expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
| ^^^^^^^ one type is more general than the other
|
= note: expected fn pointer `for<'r> fn(&'r u32)`
found fn pointer `fn(&u32)`

error: aborting due to 5 previous errors

Some errors have detailed explanations: E0308, E0631.
For more information about an error, try `rustc --explain E0308`.
For more information about this error, try `rustc --explain E0308`.
23 changes: 10 additions & 13 deletions src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr
@@ -1,17 +1,14 @@
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:39:26
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:96:1
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
...
LL | / check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32),
LL | | for<'a> fn(&'a u32, &'a u32)) }
| |__________________________________________________________________- in this macro invocation
|
= note: expected enum `std::option::Option<for<'a, 'b> fn(&'a u32, &'b u32)>`
found enum `std::option::Option<for<'a> fn(&'a u32, &'a u32)>`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
LL | / fn main() {
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
4 changes: 2 additions & 2 deletions src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr
@@ -1,11 +1,11 @@
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:100:1
--> $DIR/hr-subtype.rs:96:1
|
LL | / fn main() {
LL | |
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr
@@ -1,11 +1,11 @@
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:100:1
--> $DIR/hr-subtype.rs:96:1
|
LL | / fn main() {
LL | |
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr
Expand Up @@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:39:26
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
| ^^^^^^^^^^^ one type is more general than the other
...
LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
LL | | fn(&'x u32)) }
Expand Down
23 changes: 10 additions & 13 deletions src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr
@@ -1,17 +1,14 @@
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:39:26
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:96:1
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
...
LL | / check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>),
LL | | for<'a> fn(Co<'a>, Co<'a>)) }
| |______________________________________________________________________- in this macro invocation
|
= note: expected enum `std::option::Option<for<'a, 'b> fn(Co<'a>, Co<'b>)>`
found enum `std::option::Option<for<'a> fn(Co<'a>, Co<'a>)>`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
LL | / fn main() {
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
@@ -1,17 +1,14 @@
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:39:26
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:96:1
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
...
LL | / check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>,
LL | | for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) }
| |______________________________________________________________________________________- in this macro invocation
|
= note: expected enum `std::option::Option<for<'a, 'b> fn(Co<'a>, Co<'b>) -> Contra<'a>>`
found enum `std::option::Option<for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>>`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
LL | / fn main() {
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
@@ -1,11 +1,11 @@
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:100:1
--> $DIR/hr-subtype.rs:96:1
|
LL | / fn main() {
LL | |
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^
Expand Down
@@ -1,17 +1,14 @@
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:39:26
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:96:1
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
...
LL | / check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>,
LL | | for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) }
| |______________________________________________________________________________________________- in this macro invocation
|
= note: expected enum `std::option::Option<for<'a, 'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>>`
found enum `std::option::Option<for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>>`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
LL | / fn main() {
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
@@ -1,11 +1,11 @@
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:100:1
--> $DIR/hr-subtype.rs:96:1
|
LL | / fn main() {
LL | |
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr
@@ -1,11 +1,11 @@
error: fatal error triggered by #[rustc_error]
--> $DIR/hr-subtype.rs:100:1
--> $DIR/hr-subtype.rs:96:1
|
LL | / fn main() {
LL | |
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_^
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/hr-subtype/hr-subtype.rs
Expand Up @@ -42,10 +42,6 @@ macro_rules! check {
//[bound_inv_a_b_vs_bound_inv_a]~^^^ ERROR
//[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^ ERROR
//[free_inv_x_vs_free_inv_y]~^^^^^ ERROR
//[bound_a_b_vs_bound_a]~^^^^^^ ERROR mismatched types
//[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR
//[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^ ERROR
//[bound_co_a_b_vs_bound_co_a]~^^^^^^^^^ ERROR
}
}
}
Expand Down Expand Up @@ -103,4 +99,8 @@ fn main() {
//[bound_inv_a_vs_bound_inv_b]~^^^ ERROR fatal error triggered by #[rustc_error]
//[bound_co_a_vs_bound_co_b]~^^^^ ERROR fatal error triggered by #[rustc_error]
//[free_x_vs_free_x]~^^^^^ ERROR fatal error triggered by #[rustc_error]
//[bound_a_b_vs_bound_a]~^^^^^^ ERROR fatal error triggered by #[rustc_error]
//[bound_co_a_b_vs_bound_co_a]~^^^^^^^ ERROR fatal error triggered by #[rustc_error]
//[bound_co_a_co_b_ret_contra_a]~^^^^^^^^ ERROR fatal error triggered by #[rustc_error]
//[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR fatal error triggered by #[rustc_error]
}
4 changes: 1 addition & 3 deletions src/test/ui/hrtb/hrtb-exists-forall-fn.stderr
Expand Up @@ -2,9 +2,7 @@ error[E0308]: mismatched types
--> $DIR/hrtb-exists-forall-fn.rs:17:34
|
LL | let _: for<'b> fn(&'b u32) = foo();
| ------------------- ^^^^^ expected concrete lifetime, found bound lifetime parameter 'b
| |
| expected due to this
| ^^^^^ one type is more general than the other
|
= note: expected fn pointer `for<'b> fn(&'b u32)`
found fn pointer `fn(&u32)`
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs
Expand Up @@ -32,5 +32,5 @@ fn main() {
// NB. *However*, the reinstated leak-check gives an error here.

foo::<()>();
//~^ ERROR not satisfied
//~^ ERROR implementation of `Trait` is not general enough
}
18 changes: 7 additions & 11 deletions src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr
@@ -1,18 +1,14 @@
error[E0277]: the trait bound `(): Trait<for<'b> fn(&'b u32)>` is not satisfied
--> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:11
error: implementation of `Trait` is not general enough
--> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5
|
LL | fn foo<T>()
| --- required by a bound in this
LL | where
LL | T: Trait<for<'b> fn(&'b u32)>,
| -------------------------- required by this bound in `foo`
LL | trait Trait<T> {}
| ----------------- trait `Trait` defined here
...
LL | foo::<()>();
| ^^ the trait `Trait<for<'b> fn(&'b u32)>` is not implemented for `()`
| ^^^^^^^^^ implementation of `Trait` is not general enough
|
= help: the following implementations were found:
<() as Trait<fn(&'a u32)>>
= note: `()` must implement `Trait<for<'b> fn(&'b u32)>`
= note: ...but `()` actually implements `Trait<fn(&'0 u32)>`, for some specific lifetime `'0`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.

0 comments on commit bcc0a9c

Please sign in to comment.