From bcc0a9c8eba0c4eaaafb7983b1b367a926ca8948 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 18 May 2020 09:43:36 +0000 Subject: [PATCH 01/13] modify leak-check to track only outgoing edges from placeholders 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`. --- .../infer/region_constraints/leak_check.rs | 21 ++++++-- .../expect-fn-supply-fn.rs | 6 +-- .../expect-fn-supply-fn.stderr | 51 +++++++------------ .../hr-subtype.bound_a_b_vs_bound_a.stderr | 23 ++++----- .../hr-subtype.bound_a_vs_bound_a.stderr | 4 +- .../hr-subtype.bound_a_vs_bound_b.stderr | 4 +- .../hr-subtype.bound_a_vs_free_x.stderr | 2 +- ...-subtype.bound_co_a_b_vs_bound_co_a.stderr | 23 ++++----- ...ubtype.bound_co_a_co_b_ret_contra_a.stderr | 23 ++++----- ...hr-subtype.bound_co_a_vs_bound_co_b.stderr | 4 +- ...pe.bound_contra_a_contra_b_ret_co_a.stderr | 23 ++++----- ...-subtype.bound_inv_a_vs_bound_inv_b.stderr | 4 +- .../hr-subtype.free_x_vs_free_x.stderr | 4 +- src/test/ui/hr-subtype/hr-subtype.rs | 8 +-- src/test/ui/hrtb/hrtb-exists-forall-fn.stderr | 4 +- .../hrtb-exists-forall-trait-contravariant.rs | 2 +- ...b-exists-forall-trait-contravariant.stderr | 18 +++---- ...igher-ranker-supertraits-transitive.stderr | 19 +++---- src/test/ui/hrtb/hrtb-just-for-static.stderr | 20 ++++---- src/test/ui/hrtb/issue-46989.rs | 2 +- src/test/ui/hrtb/issue-46989.stderr | 19 +++---- src/test/ui/issues/issue-57362-1.rs | 2 +- src/test/ui/issues/issue-57362-1.stderr | 21 ++++---- src/test/ui/issues/issue-57362-2.rs | 4 +- src/test/ui/issues/issue-57362-2.stderr | 39 ++++++++++---- src/test/ui/lub-glb/old-lub-glb-hr.rs | 35 +++++++++++-- src/test/ui/lub-glb/old-lub-glb-hr.stderr | 10 ++-- ...ons-fn-subtyping-return-static-fail.stderr | 4 +- src/test/ui/where-clauses/where-for-self-2.rs | 2 +- .../ui/where-clauses/where-for-self-2.stderr | 19 ++++--- 30 files changed, 219 insertions(+), 201 deletions(-) diff --git a/src/librustc_infer/infer/region_constraints/leak_check.rs b/src/librustc_infer/infer/region_constraints/leak_check.rs index 91c39a0e78ffb..111a7b997a486 100644 --- a/src/librustc_infer/infer/region_constraints/leak_check.rs +++ b/src/librustc_infer/infer/region_constraints/leak_check.rs @@ -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(), diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs index a4e43da91baf8..6977fd47a2e85 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs @@ -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() { @@ -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 }); } diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index fae41c4114abc..8a183bb704b4d 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -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) - | ------------------------------------------ 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) - | ------------------------------------------- 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) - | ------------------------------------------- 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`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr index 45f53d4fe99db..c4e838e6887b5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr +++ b/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 fn(&'a u32, &'b u32)>` - found enum `std::option::Option 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`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr index 6aba6466fada5..c4e838e6887b5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr +++ b/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 | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr index 6aba6466fada5..c4e838e6887b5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr +++ b/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 | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr index c3e4f6d2ed0c1..b3e3f5dc401cf 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -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)) } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr index 4d7b86027f564..c4e838e6887b5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr +++ b/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 fn(Co<'a>, Co<'b>)>` - found enum `std::option::Option 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`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr index 7f0a4197dd7fe..c4e838e6887b5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_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_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 fn(Co<'a>, Co<'b>) -> Contra<'a>>` - found enum `std::option::Option 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`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr index 6aba6466fada5..c4e838e6887b5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_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 | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr index c12e543a44e79..c4e838e6887b5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_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_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 fn(Contra<'a>, Contra<'b>) -> Co<'a>>` - found enum `std::option::Option 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`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr index 6aba6466fada5..c4e838e6887b5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_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 | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr index 6aba6466fada5..c4e838e6887b5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr +++ b/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 | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.rs b/src/test/ui/hr-subtype/hr-subtype.rs index b31f198bd97bf..995ec64d53b83 100644 --- a/src/test/ui/hr-subtype/hr-subtype.rs +++ b/src/test/ui/hr-subtype/hr-subtype.rs @@ -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 } } } @@ -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] } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr index 328e98657effb..9914783d9767d 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr @@ -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)` diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs index 4c1d4d28a09b0..921061916fc95 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs @@ -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 } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr index 7a7285d3d76e0..fe8209d054c8a 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr @@ -1,18 +1,14 @@ -error[E0277]: the trait bound `(): Trait 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() - | --- required by a bound in this -LL | where -LL | T: Trait fn(&'b u32)>, - | -------------------------- required by this bound in `foo` +LL | trait Trait {} + | ----------------- trait `Trait` defined here ... LL | foo::<()>(); - | ^^ the trait `Trait fn(&'b u32)>` is not implemented for `()` + | ^^^^^^^^^ implementation of `Trait` is not general enough | - = help: the following implementations were found: - <() as Trait> + = note: `()` must implement `Trait fn(&'b u32)>` + = note: ...but `()` actually implements `Trait`, for some specific lifetime `'0` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr index 87a13889298df..ebb3abf184856 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr @@ -1,19 +1,12 @@ -error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied - --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:26 +error[E0308]: mismatched types + --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:5 | -LL | fn want_bar_for_any_ccx(b: &B) - | -------------------- required by a bound in this -LL | where B : for<'ccx> Bar<'ccx> - | ------------------- required by this bound in `want_bar_for_any_ccx` -... LL | want_bar_for_any_ccx(b); - | ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | -help: consider further restricting this bound - | -LL | where B : Qux + for<'ccx> Bar<'ccx> - | ^^^^^^^^^^^^^^^^^^^^^ + = note: expected type `for<'ccx> Bar<'ccx>` + found type `Bar<'static>` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 4fa404624775b..bf7373059a074 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -1,16 +1,16 @@ -error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied - --> $DIR/hrtb-just-for-static.rs:24:17 +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-just-for-static.rs:24:5 | -LL | fn want_hrtb() - | --------- required by a bound in this -LL | where T : for<'a> Foo<&'a isize> - | ---------------------- required by this bound in `want_hrtb` +LL | / trait Foo { +LL | | fn foo(&self, x: X) { } +LL | | } + | |_- trait `Foo` defined here ... -LL | want_hrtb::() - | ^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt` +LL | want_hrtb::() + | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = help: the following implementations were found: - > + = note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... + = note: ...but `StaticInt` actually implements `Foo<&'1 isize>`, for some specific lifetime `'1` error[E0277]: the trait bound `for<'a> &'a u32: Foo<&'a isize>` is not satisfied --> $DIR/hrtb-just-for-static.rs:30:17 diff --git a/src/test/ui/hrtb/issue-46989.rs b/src/test/ui/hrtb/issue-46989.rs index 2c85905545807..eb6549099fe6a 100644 --- a/src/test/ui/hrtb/issue-46989.rs +++ b/src/test/ui/hrtb/issue-46989.rs @@ -38,5 +38,5 @@ fn assert_foo() {} fn main() { assert_foo::(); - //~^ ERROR the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied + //~^ ERROR implementation of `Foo` is not general enough } diff --git a/src/test/ui/hrtb/issue-46989.stderr b/src/test/ui/hrtb/issue-46989.stderr index 0a7382c4dd818..0865aa4224b97 100644 --- a/src/test/ui/hrtb/issue-46989.stderr +++ b/src/test/ui/hrtb/issue-46989.stderr @@ -1,15 +1,16 @@ -error[E0277]: the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied - --> $DIR/issue-46989.rs:40:18 +error: implementation of `Foo` is not general enough + --> $DIR/issue-46989.rs:40:5 | -LL | fn assert_foo() {} - | --- required by this bound in `assert_foo` +LL | / trait Foo { +LL | | +LL | | } + | |_- trait `Foo` defined here ... -LL | assert_foo::(); - | ^^^^^^^^ the trait `Foo` is not implemented for `for<'r> fn(&'r i32)` +LL | assert_foo::(); + | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = help: the following implementations were found: - + = note: `Foo` would have to be implemented for the type `for<'r> fn(&'r i32)` + = note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-57362-1.rs b/src/test/ui/issues/issue-57362-1.rs index 1fa417fe98ab7..3ba82300fabea 100644 --- a/src/test/ui/issues/issue-57362-1.rs +++ b/src/test/ui/issues/issue-57362-1.rs @@ -17,7 +17,7 @@ impl Trait for fn(&T) { fn f() { let a: fn(_) = |_: &u8| {}; - a.f(); //~ ERROR no method named `f` + a.f(); //~ ERROR implementation of `Trait` is not general enough } fn main() {} diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr index 5c611cd43d3cc..24408420b1373 100644 --- a/src/test/ui/issues/issue-57362-1.stderr +++ b/src/test/ui/issues/issue-57362-1.stderr @@ -1,17 +1,16 @@ -error[E0599]: no method named `f` found for fn pointer `fn(&u8)` in the current scope +error: implementation of `Trait` is not general enough --> $DIR/issue-57362-1.rs:20:7 | -LL | a.f(); - | ^ method not found in `fn(&u8)` +LL | / trait Trait { +LL | | fn f(self); +LL | | } + | |_- trait `Trait` defined here +... +LL | a.f(); + | ^ implementation of `Trait` is not general enough | - = note: `a` is a function, perhaps you wish to call it - = help: items from traits can only be used if the trait is implemented and in scope -note: `Trait` defines an item `f`, perhaps you need to implement it - --> $DIR/issue-57362-1.rs:8:1 - | -LL | trait Trait { - | ^^^^^^^^^^^ + = note: `Trait` would have to be implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0`... + = note: ...but `Trait` is actually implemented for the type `for<'r> fn(&'r u8)` error: aborting due to previous error -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-57362-2.rs b/src/test/ui/issues/issue-57362-2.rs index 870d7f28ba953..7b6594abc9647 100644 --- a/src/test/ui/issues/issue-57362-2.rs +++ b/src/test/ui/issues/issue-57362-2.rs @@ -19,7 +19,9 @@ impl<'a> X for fn(&'a ()) { } fn g() { - let x = ::make_g(); //~ ERROR no function or associated item + let x = ::make_g(); + //~^ ERROR implementation of `X` is not general enough + //~| ERROR implementation of `X` is not general enough } fn main() {} diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index 2edc009746455..dfd48ec22275b 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -1,16 +1,33 @@ -error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'r> fn(&'r ())` in the current scope - --> $DIR/issue-57362-2.rs:22:25 +error: implementation of `X` is not general enough + --> $DIR/issue-57362-2.rs:22:13 | -LL | let x = ::make_g(); - | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` +LL | / trait X { +LL | | type G; +LL | | fn make_g() -> Self::G; +LL | | } + | |_- trait `X` defined here +... +LL | let x = ::make_g(); + | ^^^^^^^^^^^^^^^^^^ implementation of `X` is not general enough | - = help: items from traits can only be used if the trait is implemented and in scope -note: `X` defines an item `make_g`, perhaps you need to implement it - --> $DIR/issue-57362-2.rs:8:1 + = note: `X` would have to be implemented for the type `for<'r> fn(&'r ())` + = note: ...but `X` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` + +error: implementation of `X` is not general enough + --> $DIR/issue-57362-2.rs:22:13 + | +LL | / trait X { +LL | | type G; +LL | | fn make_g() -> Self::G; + | | ----------------------- due to a where-clause on `X::make_g`... +LL | | } + | |_- trait `X` defined here +... +LL | let x = ::make_g(); + | ^^^^^^^^^^^^^^^^^^ doesn't satisfy where-clause | -LL | trait X { - | ^^^^^^^ + = note: ...`X` would have to be implemented for the type `for<'r> fn(&'r ())` + = note: ...but `X` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.rs b/src/test/ui/lub-glb/old-lub-glb-hr.rs index bc7b787cd65ac..5e24a99bcc331 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr.rs +++ b/src/test/ui/lub-glb/old-lub-glb-hr.rs @@ -3,21 +3,21 @@ // error. However, now that we handle subtyping correctly, we no // longer get an error, because we recognize these two types as // equivalent! -// -// Whoops -- now that we reinstituted the leak-check, we get an error -// again. fn foo( x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8), ) { + // The two types above are actually equivalent. With the older + // leak check, though, we didn't consider them as equivalent, and + // hence we gave errors. But now we've fixed that. let z = match 22 { 0 => x, - _ => y, //~ ERROR `match` arms have incompatible types + _ => y, }; } -fn bar( +fn foo_cast( x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8), ) { @@ -28,5 +28,30 @@ fn bar( }; } +fn bar( + x: for<'a, 'b> fn(&'a u8, &'b u8)-> &'a u8, + y: for<'a> fn(&'a u8, &'a u8) -> &'a u8, +) { + // The two types above are not equivalent. With the older LUB/GLB + // algorithm, this may have worked (I don't remember), but now it + // doesn't because we require equality. + let z = match 22 { + 0 => x, + _ => y, //~ ERROR `match` arms have incompatible types + }; +} + +fn bar_cast( + x: for<'a, 'b> fn(&'a u8, &'b u8)-> &'a u8, + y: for<'a> fn(&'a u8, &'a u8) -> &'a u8, +) { + // But we can *upcast* explicitly the type of `x` and figure + // things out: + let z = match 22 { + 0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8, + _ => y, + }; +} + fn main() { } diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.stderr b/src/test/ui/lub-glb/old-lub-glb-hr.stderr index 6d5d51174699f..d242fb7789aa1 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-hr.stderr @@ -1,17 +1,17 @@ error[E0308]: `match` arms have incompatible types - --> $DIR/old-lub-glb-hr.rs:16:14 + --> $DIR/old-lub-glb-hr.rs:40:14 | LL | let z = match 22 { | _____________- LL | | 0 => x, - | | - this is found to be of type `for<'r, 's> fn(&'r u8, &'s u8)` + | | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` LL | | _ => y, - | | ^ expected bound lifetime parameter, found concrete lifetime + | | ^ expected bound lifetime parameter 'a, found concrete lifetime LL | | }; | |_____- `match` arms have incompatible types | - = note: expected type `for<'r, 's> fn(&'r u8, &'s u8)` - found fn pointer `for<'a> fn(&'a u8, &'a u8)` + = note: expected type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` error: aborting due to previous error diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr index 27704b3e0a8c7..7848f770a70cf 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr @@ -11,10 +11,10 @@ error[E0308]: mismatched types --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12 | LL | want_G(baz); - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx + | ^^^ one type is more general than the other | = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S` - found fn item `for<'r> fn(&'r S) -> &'r S {baz}` + found fn pointer `for<'r> fn(&'r S) -> &'r S` error: aborting due to 2 previous errors diff --git a/src/test/ui/where-clauses/where-for-self-2.rs b/src/test/ui/where-clauses/where-for-self-2.rs index 31174fd4cf163..0ce38e69f6b0f 100644 --- a/src/test/ui/where-clauses/where-for-self-2.rs +++ b/src/test/ui/where-clauses/where-for-self-2.rs @@ -18,5 +18,5 @@ fn foo(x: &T) {} fn main() { - foo(&X); //~ ERROR trait bound + foo(&X); //~ ERROR implementation of `Bar` is not general enough } diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index 9976243b200dc..b3cadf5b1b078 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -1,17 +1,16 @@ -error[E0277]: the trait bound `for<'a> &'a _: Bar` is not satisfied +error: implementation of `Bar` is not general enough --> $DIR/where-for-self-2.rs:21:5 | -LL | fn foo(x: &T) - | --- required by a bound in this -LL | where for<'a> &'a T: Bar - | --- required by this bound in `foo` +LL | / trait Bar { +LL | | fn bar(&self); +LL | | } + | |_- trait `Bar` defined here ... -LL | foo(&X); - | ^^^ the trait `for<'a> Bar` is not implemented for `&'a _` +LL | foo(&X); + | ^^^ implementation of `Bar` is not general enough | - = help: the following implementations were found: - <&'static u32 as Bar> + = note: `Bar` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... + = note: ...but `Bar` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. From 4199b3ae26007eb9c871b57f56057da586bbd1db Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 18 May 2020 21:43:11 +0000 Subject: [PATCH 02/13] Revert "modify leak-check to track only outgoing edges from placeholders" This reverts commit 2e01db4b396a1e161f7a73933fff34bc9421dba0. --- .../infer/region_constraints/leak_check.rs | 21 ++------ .../expect-fn-supply-fn.rs | 6 +-- .../expect-fn-supply-fn.stderr | 51 ++++++++++++------- .../hr-subtype.bound_a_b_vs_bound_a.stderr | 23 +++++---- .../hr-subtype.bound_a_vs_bound_a.stderr | 4 +- .../hr-subtype.bound_a_vs_bound_b.stderr | 4 +- .../hr-subtype.bound_a_vs_free_x.stderr | 2 +- ...-subtype.bound_co_a_b_vs_bound_co_a.stderr | 23 +++++---- ...ubtype.bound_co_a_co_b_ret_contra_a.stderr | 23 +++++---- ...hr-subtype.bound_co_a_vs_bound_co_b.stderr | 4 +- ...pe.bound_contra_a_contra_b_ret_co_a.stderr | 23 +++++---- ...-subtype.bound_inv_a_vs_bound_inv_b.stderr | 4 +- .../hr-subtype.free_x_vs_free_x.stderr | 4 +- src/test/ui/hr-subtype/hr-subtype.rs | 8 +-- src/test/ui/hrtb/hrtb-exists-forall-fn.stderr | 4 +- .../hrtb-exists-forall-trait-contravariant.rs | 2 +- ...b-exists-forall-trait-contravariant.stderr | 18 ++++--- ...igher-ranker-supertraits-transitive.stderr | 19 ++++--- src/test/ui/hrtb/hrtb-just-for-static.stderr | 20 ++++---- src/test/ui/hrtb/issue-46989.rs | 2 +- src/test/ui/hrtb/issue-46989.stderr | 19 ++++--- src/test/ui/issues/issue-57362-1.rs | 2 +- src/test/ui/issues/issue-57362-1.stderr | 21 ++++---- src/test/ui/issues/issue-57362-2.rs | 4 +- src/test/ui/issues/issue-57362-2.stderr | 39 ++++---------- src/test/ui/lub-glb/old-lub-glb-hr.rs | 35 ++----------- src/test/ui/lub-glb/old-lub-glb-hr.stderr | 10 ++-- ...ons-fn-subtyping-return-static-fail.stderr | 4 +- src/test/ui/where-clauses/where-for-self-2.rs | 2 +- .../ui/where-clauses/where-for-self-2.stderr | 19 +++---- 30 files changed, 201 insertions(+), 219 deletions(-) diff --git a/src/librustc_infer/infer/region_constraints/leak_check.rs b/src/librustc_infer/infer/region_constraints/leak_check.rs index 111a7b997a486..91c39a0e78ffb 100644 --- a/src/librustc_infer/infer/region_constraints/leak_check.rs +++ b/src/librustc_infer/infer/region_constraints/leak_check.rs @@ -42,23 +42,10 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { _ => bug!("leak_check: expected placeholder found {:?}", 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); + // 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); taint_set.fixed_point( tcx, self.undo_log.region_constraints(), diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs index 6977fd47a2e85..a4e43da91baf8 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs @@ -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 mismatched types + //~^ ERROR type mismatch } 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 mismatched types + //~^ ERROR type mismatch } fn expect_bound_supply_free_from_closure() { @@ -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 mismatched types + //~^ ERROR type mismatch }); } diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index 8a183bb704b4d..fae41c4114abc 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -36,33 +36,46 @@ 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[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:30:52 +error[E0631]: type mismatch in closure arguments + --> $DIR/expect-fn-supply-fn.rs:30:5 | +LL | fn with_closure_expecting_fn_with_free_region(_: 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| {}); - | ^^^^^^^^ one type is more general than the other - | - = note: expected fn pointer `fn(&u32)` - found fn pointer `for<'r> fn(&'r u32)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` + | | + | expected signature of `fn(fn(&'a u32), &i32) -> _` -error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:37:53 +error[E0631]: type mismatch in closure arguments + --> $DIR/expect-fn-supply-fn.rs:37:5 | +LL | fn with_closure_expecting_fn_with_bound_region(_: 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| {}); - | ^^^^^^^^^^^ one type is more general than the other - | - = note: expected fn pointer `for<'r> fn(&'r u32)` - found fn pointer `fn(&'x u32)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _` + | | + | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` -error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:46:53 +error[E0631]: type mismatch in closure arguments + --> $DIR/expect-fn-supply-fn.rs:46:5 | +LL | fn with_closure_expecting_fn_with_bound_region(_: 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| { - | ^^^^^^^ one type is more general than the other - | - = note: expected fn pointer `for<'r> fn(&'r u32)` - found fn pointer `fn(&u32)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _` + | | + | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0631. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr index c4e838e6887b5..45f53d4fe99db 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr @@ -1,14 +1,17 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:96:1 +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:39:26 | -LL | / fn main() { -LL | | -LL | | -LL | | -... | -LL | | -LL | | } - | |_^ +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 fn(&'a u32, &'b u32)>` + found enum `std::option::Option fn(&'a u32, &'a u32)>` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr index c4e838e6887b5..6aba6466fada5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr +++ b/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:96:1 + --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { LL | | LL | | LL | | -... | +LL | | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr index c4e838e6887b5..6aba6466fada5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr +++ b/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:96:1 + --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { LL | | LL | | LL | | -... | +LL | | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr index b3e3f5dc401cf..c3e4f6d2ed0c1 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a ... LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), LL | | fn(&'x u32)) } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr index c4e838e6887b5..4d7b86027f564 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr @@ -1,14 +1,17 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:96:1 +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:39:26 | -LL | / fn main() { -LL | | -LL | | -LL | | -... | -LL | | -LL | | } - | |_^ +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 fn(Co<'a>, Co<'b>)>` + found enum `std::option::Option fn(Co<'a>, Co<'a>)>` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr index c4e838e6887b5..7f0a4197dd7fe 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr @@ -1,14 +1,17 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:96:1 +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:39:26 | -LL | / fn main() { -LL | | -LL | | -LL | | -... | -LL | | -LL | | } - | |_^ +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 fn(Co<'a>, Co<'b>) -> Contra<'a>>` + found enum `std::option::Option 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) error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr index c4e838e6887b5..6aba6466fada5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr @@ -1,11 +1,11 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:96:1 + --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { LL | | LL | | LL | | -... | +LL | | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr index c4e838e6887b5..c12e543a44e79 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr @@ -1,14 +1,17 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:96:1 +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:39:26 | -LL | / fn main() { -LL | | -LL | | -LL | | -... | -LL | | -LL | | } - | |_^ +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 fn(Contra<'a>, Contra<'b>) -> Co<'a>>` + found enum `std::option::Option 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) error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr index c4e838e6887b5..6aba6466fada5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr @@ -1,11 +1,11 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:96:1 + --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { LL | | LL | | LL | | -... | +LL | | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr index c4e838e6887b5..6aba6466fada5 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr +++ b/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:96:1 + --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { LL | | LL | | LL | | -... | +LL | | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.rs b/src/test/ui/hr-subtype/hr-subtype.rs index 995ec64d53b83..b31f198bd97bf 100644 --- a/src/test/ui/hr-subtype/hr-subtype.rs +++ b/src/test/ui/hr-subtype/hr-subtype.rs @@ -42,6 +42,10 @@ 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 } } } @@ -99,8 +103,4 @@ 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] } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr index 9914783d9767d..328e98657effb 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/hrtb-exists-forall-fn.rs:17:34 | LL | let _: for<'b> fn(&'b u32) = foo(); - | ^^^^^ one type is more general than the other + | ------------------- ^^^^^ expected concrete lifetime, found bound lifetime parameter 'b + | | + | expected due to this | = note: expected fn pointer `for<'b> fn(&'b u32)` found fn pointer `fn(&u32)` diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs index 921061916fc95..4c1d4d28a09b0 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs @@ -32,5 +32,5 @@ fn main() { // NB. *However*, the reinstated leak-check gives an error here. foo::<()>(); - //~^ ERROR implementation of `Trait` is not general enough + //~^ ERROR not satisfied } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr index fe8209d054c8a..7a7285d3d76e0 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr @@ -1,14 +1,18 @@ -error: implementation of `Trait` is not general enough - --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 +error[E0277]: the trait bound `(): Trait fn(&'b u32)>` is not satisfied + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:11 | -LL | trait Trait {} - | ----------------- trait `Trait` defined here +LL | fn foo() + | --- required by a bound in this +LL | where +LL | T: Trait fn(&'b u32)>, + | -------------------------- required by this bound in `foo` ... LL | foo::<()>(); - | ^^^^^^^^^ implementation of `Trait` is not general enough + | ^^ the trait `Trait fn(&'b u32)>` is not implemented for `()` | - = note: `()` must implement `Trait fn(&'b u32)>` - = note: ...but `()` actually implements `Trait`, for some specific lifetime `'0` + = help: the following implementations were found: + <() as Trait> error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr index ebb3abf184856..87a13889298df 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr @@ -1,12 +1,19 @@ -error[E0308]: mismatched types - --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:5 +error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied + --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:26 | +LL | fn want_bar_for_any_ccx(b: &B) + | -------------------- required by a bound in this +LL | where B : for<'ccx> Bar<'ccx> + | ------------------- required by this bound in `want_bar_for_any_ccx` +... LL | want_bar_for_any_ccx(b); - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` | - = note: expected type `for<'ccx> Bar<'ccx>` - found type `Bar<'static>` +help: consider further restricting this bound + | +LL | where B : Qux + for<'ccx> Bar<'ccx> + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index bf7373059a074..4fa404624775b 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -1,16 +1,16 @@ -error: implementation of `Foo` is not general enough - --> $DIR/hrtb-just-for-static.rs:24:5 +error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied + --> $DIR/hrtb-just-for-static.rs:24:17 | -LL | / trait Foo { -LL | | fn foo(&self, x: X) { } -LL | | } - | |_- trait `Foo` defined here +LL | fn want_hrtb() + | --------- required by a bound in this +LL | where T : for<'a> Foo<&'a isize> + | ---------------------- required by this bound in `want_hrtb` ... -LL | want_hrtb::() - | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough +LL | want_hrtb::() + | ^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt` | - = note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... - = note: ...but `StaticInt` actually implements `Foo<&'1 isize>`, for some specific lifetime `'1` + = help: the following implementations were found: + > error[E0277]: the trait bound `for<'a> &'a u32: Foo<&'a isize>` is not satisfied --> $DIR/hrtb-just-for-static.rs:30:17 diff --git a/src/test/ui/hrtb/issue-46989.rs b/src/test/ui/hrtb/issue-46989.rs index eb6549099fe6a..2c85905545807 100644 --- a/src/test/ui/hrtb/issue-46989.rs +++ b/src/test/ui/hrtb/issue-46989.rs @@ -38,5 +38,5 @@ fn assert_foo() {} fn main() { assert_foo::(); - //~^ ERROR implementation of `Foo` is not general enough + //~^ ERROR the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied } diff --git a/src/test/ui/hrtb/issue-46989.stderr b/src/test/ui/hrtb/issue-46989.stderr index 0865aa4224b97..0a7382c4dd818 100644 --- a/src/test/ui/hrtb/issue-46989.stderr +++ b/src/test/ui/hrtb/issue-46989.stderr @@ -1,16 +1,15 @@ -error: implementation of `Foo` is not general enough - --> $DIR/issue-46989.rs:40:5 +error[E0277]: the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied + --> $DIR/issue-46989.rs:40:18 | -LL | / trait Foo { -LL | | -LL | | } - | |_- trait `Foo` defined here +LL | fn assert_foo() {} + | --- required by this bound in `assert_foo` ... -LL | assert_foo::(); - | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough +LL | assert_foo::(); + | ^^^^^^^^ the trait `Foo` is not implemented for `for<'r> fn(&'r i32)` | - = note: `Foo` would have to be implemented for the type `for<'r> fn(&'r i32)` - = note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0` + = help: the following implementations were found: + error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-57362-1.rs b/src/test/ui/issues/issue-57362-1.rs index 3ba82300fabea..1fa417fe98ab7 100644 --- a/src/test/ui/issues/issue-57362-1.rs +++ b/src/test/ui/issues/issue-57362-1.rs @@ -17,7 +17,7 @@ impl Trait for fn(&T) { fn f() { let a: fn(_) = |_: &u8| {}; - a.f(); //~ ERROR implementation of `Trait` is not general enough + a.f(); //~ ERROR no method named `f` } fn main() {} diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr index 24408420b1373..5c611cd43d3cc 100644 --- a/src/test/ui/issues/issue-57362-1.stderr +++ b/src/test/ui/issues/issue-57362-1.stderr @@ -1,16 +1,17 @@ -error: implementation of `Trait` is not general enough +error[E0599]: no method named `f` found for fn pointer `fn(&u8)` in the current scope --> $DIR/issue-57362-1.rs:20:7 | -LL | / trait Trait { -LL | | fn f(self); -LL | | } - | |_- trait `Trait` defined here -... -LL | a.f(); - | ^ implementation of `Trait` is not general enough +LL | a.f(); + | ^ method not found in `fn(&u8)` | - = note: `Trait` would have to be implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0`... - = note: ...but `Trait` is actually implemented for the type `for<'r> fn(&'r u8)` + = note: `a` is a function, perhaps you wish to call it + = help: items from traits can only be used if the trait is implemented and in scope +note: `Trait` defines an item `f`, perhaps you need to implement it + --> $DIR/issue-57362-1.rs:8:1 + | +LL | trait Trait { + | ^^^^^^^^^^^ error: aborting due to previous error +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-57362-2.rs b/src/test/ui/issues/issue-57362-2.rs index 7b6594abc9647..870d7f28ba953 100644 --- a/src/test/ui/issues/issue-57362-2.rs +++ b/src/test/ui/issues/issue-57362-2.rs @@ -19,9 +19,7 @@ impl<'a> X for fn(&'a ()) { } fn g() { - let x = ::make_g(); - //~^ ERROR implementation of `X` is not general enough - //~| ERROR implementation of `X` is not general enough + let x = ::make_g(); //~ ERROR no function or associated item } fn main() {} diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index dfd48ec22275b..2edc009746455 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -1,33 +1,16 @@ -error: implementation of `X` is not general enough - --> $DIR/issue-57362-2.rs:22:13 +error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'r> fn(&'r ())` in the current scope + --> $DIR/issue-57362-2.rs:22:25 | -LL | / trait X { -LL | | type G; -LL | | fn make_g() -> Self::G; -LL | | } - | |_- trait `X` defined here -... -LL | let x = ::make_g(); - | ^^^^^^^^^^^^^^^^^^ implementation of `X` is not general enough +LL | let x = ::make_g(); + | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` | - = note: `X` would have to be implemented for the type `for<'r> fn(&'r ())` - = note: ...but `X` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` - -error: implementation of `X` is not general enough - --> $DIR/issue-57362-2.rs:22:13 - | -LL | / trait X { -LL | | type G; -LL | | fn make_g() -> Self::G; - | | ----------------------- due to a where-clause on `X::make_g`... -LL | | } - | |_- trait `X` defined here -... -LL | let x = ::make_g(); - | ^^^^^^^^^^^^^^^^^^ doesn't satisfy where-clause + = help: items from traits can only be used if the trait is implemented and in scope +note: `X` defines an item `make_g`, perhaps you need to implement it + --> $DIR/issue-57362-2.rs:8:1 | - = note: ...`X` would have to be implemented for the type `for<'r> fn(&'r ())` - = note: ...but `X` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` +LL | trait X { + | ^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.rs b/src/test/ui/lub-glb/old-lub-glb-hr.rs index 5e24a99bcc331..bc7b787cd65ac 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr.rs +++ b/src/test/ui/lub-glb/old-lub-glb-hr.rs @@ -3,21 +3,21 @@ // error. However, now that we handle subtyping correctly, we no // longer get an error, because we recognize these two types as // equivalent! +// +// Whoops -- now that we reinstituted the leak-check, we get an error +// again. fn foo( x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8), ) { - // The two types above are actually equivalent. With the older - // leak check, though, we didn't consider them as equivalent, and - // hence we gave errors. But now we've fixed that. let z = match 22 { 0 => x, - _ => y, + _ => y, //~ ERROR `match` arms have incompatible types }; } -fn foo_cast( +fn bar( x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8), ) { @@ -28,30 +28,5 @@ fn foo_cast( }; } -fn bar( - x: for<'a, 'b> fn(&'a u8, &'b u8)-> &'a u8, - y: for<'a> fn(&'a u8, &'a u8) -> &'a u8, -) { - // The two types above are not equivalent. With the older LUB/GLB - // algorithm, this may have worked (I don't remember), but now it - // doesn't because we require equality. - let z = match 22 { - 0 => x, - _ => y, //~ ERROR `match` arms have incompatible types - }; -} - -fn bar_cast( - x: for<'a, 'b> fn(&'a u8, &'b u8)-> &'a u8, - y: for<'a> fn(&'a u8, &'a u8) -> &'a u8, -) { - // But we can *upcast* explicitly the type of `x` and figure - // things out: - let z = match 22 { - 0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8, - _ => y, - }; -} - fn main() { } diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.stderr b/src/test/ui/lub-glb/old-lub-glb-hr.stderr index d242fb7789aa1..6d5d51174699f 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-hr.stderr @@ -1,17 +1,17 @@ error[E0308]: `match` arms have incompatible types - --> $DIR/old-lub-glb-hr.rs:40:14 + --> $DIR/old-lub-glb-hr.rs:16:14 | LL | let z = match 22 { | _____________- LL | | 0 => x, - | | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + | | - this is found to be of type `for<'r, 's> fn(&'r u8, &'s u8)` LL | | _ => y, - | | ^ expected bound lifetime parameter 'a, found concrete lifetime + | | ^ expected bound lifetime parameter, found concrete lifetime LL | | }; | |_____- `match` arms have incompatible types | - = note: expected type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` - found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` + = note: expected type `for<'r, 's> fn(&'r u8, &'s u8)` + found fn pointer `for<'a> fn(&'a u8, &'a u8)` error: aborting due to previous error diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr index 7848f770a70cf..27704b3e0a8c7 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr @@ -11,10 +11,10 @@ error[E0308]: mismatched types --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12 | LL | want_G(baz); - | ^^^ one type is more general than the other + | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx | = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S` - found fn pointer `for<'r> fn(&'r S) -> &'r S` + found fn item `for<'r> fn(&'r S) -> &'r S {baz}` error: aborting due to 2 previous errors diff --git a/src/test/ui/where-clauses/where-for-self-2.rs b/src/test/ui/where-clauses/where-for-self-2.rs index 0ce38e69f6b0f..31174fd4cf163 100644 --- a/src/test/ui/where-clauses/where-for-self-2.rs +++ b/src/test/ui/where-clauses/where-for-self-2.rs @@ -18,5 +18,5 @@ fn foo(x: &T) {} fn main() { - foo(&X); //~ ERROR implementation of `Bar` is not general enough + foo(&X); //~ ERROR trait bound } diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index b3cadf5b1b078..9976243b200dc 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -1,16 +1,17 @@ -error: implementation of `Bar` is not general enough +error[E0277]: the trait bound `for<'a> &'a _: Bar` is not satisfied --> $DIR/where-for-self-2.rs:21:5 | -LL | / trait Bar { -LL | | fn bar(&self); -LL | | } - | |_- trait `Bar` defined here +LL | fn foo(x: &T) + | --- required by a bound in this +LL | where for<'a> &'a T: Bar + | --- required by this bound in `foo` ... -LL | foo(&X); - | ^^^ implementation of `Bar` is not general enough +LL | foo(&X); + | ^^^ the trait `for<'a> Bar` is not implemented for `&'a _` | - = note: `Bar` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... - = note: ...but `Bar` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` + = help: the following implementations were found: + <&'static u32 as Bar> error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. From f2cf9944831f15b1940da85c8fb1b419dec9f074 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 19 May 2020 01:09:40 +0000 Subject: [PATCH 03/13] rewrite leak check to be based on universes In the new leak check, instead of getting a list of placeholders to track, we look for any placeholder that is part of a universe which was created during the snapshot. We are looking for the following error patterns: * P1: P2, where P1 != P2 * P1: R, where R is in some universe that cannot name P1 This new leak check is more precise than before, in that it accepts this patterns: * R: P1, even if R cannot name P1, because R = 'static is a valid sol'n * R: P1, R: P2, as above Note that this leak check, when running during subtyping, is less efficient than before in some sense because it is going to check and re-check all the universes created since the snapshot. We're going to move when the leak check runs to try and correct that. --- src/librustc_infer/infer/higher_ranked/mod.rs | 7 +- src/librustc_infer/infer/mod.rs | 8 +- .../infer/region_constraints/leak_check.rs | 521 ++++++++++++++---- src/librustc_infer/lib.rs | 3 + .../traits/project.rs | 12 +- .../traits/select/mod.rs | 19 +- .../associated-types-eq-hr.stderr | 4 +- ...pe.bound_a_b_ret_a_vs_bound_a_ret_a.stderr | 6 +- .../hr-subtype.bound_a_b_vs_bound_a.stderr | 6 +- .../hr-subtype.bound_a_vs_bound_a.stderr | 4 +- .../hr-subtype.bound_a_vs_bound_b.stderr | 4 +- .../hr-subtype.bound_a_vs_free_x.stderr | 6 +- ...-subtype.bound_co_a_b_vs_bound_co_a.stderr | 23 +- ...ubtype.bound_co_a_co_b_ret_contra_a.stderr | 23 +- ...hr-subtype.bound_co_a_vs_bound_co_b.stderr | 4 +- ...pe.bound_contra_a_contra_b_ret_co_a.stderr | 6 +- ...ubtype.bound_inv_a_b_vs_bound_inv_a.stderr | 6 +- ...-subtype.bound_inv_a_vs_bound_inv_b.stderr | 4 +- ...hr-subtype.free_inv_x_vs_free_inv_y.stderr | 56 +- .../hr-subtype.free_x_vs_free_x.stderr | 4 +- .../hr-subtype.free_x_vs_free_y.stderr | 28 +- src/test/ui/hr-subtype/hr-subtype.rs | 64 ++- .../hrtb-exists-forall-trait-covariant.rs | 5 +- .../hrtb-exists-forall-trait-covariant.stderr | 18 - ...regions-fn-subtyping-return-static-fail.rs | 11 +- ...ons-fn-subtyping-return-static-fail.stderr | 11 +- .../regions-fn-subtyping-return-static.rs | 13 +- .../regions-fn-subtyping-return-static.stderr | 12 - src/test/ui/rfc1623.stderr | 2 +- 29 files changed, 571 insertions(+), 319 deletions(-) delete mode 100644 src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr delete mode 100644 src/test/ui/regions/regions-fn-subtyping-return-static.stderr diff --git a/src/librustc_infer/infer/higher_ranked/mod.rs b/src/librustc_infer/infer/higher_ranked/mod.rs index 0499dc9ed2232..b94221785ae75 100644 --- a/src/librustc_infer/infer/higher_ranked/mod.rs +++ b/src/librustc_infer/infer/higher_ranked/mod.rs @@ -33,7 +33,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { self.infcx.commit_if_ok(|snapshot| { // First, we instantiate each bound region in the supertype with a // fresh placeholder region. - let (b_prime, placeholder_map) = self.infcx.replace_bound_vars_with_placeholders(b); + let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b); // Next, we instantiate each bound region in the subtype // with a fresh region variable. These region variables -- @@ -48,7 +48,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { // Compare types now that bound regions have been replaced. let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; - self.infcx.leak_check(!a_is_expected, &placeholder_map, snapshot)?; + self.infcx.leak_check(!a_is_expected, snapshot)?; debug!("higher_ranked_sub: OK result={:?}", result); @@ -119,7 +119,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn leak_check( &self, overly_polymorphic: bool, - placeholder_map: &PlaceholderMap<'tcx>, snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> RelateResult<'tcx, ()> { // If the user gave `-Zno-leak-check`, or we have been @@ -135,7 +134,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.inner.borrow_mut().unwrap_region_constraints().leak_check( self.tcx, overly_polymorphic, - placeholder_map, + self.universe(), snapshot, ) } diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 91f4b3323f30e..0e569be34aa66 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -992,12 +992,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } Some(self.commit_if_ok(|snapshot| { - let (ty::SubtypePredicate { a_is_expected, a, b }, placeholder_map) = + let (ty::SubtypePredicate { a_is_expected, a, b }, _) = self.replace_bound_vars_with_placeholders(&predicate); let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; - self.leak_check(false, &placeholder_map, snapshot)?; + self.leak_check(false, snapshot)?; Ok(ok.unit()) })) @@ -1009,13 +1009,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { predicate: ty::PolyRegionOutlivesPredicate<'tcx>, ) -> UnitResult<'tcx> { self.commit_if_ok(|snapshot| { - let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) = + let (ty::OutlivesPredicate(r_a, r_b), _) = self.replace_bound_vars_with_placeholders(&predicate); let origin = SubregionOrigin::from_obligation_cause(cause, || { RelateRegionParamBound(cause.span) }); self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` - self.leak_check(false, &placeholder_map, snapshot)?; + self.leak_check(false, snapshot)?; Ok(()) }) } diff --git a/src/librustc_infer/infer/region_constraints/leak_check.rs b/src/librustc_infer/infer/region_constraints/leak_check.rs index 91c39a0e78ffb..f3b78909b42d8 100644 --- a/src/librustc_infer/infer/region_constraints/leak_check.rs +++ b/src/librustc_infer/infer/region_constraints/leak_check.rs @@ -1,158 +1,445 @@ use super::*; -use crate::infer::{CombinedSnapshot, PlaceholderMap}; -use rustc_data_structures::undo_log::UndoLogs; +use crate::infer::CombinedSnapshot; +use rustc_data_structures::{ + graph::{scc::Sccs, vec_graph::VecGraph}, + undo_log::UndoLogs, +}; +use rustc_index::vec::Idx; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::RelateResult; impl<'tcx> RegionConstraintCollector<'_, 'tcx> { - /// Searches region constraints created since `snapshot` that - /// affect one of the placeholders in `placeholder_map`, returning - /// an error if any of the placeholders are related to another - /// placeholder or would have to escape into some parent universe - /// that cannot name them. + /// Searches new universes created during `snapshot`, looking for + /// placeholders that may "leak" out from the universes they are contained + /// in. If any leaking placeholders are found, then an `Err` is returned + /// (typically leading to the snapshot being reversed). /// - /// This is a temporary backwards compatibility measure to try and - /// retain the older (arguably incorrect) behavior of the - /// compiler. + /// The leak check *used* to be the only way we had to handle higher-ranked + /// obligations. Now that we have integrated universes into the region + /// solvers, this is no longer the case, but we retain the leak check for + /// backwards compatibility purposes. In particular, it lets us make "early" + /// decisions about whether a region error will be reported that are used in + /// coherence and elsewhere -- see #56105 and #59490 for more details. The + /// eventual fate of the leak checker is not yet settled. /// - /// NB. Although `_snapshot` isn't used, it's passed in to prove - /// that we are in a snapshot, which guarantees that we can just - /// search the "undo log" for edges. This is mostly an efficiency - /// thing -- we could search *all* region constraints, but that'd be - /// a bigger set and the data structures are not setup for that. If - /// we wind up keeping some form of this check long term, it would - /// probably be better to remove the snapshot parameter and to - /// refactor the constraint set. + /// The leak checker works by searching for the following error patterns: + /// + /// * P1: P2, where P1 != P2 + /// * P1: R, where R is in some universe that cannot name P1 + /// + /// The idea here is that each of these patterns represents something that + /// the region solver would eventually report as an error, so we can detect + /// the error early. There is a fly in the ointment, though, in that this is + /// not entirely true. In particular, in the future, we may extend the + /// environment with implied bounds or other info about how placeholders + /// relate to regions in outer universes. In that case, `P1: R` for example + /// might become solveable. + /// + /// # Summary of the implementation + /// + /// The leak checks as follows. First, we construct a graph where `R2: R1` + /// implies `R2 -> R1`, and we compute the SCCs. + /// + /// For each SCC S, we compute: + /// + /// * what placeholder P it must be equal to, if any + /// * if there are multiple placeholders that must be equal, report an error because `P1: P2` + /// * the minimum universe of its constituents + /// + /// Then we walk the SCCs in dependency order and compute + /// + /// * what placeholder they must outlive transitively + /// * if they must also be equal to a placeholder, report an error because `P1: P2` + /// * minimum universe U of all SCCs they must outlive + /// * if they must also be equal to a placeholder P, and U cannot name P, report an error, as that + /// indicates `P: R` and `R` is in an incompatible universe + /// + /// # Historical note + /// + /// Older variants of the leak check used to report errors for these + /// patterns, but we no longer do: + /// + /// * R: P1, even if R cannot name P1, because R = 'static is a valid sol'n + /// * R: P1, R: P2, as above pub fn leak_check( &mut self, tcx: TyCtxt<'tcx>, overly_polymorphic: bool, - placeholder_map: &PlaceholderMap<'tcx>, - _snapshot: &CombinedSnapshot<'_, 'tcx>, + max_universe: ty::UniverseIndex, + snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> RelateResult<'tcx, ()> { - debug!("leak_check(placeholders={:?})", placeholder_map); + debug!( + "leak_check(max_universe={:?}, snapshot.universe={:?}, overly_polymorphic={:?})", + max_universe, snapshot.universe, overly_polymorphic + ); assert!(UndoLogs::>::in_snapshot(&self.undo_log)); - // Go through each placeholder that we created. - for &placeholder_region in placeholder_map.values() { - // Find the universe this placeholder inhabits. - let placeholder = match placeholder_region { - ty::RePlaceholder(p) => p, - _ => 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); - taint_set.fixed_point( - tcx, - self.undo_log.region_constraints(), - &self.storage.data.verifys, - ); - let tainted_regions = taint_set.into_set(); - - // Report an error if two placeholders in the same universe - // are related to one another, or if a placeholder is related - // to something from a parent universe. - for &tainted_region in &tainted_regions { - if let ty::RePlaceholder(_) = tainted_region { - // Two placeholders cannot be related: - if tainted_region == placeholder_region { - continue; - } - } else if self.universe(tainted_region).can_name(placeholder.universe) { - continue; - } - - return Err(if overly_polymorphic { - debug!("overly polymorphic!"); - TypeError::RegionsOverlyPolymorphic(placeholder.name, tainted_region) - } else { - debug!("not as polymorphic!"); - TypeError::RegionsInsufficientlyPolymorphic(placeholder.name, tainted_region) - }); - } + let universe_at_start_of_snapshot = snapshot.universe; + if universe_at_start_of_snapshot == max_universe { + return Ok(()); } + let mini_graph = + &MiniGraph::new(tcx, self.undo_log.region_constraints(), &self.storage.data.verifys); + + let mut leak_check = LeakCheck::new( + tcx, + universe_at_start_of_snapshot, + max_universe, + overly_polymorphic, + mini_graph, + self, + ); + leak_check.assign_placeholder_values()?; + leak_check.propagate_scc_value()?; Ok(()) } } -#[derive(Debug)] -struct TaintSet<'tcx> { - directions: TaintDirections, - regions: FxHashSet>, +struct LeakCheck<'me, 'tcx> { + tcx: TyCtxt<'tcx>, + universe_at_start_of_snapshot: ty::UniverseIndex, + overly_polymorphic: bool, + mini_graph: &'me MiniGraph<'tcx>, + rcc: &'me RegionConstraintCollector<'me, 'tcx>, + + // Initially, for each SCC S, stores a placeholder `P` such that `S = P` + // must hold. + // + // Later, during the [`LeakCheck::propagate_scc_value`] function, this array + // is repurposed to store some placeholder `P` such that the weaker + // condition `S: P` must hold. (This is true if `S: S1` transitively and `S1 + // = P`.) + scc_placeholders: IndexVec>, + + // For each SCC S, track the minimum universe that flows into it. Note that + // this is both the minimum of the universes for every region that is a + // member of the SCC, but also if you have `R1: R2`, then the universe of + // `R2` must be less than the universe of `R1` (i.e., `R1` flows `R2`). To + // see that, imagine that you have `P1: R` -- in that case, `R` must be + // either the placeholder `P1` or the empty region in that same universe. + // + // To detect errors, we look for an SCC S where the values in + // `scc_values[S]` (if any) cannot be stored into `scc_universes[S]`. + scc_universes: IndexVec>, } -impl<'tcx> TaintSet<'tcx> { - fn new(directions: TaintDirections, initial_region: ty::Region<'tcx>) -> Self { - let mut regions = FxHashSet::default(); - regions.insert(initial_region); - TaintSet { directions, regions } +impl<'me, 'tcx> LeakCheck<'me, 'tcx> { + fn new( + tcx: TyCtxt<'tcx>, + universe_at_start_of_snapshot: ty::UniverseIndex, + max_universe: ty::UniverseIndex, + overly_polymorphic: bool, + mini_graph: &'me MiniGraph<'tcx>, + rcc: &'me RegionConstraintCollector<'me, 'tcx>, + ) -> Self { + let dummy_scc_universe = SccUniverse { universe: max_universe, region: None }; + Self { + tcx, + universe_at_start_of_snapshot, + overly_polymorphic, + mini_graph, + rcc, + scc_placeholders: IndexVec::from_elem_n(None, mini_graph.sccs.num_sccs()), + scc_universes: IndexVec::from_elem_n(dummy_scc_universe, mini_graph.sccs.num_sccs()), + } + } + + /// Compute what placeholders (if any) each SCC must be equal to. + /// Also compute the minimum universe of all the regions in each SCC. + fn assign_placeholder_values(&mut self) -> RelateResult<'tcx, ()> { + // First walk: find each placeholder that is from a newly created universe. + for (region, leak_check_node) in &self.mini_graph.nodes { + let scc = self.mini_graph.sccs.scc(*leak_check_node); + + // Set the universe of each SCC to be the minimum of its constituent universes + let universe = self.rcc.universe(region); + debug!( + "assign_placeholder_values: scc={:?} universe={:?} region={:?}", + scc, universe, region + ); + self.scc_universes[scc].take_min(universe, region); + + // Detect those SCCs that directly contain a placeholder + if let ty::RePlaceholder(placeholder) = region { + if self.universe_at_start_of_snapshot.cannot_name(placeholder.universe) { + self.assign_scc_value(scc, *placeholder)?; + } + } + } + + Ok(()) } - fn fixed_point<'a>( + // assign_scc_value(S, P): Update `scc_values` to account for the fact that `P: S` must hold. + // This may create an error. + fn assign_scc_value( &mut self, - tcx: TyCtxt<'tcx>, - undo_log: impl IntoIterator> + Clone, - verifys: &[Verify<'tcx>], - ) where - 'tcx: 'a, - { - let mut prev_len = 0; - while prev_len < self.len() { - debug!("tainted: prev_len = {:?} new_len = {:?}", prev_len, self.len()); - - prev_len = self.len(); - - for undo_entry in undo_log.clone() { - match undo_entry { - &AddConstraint(Constraint::VarSubVar(a, b)) => { - self.add_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b))); - } - &AddConstraint(Constraint::RegSubVar(a, b)) => { - self.add_edge(a, tcx.mk_region(ReVar(b))); - } - &AddConstraint(Constraint::VarSubReg(a, b)) => { - self.add_edge(tcx.mk_region(ReVar(a)), b); - } - &AddConstraint(Constraint::RegSubReg(a, b)) => { - self.add_edge(a, b); - } - &AddGiven(a, b) => { - self.add_edge(a, tcx.mk_region(ReVar(b))); - } - &AddVerify(i) => span_bug!( - verifys[i].origin.span(), - "we never add verifications while doing higher-ranked things", - ), - &AddCombination(..) | &AddVar(..) => {} + scc: LeakCheckScc, + placeholder: ty::PlaceholderRegion, + ) -> RelateResult<'tcx, ()> { + match self.scc_placeholders[scc] { + Some(p) => { + assert_ne!(p, placeholder); + return Err(self.placeholder_error(p, placeholder)); + } + None => { + self.scc_placeholders[scc] = Some(placeholder); + } + }; + + Ok(()) + } + + /// For each SCC S, iterate over each successor S1 where `S: S1`: + /// + /// * Compute + /// Iterate over each SCC `S` and ensure that, for each `S1` where `S1: S`, + /// `universe(S) <= universe(S1)`. This executes after + /// `assign_placeholder_values`, so `universe(S)` is already the minimum + /// universe of any of its direct constituents. + fn propagate_scc_value(&mut self) -> RelateResult<'tcx, ()> { + // Loop invariants: + // + // On start of the loop iteration for `scc1`: + // + // * `scc_universes[scc1]` contains the minimum universe of the + // constituents of `scc1` + // * `scc_placeholder[scc1]` stores the placeholder that `scc1` must + // be equal to (if any) + // + // For each succssor `scc2` where `scc1: scc2`: + // + // * `scc_placeholder[scc2]` stores some placeholder `P` where + // `scc2: P` (if any) + // * `scc_universes[scc2]` contains the minimum universe of the + // constituents of `scc2` and any of its successors + for scc1 in self.mini_graph.sccs.all_sccs() { + debug!( + "propagate_scc_value: scc={:?} with universe {:?}", + scc1, self.scc_universes[scc1] + ); + + // Walk over each `scc2` such that `scc1: scc2` and compute: + // + // * `scc1_universe`: the minimum universe of `scc2` and the constituents of `scc1` + // * `succ_bound`: placeholder `P` that the successors must outlive, if any (if there are multiple, + // we pick one arbitrarily) + let mut scc1_universe = self.scc_universes[scc1]; + let mut succ_bound = None; + for &scc2 in self.mini_graph.sccs.successors(scc1) { + let SccUniverse { universe: scc2_universe, region: scc2_region } = + self.scc_universes[scc2]; + + scc1_universe.take_min(scc2_universe, scc2_region.unwrap()); + + if let Some(b) = self.scc_placeholders[scc2] { + succ_bound = Some(b); } } + + // Update minimum universe of scc1. + self.scc_universes[scc1] = scc1_universe; + + // At this point, `scc_placholder[scc1]` stores the placeholder that + // `scc1` must be equal to, if any. + if let Some(scc1_placeholder) = self.scc_placeholders[scc1] { + debug!( + "propagate_scc_value: scc1={:?} placeholder={:?} scc1_universe={:?}", + scc1, scc1_placeholder, scc1_universe + ); + + // Check if `P1: R` for some `R` in a universe that cannot name + // P1. That's an error. + if scc1_universe.universe.cannot_name(scc1_placeholder.universe) { + return Err(self.error(scc1_placeholder, scc1_universe.region.unwrap())); + } + + // Check if we have some placeholder where `S: P2` + // (transitively). In that case, since `S = P1`, that implies + // `P1: P2`, which is an error condition. + if let Some(scc2_placeholder) = succ_bound { + assert_ne!(scc1_placeholder, scc2_placeholder); + return Err(self.placeholder_error(scc1_placeholder, scc2_placeholder)); + } + } else { + // Otherwise, we can reach a placeholder if some successor can. + self.scc_placeholders[scc1] = succ_bound; + } + + // At this point, `scc_placeholder[scc1]` stores some placeholder that `scc1` must outlive (if any). } + Ok(()) } - fn into_set(self) -> FxHashSet> { - self.regions + fn placeholder_error( + &self, + placeholder1: ty::PlaceholderRegion, + placeholder2: ty::PlaceholderRegion, + ) -> TypeError<'tcx> { + self.error(placeholder1, self.tcx.mk_region(ty::RePlaceholder(placeholder2))) } - fn len(&self) -> usize { - self.regions.len() + fn error( + &self, + placeholder: ty::PlaceholderRegion, + other_region: ty::Region<'tcx>, + ) -> TypeError<'tcx> { + if self.overly_polymorphic { + return TypeError::RegionsOverlyPolymorphic(placeholder.name, other_region); + } else { + return TypeError::RegionsInsufficientlyPolymorphic(placeholder.name, other_region); + } } +} - fn add_edge(&mut self, source: ty::Region<'tcx>, target: ty::Region<'tcx>) { - if self.directions.incoming { - if self.regions.contains(&target) { - self.regions.insert(source); - } +// States we need to distinguish: +// +// * must be equal to a placeholder (i.e., a placeholder is in the SCC) +// * it could conflict with some other regions in the SCC in different universes +// * or a different placeholder +// * `P1: S` and `S` must be equal to a placeholder +// * `P1: S` and `S` is in an incompatible universe +// +// So if we +// +// (a) compute which placeholder (if any) each SCC must be equal to +// (b) compute its minimum universe +// (c) compute *some* placeholder where `S: P1` (any one will do) +// +// then we get an error if: +// +// - it must be equal to a placeholder `P1` and minimum universe cannot name `P1` +// - `S: P1` and minimum universe cannot name `P1` +// - `S: P1` and we must be equal to `P2` +// +// So we want to track: +// +// * Equal placeholder (if any) +// * Some bounding placeholder (if any) +// * Minimum universe +// +// * We compute equal placeholder + minimum universe of constituents in first pass +// * Then we walk in order and compute from our dependencies `S1` where `S: S1` (`S -> S1`) +// * bounding placeholder (if any) +// * minimum universe +// * And if we must be equal to a placeholder then we check it against +// * minimum universe +// * no bounding placeholder + +/// Tracks the "minimum universe" for each SCC, along with some region that +/// caused it to change. +#[derive(Copy, Clone, Debug)] +struct SccUniverse<'tcx> { + /// For some SCC S, the minimum universe of: + /// + /// * each region R in S + /// * each SCC S1 such that S: S1 + universe: ty::UniverseIndex, + + /// Some region that caused `universe` to be what it is. + region: Option>, +} + +impl<'tcx> SccUniverse<'tcx> { + /// If `universe` is less than our current universe, then update + /// `self.universe` and `self.region`. + fn take_min(&mut self, universe: ty::UniverseIndex, region: ty::Region<'tcx>) { + if universe < self.universe || self.region.is_none() { + self.universe = universe; + self.region = Some(region); } + } +} + +rustc_index::newtype_index! { + struct LeakCheckNode { + DEBUG_FORMAT = "LeakCheckNode({})" + } +} - if self.directions.outgoing { - if self.regions.contains(&source) { - self.regions.insert(target); +rustc_index::newtype_index! { + struct LeakCheckScc { + DEBUG_FORMAT = "LeakCheckScc({})" + } +} + +/// Represents the graph of constraints. For each `R1: R2` constraint we create +/// an edge `R1 -> R2` in the graph. +struct MiniGraph<'tcx> { + /// Map from a region to the index of the node in the graph. + nodes: FxHashMap, LeakCheckNode>, + + /// Map from node index to SCC, and stores the successors of each SCC. All + /// the regions in the same SCC are equal to one another, and if `S1 -> S2`, + /// then `S1: S2`. + sccs: Sccs, +} + +impl<'tcx> MiniGraph<'tcx> { + fn new<'a>( + tcx: TyCtxt<'tcx>, + undo_log: impl Iterator>, + verifys: &[Verify<'tcx>], + ) -> Self + where + 'tcx: 'a, + { + let mut nodes = FxHashMap::default(); + let mut edges = Vec::new(); + + // Note that if `R2: R1`, we get a callback `r1, r2`, so `target` is first parameter. + Self::iterate_undo_log(tcx, undo_log, verifys, |target, source| { + let source_node = Self::add_node(&mut nodes, source); + let target_node = Self::add_node(&mut nodes, target); + edges.push((source_node, target_node)); + }); + let graph = VecGraph::new(nodes.len(), edges); + let sccs = Sccs::new(&graph); + Self { nodes, sccs } + } + + /// Invokes `each_edge(R1, R2)` for each edge where `R2: R1` + fn iterate_undo_log<'a>( + tcx: TyCtxt<'tcx>, + undo_log: impl Iterator>, + verifys: &[Verify<'tcx>], + mut each_edge: impl FnMut(ty::Region<'tcx>, ty::Region<'tcx>), + ) where + 'tcx: 'a, + { + for undo_entry in undo_log { + match undo_entry { + &AddConstraint(Constraint::VarSubVar(a, b)) => { + each_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b))); + } + &AddConstraint(Constraint::RegSubVar(a, b)) => { + each_edge(a, tcx.mk_region(ReVar(b))); + } + &AddConstraint(Constraint::VarSubReg(a, b)) => { + each_edge(tcx.mk_region(ReVar(a)), b); + } + &AddConstraint(Constraint::RegSubReg(a, b)) => { + each_edge(a, b); + } + &AddGiven(a, b) => { + each_edge(a, tcx.mk_region(ReVar(b))); + } + &AddVerify(i) => span_bug!( + verifys[i].origin.span(), + "we never add verifications while doing higher-ranked things", + ), + &AddCombination(..) | &AddVar(..) => {} } } } + + fn add_node( + nodes: &mut FxHashMap, LeakCheckNode>, + r: ty::Region<'tcx>, + ) -> LeakCheckNode { + let l = nodes.len(); + *nodes.entry(r).or_insert(LeakCheckNode::new(l)) + } } diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs index ed04ee02b7203..0f3f3db867959 100644 --- a/src/librustc_infer/lib.rs +++ b/src/librustc_infer/lib.rs @@ -16,6 +16,9 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(const_fn)] +#![feature(const_if_match)] +#![feature(const_panic)] #![feature(extend_one)] #![feature(never_type)] #![feature(or_patterns)] diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 574d50a4fccc2..4bc58fbaadcda 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -150,14 +150,12 @@ pub fn poly_project_and_unify_type<'cx, 'tcx>( let infcx = selcx.infcx(); infcx.commit_if_ok(|snapshot| { - let (placeholder_predicate, placeholder_map) = + let (placeholder_predicate, _) = infcx.replace_bound_vars_with_placeholders(&obligation.predicate); let placeholder_obligation = obligation.with(placeholder_predicate); let result = project_and_unify_type(selcx, &placeholder_obligation)?; - infcx - .leak_check(false, &placeholder_map, snapshot) - .map_err(|err| MismatchedProjectionTypes { err })?; + infcx.leak_check(false, snapshot).map_err(|err| MismatchedProjectionTypes { err })?; Ok(result) }) } @@ -300,7 +298,11 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { fn fold>(&mut self, value: &T) -> T { let value = self.selcx.infcx().resolve_vars_if_possible(value); - if !value.has_projections() { value } else { value.fold_with(self) } + if !value.has_projections() { + value + } else { + value.fold_with(self) + } } } diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs index 076bdad423ab8..e90acbbce67ba 100644 --- a/src/librustc_trait_selection/traits/select/mod.rs +++ b/src/librustc_trait_selection/traits/select/mod.rs @@ -21,7 +21,7 @@ use super::{Normalized, ProjectionCacheKey}; use super::{ObligationCause, PredicateObligation, TraitObligation}; use super::{Overflow, SelectionError, Unimplemented}; -use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener}; +use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, TypeFreshener}; use crate::traits::error_reporting::InferCtxtExt; use crate::traits::project::ProjectionCacheKeyExt; use rustc_ast::attr; @@ -1265,7 +1265,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> bool { let poly_trait_predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate); - let (placeholder_trait_predicate, placeholder_map) = + let (placeholder_trait_predicate, _) = self.infcx().replace_bound_vars_with_placeholders(&poly_trait_predicate); debug!( "match_projection_obligation_against_definition_bounds: \ @@ -1297,7 +1297,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation, bound, placeholder_trait_predicate.trait_ref, - &placeholder_map, snapshot, ) }) { @@ -1320,7 +1319,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation, bound, placeholder_trait_predicate.trait_ref, - &placeholder_map, snapshot, ); @@ -1335,7 +1333,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, trait_bound: ty::PolyTraitRef<'tcx>, placeholder_trait_ref: ty::TraitRef<'tcx>, - placeholder_map: &PlaceholderMap<'tcx>, snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> bool { debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars()); @@ -1343,7 +1340,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .at(&obligation.cause, obligation.param_env) .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) .is_ok() - && self.infcx.leak_check(false, placeholder_map, snapshot).is_ok() + && self.infcx.leak_check(false, snapshot).is_ok() } fn evaluate_where_clause<'o>( @@ -1837,7 +1834,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(()); } - let (placeholder_obligation, placeholder_map) = + let (placeholder_obligation, _) = self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate); let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref; @@ -1869,7 +1866,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?; nested_obligations.extend(obligations); - if let Err(e) = self.infcx.leak_check(false, &placeholder_map, snapshot) { + if let Err(e) = self.infcx.leak_check(false, snapshot) { debug!("match_impl: failed leak check due to `{}`", e); return Err(()); } @@ -2405,7 +2402,11 @@ impl<'o, 'tcx> TraitObligationStackList<'o, 'tcx> { } fn depth(&self) -> usize { - if let Some(head) = self.head { head.depth } else { 0 } + if let Some(head) = self.head { + head.depth + } else { + 0 + } } } diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 58d72746e76aa..50f1d07142f8c 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -49,7 +49,7 @@ LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> | ------------- required by this bound in `tuple_one` ... LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime + | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'y, found concrete lifetime error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied --> $DIR/associated-types-eq-hr.rs:97:17 @@ -74,7 +74,7 @@ LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> | ------------- required by this bound in `tuple_two` ... LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime + | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'y, found concrete lifetime error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied --> $DIR/associated-types-eq-hr.rs:107:18 diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr index b91798fa12379..1da224a3e85e0 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr @@ -1,12 +1,12 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a ... LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, -LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } - | |_________________________________________________________________________________________- in this macro invocation +LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } + | |_____________________________________________- in this macro invocation | = note: expected enum `std::option::Option fn(&'a u32, &'b u32) -> &'a u32>` found enum `std::option::Option fn(&'a u32, &'a u32) -> &'a u32>` diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr index 45f53d4fe99db..880a8c7be8305 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr @@ -1,12 +1,12 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | 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 +LL | | for<'a> fn(&'a u32, &'a u32)) } + | |__________________________________- in this macro invocation | = note: expected enum `std::option::Option fn(&'a u32, &'b u32)>` found enum `std::option::Option fn(&'a u32, &'a u32)>` diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr index 6aba6466fada5..0cc30e479c7b9 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr +++ b/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:104:1 | LL | / fn main() { LL | | LL | | LL | | -LL | | +... | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr index 6aba6466fada5..0cc30e479c7b9 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr +++ b/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:104:1 | LL | / fn main() { LL | | LL | | LL | | -LL | | +... | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr index c3e4f6d2ed0c1..d2abcc4a66091 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -1,12 +1,12 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a ... LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), -LL | | fn(&'x u32)) } - | |___________________________________________- in this macro invocation +LL | | fn(&'x u32)) } + | |______________- in this macro invocation | = note: expected enum `std::option::Option fn(&'a u32)>` found enum `std::option::Option` diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr index 4d7b86027f564..0cc30e479c7b9 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr +++ b/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:104: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 fn(Co<'a>, Co<'b>)>` - found enum `std::option::Option 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`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr index 7f0a4197dd7fe..0cc30e479c7b9 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_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:104: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 fn(Co<'a>, Co<'b>) -> Contra<'a>>` - found enum `std::option::Option 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`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr index 6aba6466fada5..0cc30e479c7b9 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr @@ -1,11 +1,11 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:104:1 | LL | / fn main() { LL | | LL | | LL | | -LL | | +... | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr index c12e543a44e79..e1a16f5149cc6 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr @@ -1,12 +1,12 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | 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 +LL | | for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) } + | |__________________________________________________- in this macro invocation | = note: expected enum `std::option::Option fn(Contra<'a>, Contra<'b>) -> Co<'a>>` found enum `std::option::Option fn(Contra<'a>, Contra<'a>) -> Co<'a>>` diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr index 460356856bd56..5fec1e9a92eae 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr @@ -1,12 +1,12 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a ... LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), -LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } - | |__________________________________________________________________________- in this macro invocation +LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } + | |__________________________________- in this macro invocation | = note: expected enum `std::option::Option fn(Inv<'a>, Inv<'b>)>` found enum `std::option::Option fn(Inv<'a>, Inv<'a>)>` diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr index 6aba6466fada5..0cc30e479c7b9 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr @@ -1,11 +1,11 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:104:1 | LL | / fn main() { LL | | LL | | LL | | -LL | | +... | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr index fc3643306e628..3c8af20e50cef 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr @@ -1,65 +1,65 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:33:26 + --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t2>(None::<$t1>); | ^^^^^^^^^^^ lifetime mismatch ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation | = note: expected enum `std::option::Option)>` found enum `std::option::Option)>` -note: the lifetime `'x` as defined on the function body at 32:20... - --> $DIR/hr-subtype.rs:32:20 +note: the lifetime `'x` as defined on the function body at 38:20... + --> $DIR/hr-subtype.rs:38:20 | -LL | fn subtype<'x,'y:'x,'z:'y>() { +LL | fn subtype<'x, 'y: 'x, 'z: 'y>() { | ^^ ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation -note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 32:23 - --> $DIR/hr-subtype.rs:32:23 +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation +note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:24 + --> $DIR/hr-subtype.rs:38:24 | -LL | fn subtype<'x,'y:'x,'z:'y>() { - | ^^ +LL | fn subtype<'x, 'y: 'x, 'z: 'y>() { + | ^^ ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^ lifetime mismatch ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation | = note: expected enum `std::option::Option)>` found enum `std::option::Option)>` -note: the lifetime `'x` as defined on the function body at 38:22... - --> $DIR/hr-subtype.rs:38:22 +note: the lifetime `'x` as defined on the function body at 44:22... + --> $DIR/hr-subtype.rs:44:22 | -LL | fn supertype<'x,'y:'x,'z:'y>() { +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { | ^^ ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation -note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25 - --> $DIR/hr-subtype.rs:38:25 +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation +note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 44:26 + --> $DIR/hr-subtype.rs:44:26 | -LL | fn supertype<'x,'y:'x,'z:'y>() { - | ^^ +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { + | ^^ ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr index 6aba6466fada5..0cc30e479c7b9 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr +++ b/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:104:1 | LL | / fn main() { LL | | LL | | LL | | -LL | | +... | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr index 0dde27788f629..7b4cdd4a419b4 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr @@ -1,33 +1,33 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^ lifetime mismatch ... LL | / check! { free_x_vs_free_y: (fn(&'x u32), -LL | | fn(&'y u32)) } - | |__________________________________________- in this macro invocation +LL | | fn(&'y u32)) } + | |______________- in this macro invocation | = note: expected enum `std::option::Option` found enum `std::option::Option` -note: the lifetime `'x` as defined on the function body at 38:22... - --> $DIR/hr-subtype.rs:38:22 +note: the lifetime `'x` as defined on the function body at 44:22... + --> $DIR/hr-subtype.rs:44:22 | -LL | fn supertype<'x,'y:'x,'z:'y>() { +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { | ^^ ... LL | / check! { free_x_vs_free_y: (fn(&'x u32), -LL | | fn(&'y u32)) } - | |__________________________________________- in this macro invocation -note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25 - --> $DIR/hr-subtype.rs:38:25 +LL | | fn(&'y u32)) } + | |______________- in this macro invocation +note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 44:26 + --> $DIR/hr-subtype.rs:44:26 | -LL | fn supertype<'x,'y:'x,'z:'y>() { - | ^^ +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { + | ^^ ... LL | / check! { free_x_vs_free_y: (fn(&'x u32), -LL | | fn(&'y u32)) } - | |__________________________________________- in this macro invocation +LL | | fn(&'y u32)) } + | |______________- in this macro invocation = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/hr-subtype/hr-subtype.rs b/src/test/ui/hr-subtype/hr-subtype.rs index b31f198bd97bf..9e9c2ce9c61d7 100644 --- a/src/test/ui/hr-subtype/hr-subtype.rs +++ b/src/test/ui/hr-subtype/hr-subtype.rs @@ -18,24 +18,30 @@ // revisions: bound_inv_a_b_vs_bound_inv_a // revisions: bound_a_b_ret_a_vs_bound_a_ret_a -fn gimme(_: Option) { } +fn gimme(_: Option) {} -struct Inv<'a> { x: *mut &'a u32 } +struct Inv<'a> { + x: *mut &'a u32, +} -struct Co<'a> { x: fn(&'a u32) } +struct Co<'a> { + x: fn(&'a u32), +} -struct Contra<'a> { x: &'a u32 } +struct Contra<'a> { + x: &'a u32, +} macro_rules! check { ($rev:ident: ($t1:ty, $t2:ty)) => { #[cfg($rev)] - fn subtype<'x,'y:'x,'z:'y>() { + fn subtype<'x, 'y: 'x, 'z: 'y>() { gimme::<$t2>(None::<$t1>); //[free_inv_x_vs_free_inv_y]~^ ERROR } #[cfg($rev)] - fn supertype<'x,'y:'x,'z:'y>() { + fn supertype<'x, 'y: 'x, 'z: 'y>() { gimme::<$t1>(None::<$t2>); //[bound_a_vs_free_x]~^ ERROR //[free_x_vs_free_y]~^^ ERROR @@ -43,35 +49,33 @@ macro_rules! check { //[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 + //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^ ERROR } - } + }; } // If both have bound regions, they are equivalent, regardless of // variant. check! { bound_a_vs_bound_a: (for<'a> fn(&'a u32), - for<'a> fn(&'a u32)) } +for<'a> fn(&'a u32)) } check! { bound_a_vs_bound_b: (for<'a> fn(&'a u32), - for<'b> fn(&'b u32)) } +for<'b> fn(&'b u32)) } check! { bound_inv_a_vs_bound_inv_b: (for<'a> fn(Inv<'a>), - for<'b> fn(Inv<'b>)) } +for<'b> fn(Inv<'b>)) } check! { bound_co_a_vs_bound_co_b: (for<'a> fn(Co<'a>), - for<'b> fn(Co<'b>)) } +for<'b> fn(Co<'b>)) } // Bound is a subtype of free. check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), - fn(&'x u32)) } +fn(&'x u32)) } // Two free regions are relatable if subtyping holds. check! { free_x_vs_free_x: (fn(&'x u32), - fn(&'x u32)) } +fn(&'x u32)) } check! { free_x_vs_free_y: (fn(&'x u32), - fn(&'y u32)) } +fn(&'y u32)) } check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), - fn(Inv<'y>)) } +fn(Inv<'y>)) } // Somewhat surprisingly, a fn taking two distinct bound lifetimes and // a fn taking one bound lifetime can be interchangeable, but only if @@ -82,25 +86,27 @@ check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), // intersection; // - if we are contravariant, then 'a can be inferred to 'static. check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32), - for<'a> fn(&'a u32, &'a u32)) } +for<'a> fn(&'a u32, &'a u32)) } check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>), - for<'a> fn(Co<'a>, Co<'a>)) } +for<'a> fn(Co<'a>, Co<'a>)) } check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>, - for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) } +for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) } check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>, - for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) } +for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) } // If we make those lifetimes invariant, then the two types are not interchangeable. check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), - for<'a> fn(Inv<'a>, Inv<'a>)) } +for<'a> fn(Inv<'a>, Inv<'a>)) } check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, - for<'a> fn(&'a u32, &'a u32) -> &'a u32) } +for<'a> fn(&'a u32, &'a u32) -> &'a u32) } #[rustc_error] fn main() { -//[bound_a_vs_bound_a]~^ ERROR fatal error triggered by #[rustc_error] -//[bound_a_vs_bound_b]~^^ ERROR fatal error triggered by #[rustc_error] -//[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_vs_bound_a]~^ ERROR fatal error triggered by #[rustc_error] + //[bound_a_vs_bound_b]~^^ ERROR fatal error triggered by #[rustc_error] + //[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_co_a_b_vs_bound_co_a]~^^^^^^ ERROR + //[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs index 95b57d6c5bb5e..f95496a6c3cc0 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs @@ -2,6 +2,8 @@ // // In particular, we test this pattern in trait solving, where it is not connected // to any part of the source code. +// +// check-pass trait Trait {} @@ -30,9 +32,6 @@ fn main() { // - `?b: ?a` -- solveable if `?b` is inferred to `'static` // - So the subtyping check succeeds, somewhat surprisingly. // This is because we can use `'static`. - // - // NB. *However*, the reinstated leak-check gives an error here. foo::<()>(); - //~^ ERROR not satisfied } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr deleted file mode 100644 index 1e335f9ee9610..0000000000000 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0277]: the trait bound `(): Trait fn(fn(&'b u32))>` is not satisfied - --> $DIR/hrtb-exists-forall-trait-covariant.rs:36:11 - | -LL | fn foo() - | --- required by a bound in this -LL | where -LL | T: Trait fn(fn(&'b u32))>, - | ------------------------------ required by this bound in `foo` -... -LL | foo::<()>(); - | ^^ the trait `Trait fn(fn(&'b u32))>` is not implemented for `()` - | - = help: the following implementations were found: - <() as Trait> - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.rs b/src/test/ui/regions-fn-subtyping-return-static-fail.rs index 2dd0c9796e258..539221b5a046c 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.rs +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.rs @@ -13,11 +13,11 @@ struct S; // Given 'cx, return 'cx type F = for<'cx> fn(&'cx S) -> &'cx S; -fn want_F(f: F) { } +fn want_F(f: F) {} // Given anything, return 'static type G = for<'cx> fn(&'cx S) -> &'static S; -fn want_G(f: G) { } +fn want_G(f: G) {} // Should meet both. fn foo(x: &S) -> &'static S { @@ -25,7 +25,7 @@ fn foo(x: &S) -> &'static S { } // Should meet both. -fn bar<'a,'b>(x: &'a S) -> &'b S { +fn bar<'a, 'b>(x: &'a S) -> &'b S { panic!() } @@ -37,7 +37,7 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - want_F(bar); //~ ERROR mismatched types + want_F(bar); want_F(baz); } @@ -48,5 +48,4 @@ fn supply_G() { want_G(baz); //~ ERROR mismatched types } -pub fn main() { -} +pub fn main() {} diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr index 27704b3e0a8c7..6d75ace3c4698 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr @@ -1,12 +1,3 @@ -error[E0308]: mismatched types - --> $DIR/regions-fn-subtyping-return-static-fail.rs:40:12 - | -LL | want_F(bar); - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx - | - = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'cx S` - found fn item `for<'a> fn(&'a S) -> &S {bar::<'_>}` - error[E0308]: mismatched types --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12 | @@ -16,6 +7,6 @@ LL | want_G(baz); = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S` found fn item `for<'r> fn(&'r S) -> &'r S {baz}` -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.rs b/src/test/ui/regions/regions-fn-subtyping-return-static.rs index fa2cc37d05b2b..de14d5ba82a1b 100644 --- a/src/test/ui/regions/regions-fn-subtyping-return-static.rs +++ b/src/test/ui/regions/regions-fn-subtyping-return-static.rs @@ -5,6 +5,8 @@ // *ANY* lifetime and returns a reference with the 'static lifetime. // This can safely be considered to be an instance of `F` because all // lifetimes are sublifetimes of 'static. +// +// check-pass #![allow(dead_code)] #![allow(unused_variables)] @@ -14,11 +16,11 @@ struct S; // Given 'cx, return 'cx type F = for<'cx> fn(&'cx S) -> &'cx S; -fn want_F(f: F) { } +fn want_F(f: F) {} // Given anything, return 'static type G = for<'cx> fn(&'cx S) -> &'static S; -fn want_G(f: G) { } +fn want_G(f: G) {} // Should meet both. fn foo(x: &S) -> &'static S { @@ -26,7 +28,7 @@ fn foo(x: &S) -> &'static S { } // Should meet both. -fn bar<'a,'b>(x: &'a S) -> &'b S { +fn bar<'a, 'b>(x: &'a S) -> &'b S { panic!() } @@ -38,10 +40,9 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - want_F(bar); //~ ERROR mismatched types + want_F(bar); want_F(baz); } -pub fn main() { -} +pub fn main() {} diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions/regions-fn-subtyping-return-static.stderr deleted file mode 100644 index a8a7e97e6acf6..0000000000000 --- a/src/test/ui/regions/regions-fn-subtyping-return-static.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/regions-fn-subtyping-return-static.rs:41:12 - | -LL | want_F(bar); - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx - | - = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'cx S` - found fn item `for<'a> fn(&'a S) -> &S {bar::<'_>}` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.stderr index ca956004ef76f..75df99137179b 100644 --- a/src/test/ui/rfc1623.stderr +++ b/src/test/ui/rfc1623.stderr @@ -36,7 +36,7 @@ error[E0271]: type mismatch resolving `for<'a, 'b> _ {id::<_>} as std: --> $DIR/rfc1623.rs:25:8 | LL | f: &id, - | ^^^ expected bound lifetime parameter 'a, found concrete lifetime + | ^^^ expected bound lifetime parameter 'b, found concrete lifetime | = note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` From 5a7a850753b60abfd2a806bf6bba4259d3535e7b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 20 May 2020 10:19:36 +0000 Subject: [PATCH 04/13] move leak-check to during coherence, candidate eval In particular, it no longer occurs during the subtyping check. This is important for enabling lazy normalization, because the subtyping check will be producing sub-obligations that could affect its results. Consider an example like for<'a> fn(<&'a as Mirror>::Item) = fn(&'b u8) where `::Item = T` for all `T`. We will wish to produce a new subobligation like <'!1 as Mirror>::Item = &'b u8 This will, after being solved, ultimately yield a constraint that `'!1 = 'b` which will fail. But with the leak-check being performed on subtyping, there is no opportunity to normalize `<'!1 as Mirror>::Item` (unless we invoke that normalization directly from within subtyping, and I would prefer that subtyping and unification are distinct operations rather than part of the trait solving stack). The reason to keep the leak check during coherence and trait evaluation is partly for backwards compatibility. The coherence change permits impls for `fn(T)` and `fn(&T)` to co-exist, and the trait evaluation change means that we can distinguish those two cases without ambiguity errors. It also avoids recreating #57639, where we were incorrectly choosing a where clause that would have failed the leak check over the impl which succeeds. The other reason to keep the leak check in those places is that I think it is actually close to the model we want. To the point, I think the trait solver ought to have the job of "breaking down" higher-ranked region obligation like ``!1: '2` into into region obligations that operate on things in the root universe, at which point they should be handed off to polonius. The leak check isn't *really* doing that -- these obligations are still handed to the region solver to process -- but if/when we do adopt that model, the decision to pass/fail would be happening in roughly this part of the code. This change had somewhat more side-effects than I anticipated. It seems like there are cases where the leak-check was not being enforced during method proving and trait selection. I haven't quite tracked this down but I think it ought to be documented, so that we know what precisely we are committing to. One surprising test was `issue-30786.rs`. The behavior there seems a bit "fishy" to me, but the problem is not related to the leak check change as far as I can tell, but more to do with the closure signature inference code and perhaps the associated type projection, which together seem to be conspiring to produce an unexpected signature. Nonetheless, it is an example of where changing the leak-check can have some unexpected consequences: we're now failing to resolve a method earlier than we were, which suggests we might change some method resolutions that would have been ambiguous to be successful. TODO: * figure out remainig test failures * add new coherence tests for the patterns we ARE disallowing --- src/librustc_infer/infer/higher_ranked/mod.rs | 18 +++- .../infer/region_constraints/leak_check.rs | 1 + .../traits/coherence.rs | 10 +- .../traits/project.rs | 6 +- .../traits/select/mod.rs | 12 ++- .../associated-types-eq-hr.stderr | 2 +- ...project-fn-ret-invariant.krisskross.stderr | 30 +++--- .../cache/project-fn-ret-invariant.ok.stderr | 6 +- .../project-fn-ret-invariant.oneuse.stderr | 14 +-- .../cache/project-fn-ret-invariant.rs | 41 +++---- .../project-fn-ret-invariant.transmute.stderr | 26 ++--- .../expect-fn-supply-fn.rs | 17 +-- .../expect-fn-supply-fn.stderr | 71 +++++------- src/test/ui/closures/issue-41366.rs | 3 +- src/test/ui/closures/issue-41366.stderr | 21 ++-- .../ui/generator/resume-arg-late-bound.rs | 3 +- .../ui/generator/resume-arg-late-bound.stderr | 28 +++-- ...pe.bound_a_b_ret_a_vs_bound_a_ret_a.stderr | 2 +- .../hr-subtype.bound_a_b_vs_bound_a.stderr | 23 ++-- .../hr-subtype.bound_a_vs_bound_a.stderr | 2 +- .../hr-subtype.bound_a_vs_bound_b.stderr | 2 +- .../hr-subtype.bound_a_vs_free_x.stderr | 2 +- ...-subtype.bound_co_a_b_vs_bound_co_a.stderr | 2 +- ...ubtype.bound_co_a_co_b_ret_contra_a.stderr | 2 +- ...hr-subtype.bound_co_a_vs_bound_co_b.stderr | 2 +- ...pe.bound_contra_a_contra_b_ret_co_a.stderr | 23 ++-- ...ubtype.bound_inv_a_b_vs_bound_inv_a.stderr | 2 +- ...-subtype.bound_inv_a_vs_bound_inv_b.stderr | 2 +- .../hr-subtype.free_x_vs_free_x.stderr | 2 +- src/test/ui/hr-subtype/hr-subtype.rs | 4 +- src/test/ui/hrtb/hrtb-exists-forall-fn.stderr | 4 +- src/test/ui/hrtb/issue-30786.migrate.stderr | 50 ++++++--- src/test/ui/hrtb/issue-30786.nll.stderr | 99 ++++++++--------- src/test/ui/hrtb/issue-30786.rs | 102 +++++++++++------- src/test/ui/issues/issue-40000.stderr | 6 +- src/test/ui/issues/issue-43623.rs | 7 +- src/test/ui/issues/issue-43623.stderr | 29 ++--- src/test/ui/issues/issue-60283.rs | 8 +- src/test/ui/issues/issue-60283.stderr | 29 ++--- src/test/ui/lub-glb/old-lub-glb-hr.rs | 35 +++++- src/test/ui/lub-glb/old-lub-glb-hr.stderr | 10 +- src/test/ui/lub-glb/old-lub-glb-object.stderr | 25 +++-- .../closure-arg-type-mismatch.rs | 1 - .../closure-arg-type-mismatch.stderr | 14 +-- .../ui/mismatched_types/closure-mismatch.rs | 1 - .../mismatched_types/closure-mismatch.stderr | 18 +--- ...ons-fn-subtyping-return-static-fail.stderr | 4 +- ...lifetime-bounds-on-fns-where-clause.stderr | 6 +- ...lifetime-bounds-on-fns-where-clause.stderr | 6 +- .../regions-lifetime-bounds-on-fns.stderr | 6 +- src/test/ui/rfc1623.rs | 7 +- src/test/ui/rfc1623.stderr | 25 ++--- .../issue-57611-trait-alias.rs | 2 +- .../issue-57611-trait-alias.stderr | 16 +-- .../unboxed-closures-unsafe-extern-fn.rs | 22 ++-- .../unboxed-closures-unsafe-extern-fn.stderr | 44 ++------ .../unboxed-closures-wrong-abi.rs | 22 ++-- .../unboxed-closures-wrong-abi.stderr | 44 ++------ ...boxed-closures-wrong-arg-type-extern-fn.rs | 22 ++-- ...d-closures-wrong-arg-type-extern-fn.stderr | 44 ++------ 60 files changed, 511 insertions(+), 576 deletions(-) diff --git a/src/librustc_infer/infer/higher_ranked/mod.rs b/src/librustc_infer/infer/higher_ranked/mod.rs index b94221785ae75..b6251e34008a3 100644 --- a/src/librustc_infer/infer/higher_ranked/mod.rs +++ b/src/librustc_infer/infer/higher_ranked/mod.rs @@ -30,7 +30,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { let span = self.trace.cause.span; - self.infcx.commit_if_ok(|snapshot| { + self.infcx.commit_if_ok(|_| { // First, we instantiate each bound region in the supertype with a // fresh placeholder region. let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b); @@ -48,8 +48,6 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { // Compare types now that bound regions have been replaced. let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; - self.infcx.leak_check(!a_is_expected, snapshot)?; - debug!("higher_ranked_sub: OK result={:?}", result); Ok(ty::Binder::bind(result)) @@ -75,7 +73,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { where T: TypeFoldable<'tcx>, { - let next_universe = self.create_next_universe(); + // Figure out what the next universe will be, but don't actually create + // it until after we've done the substitution (in particular there may + // be no bound variables). This is a performance optimization, since the + // leak check for example can be skipped if no new universes are created + // (i.e., if there are no placeholders). + let next_universe = self.universe().next_universe(); let fld_r = |br| { self.tcx.mk_region(ty::RePlaceholder(ty::PlaceholderRegion { @@ -103,6 +106,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let (result, map) = self.tcx.replace_bound_vars(binder, fld_r, fld_t, fld_c); + // If there were higher-ranked regions to replace, then actually create + // the next universe (this avoids needlessly creating universes). + if !map.is_empty() { + let n_u = self.create_next_universe(); + assert_eq!(n_u, next_universe); + } + debug!( "replace_bound_vars_with_placeholders(\ next_universe={:?}, \ diff --git a/src/librustc_infer/infer/region_constraints/leak_check.rs b/src/librustc_infer/infer/region_constraints/leak_check.rs index f3b78909b42d8..32e708bf52b32 100644 --- a/src/librustc_infer/infer/region_constraints/leak_check.rs +++ b/src/librustc_infer/infer/region_constraints/leak_check.rs @@ -286,6 +286,7 @@ impl<'me, 'tcx> LeakCheck<'me, 'tcx> { placeholder: ty::PlaceholderRegion, other_region: ty::Region<'tcx>, ) -> TypeError<'tcx> { + debug!("error: placeholder={:?}, other_region={:?}", placeholder, other_region); if self.overly_polymorphic { return TypeError::RegionsOverlyPolymorphic(placeholder.name, other_region); } else { diff --git a/src/librustc_trait_selection/traits/coherence.rs b/src/librustc_trait_selection/traits/coherence.rs index 706cbf058b713..3ec7fe2bf25c6 100644 --- a/src/librustc_trait_selection/traits/coherence.rs +++ b/src/librustc_trait_selection/traits/coherence.rs @@ -120,12 +120,13 @@ fn overlap<'cx, 'tcx>( debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id); selcx.infcx().probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| { - overlap_within_probe(selcx, a_def_id, b_def_id, snapshot) + overlap_within_probe(selcx, skip_leak_check, a_def_id, b_def_id, snapshot) }) } fn overlap_within_probe( selcx: &mut SelectionContext<'cx, 'tcx>, + skip_leak_check: SkipLeakCheck, a_def_id: DefId, b_def_id: DefId, snapshot: &CombinedSnapshot<'_, 'tcx>, @@ -180,6 +181,13 @@ fn overlap_within_probe( return None; } + if !skip_leak_check.is_yes() { + if let Err(_) = infcx.leak_check(true, snapshot) { + debug!("overlap: leak check failed"); + return None; + } + } + let impl_header = selcx.infcx().resolve_vars_if_possible(&a_impl_header); let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes(); debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes); diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 4bc58fbaadcda..ae255c22f9dca 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -298,11 +298,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { fn fold>(&mut self, value: &T) -> T { let value = self.selcx.infcx().resolve_vars_if_possible(value); - if !value.has_projections() { - value - } else { - value.fold_with(self) - } + if !value.has_projections() { value } else { value.fold_with(self) } } } diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs index e90acbbce67ba..e5960e731033f 100644 --- a/src/librustc_trait_selection/traits/select/mod.rs +++ b/src/librustc_trait_selection/traits/select/mod.rs @@ -347,6 +347,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result { self.infcx.probe(|snapshot| -> Result { let result = op(self)?; + + match self.infcx.leak_check(true, snapshot) { + Ok(()) => {} + Err(_) => return Ok(EvaluatedToErr), + } + match self.infcx.region_constraints_added_in_snapshot(snapshot) { None => Ok(result), Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)), @@ -2402,11 +2408,7 @@ impl<'o, 'tcx> TraitObligationStackList<'o, 'tcx> { } fn depth(&self) -> usize { - if let Some(head) = self.head { - head.depth - } else { - 0 - } + if let Some(head) = self.head { head.depth } else { 0 } } } diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 50f1d07142f8c..315d180844d7a 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -74,7 +74,7 @@ LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> | ------------- required by this bound in `tuple_two` ... LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'y, found concrete lifetime + | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied --> $DIR/associated-types-eq-hr.rs:107:18 diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr index 5009e0868a7d4..9462121bdf203 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr @@ -1,23 +1,23 @@ error[E0623]: lifetime mismatch - --> $DIR/project-fn-ret-invariant.rs:53:21 + --> $DIR/project-fn-ret-invariant.rs:54:22 | -LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -------- -------------------- - | | - | this parameter and the return type are declared with different lifetimes... -LL | let a = bar(foo, y); - | ^ ...but data from `x` is returned here +LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -------- -------------------- + | | + | this parameter and the return type are declared with different lifetimes... +LL | let a = bar(foo, y); + | ^ ...but data from `x` is returned here error[E0623]: lifetime mismatch - --> $DIR/project-fn-ret-invariant.rs:54:21 + --> $DIR/project-fn-ret-invariant.rs:56:9 | -LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -------- -------------------- - | | - | this parameter and the return type are declared with different lifetimes... -LL | let a = bar(foo, y); -LL | let b = bar(foo, x); - | ^ ...but data from `y` is returned here +LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -------- -------------------- + | | + | this parameter and the return type are declared with different lifetimes... +... +LL | (a, b) + | ^ ...but data from `x` is returned here error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr index 8f445acf2b98c..2156ecb17393f 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr @@ -1,8 +1,8 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/project-fn-ret-invariant.rs:59:1 + --> $DIR/project-fn-ret-invariant.rs:60:1 | -LL | fn main() { } - | ^^^^^^^^^^^^^ +LL | fn main() {} + | ^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr index 65d16440ac9b0..64b5722390858 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr @@ -1,13 +1,13 @@ error[E0623]: lifetime mismatch - --> $DIR/project-fn-ret-invariant.rs:39:19 + --> $DIR/project-fn-ret-invariant.rs:40:20 | -LL | fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -------- -------------------- - | | - | this parameter and the return type are declared with different lifetimes... +LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -------- -------------------- + | | + | this parameter and the return type are declared with different lifetimes... ... -LL | let b = bar(f, y); - | ^ ...but data from `x` is returned here +LL | let b = bar(f, y); + | ^ ...but data from `x` is returned here error: aborting due to previous error diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs index 23d873212ed1e..0034d796826de 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs @@ -1,60 +1,61 @@ #![feature(unboxed_closures)] #![feature(rustc_attrs)] - // Test for projection cache. We should be able to project distinct // lifetimes from `foo` as we reinstantiate it multiple times, but not // if we do it just once. In this variant, the region `'a` is used in // an invariant position, which affects the results. // revisions: ok oneuse transmute krisskross - #![allow(dead_code, unused_variables)] use std::marker::PhantomData; struct Type<'a> { // Invariant - data: PhantomData &'a u32> + data: PhantomData &'a u32>, } -fn foo<'a>() -> Type<'a> { loop { } } +fn foo<'a>() -> Type<'a> { + loop {} +} fn bar(t: T, x: T::Output) -> T::Output - where T: FnOnce<()> +where + T: FnOnce<()>, { t() } #[cfg(ok)] // two instantiations: OK -fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { +fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { let a = bar(foo, x); let b = bar(foo, y); (a, b) } #[cfg(oneuse)] // one instantiation: BAD -fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - let f = foo; // <-- No consistent type can be inferred for `f` here. - let a = bar(f, x); - let b = bar(f, y); //[oneuse]~ ERROR lifetime mismatch [E0623] - (a, b) +fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + let f = foo; // <-- No consistent type can be inferred for `f` here. + let a = bar(f, x); + let b = bar(f, y); //[oneuse]~ ERROR lifetime mismatch [E0623] + (a, b) } #[cfg(transmute)] // one instantiations: BAD -fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { - // Cannot instantiate `foo` with any lifetime other than `'a`, - // since it is provided as input. +fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { + // Cannot instantiate `foo` with any lifetime other than `'a`, + // since it is provided as input. - bar(foo, x) //[transmute]~ ERROR E0495 + bar(foo, x) //[transmute]~ ERROR E0495 } #[cfg(krisskross)] // two instantiations, mixing and matching: BAD -fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - let a = bar(foo, y); //[krisskross]~ ERROR E0623 - let b = bar(foo, x); //[krisskross]~ ERROR E0623 - (a, b) +fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + let a = bar(foo, y); //[krisskross]~ ERROR E0623 + let b = bar(foo, x); + (a, b) //[krisskross]~ ERROR E0623 } #[rustc_error] -fn main() { } +fn main() {} //[ok]~^ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index 0a05fc6bb8286..ef57f9e0bc480 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -1,27 +1,27 @@ -error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/project-fn-ret-invariant.rs:48:4 +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/project-fn-ret-invariant.rs:49:9 | -LL | bar(foo, x) - | ^^^^^^^^^^^ +LL | bar(foo, x) + | ^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 44:8... - --> $DIR/project-fn-ret-invariant.rs:44:8 +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 45:8... + --> $DIR/project-fn-ret-invariant.rs:45:8 | -LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { +LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { | ^^ note: ...so that the expression is assignable - --> $DIR/project-fn-ret-invariant.rs:48:13 + --> $DIR/project-fn-ret-invariant.rs:49:14 | -LL | bar(foo, x) - | ^ +LL | bar(foo, x) + | ^ = note: expected `Type<'_>` found `Type<'a>` = note: but, the lifetime must be valid for the static lifetime... note: ...so that the expression is assignable - --> $DIR/project-fn-ret-invariant.rs:48:4 + --> $DIR/project-fn-ret-invariant.rs:49:5 | -LL | bar(foo, x) - | ^^^^^^^^^^^ +LL | bar(foo, x) + | ^^^^^^^^^^^ = note: expected `Type<'static>` found `Type<'_>` diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs index a4e43da91baf8..c81c40c18b45b 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs @@ -1,10 +1,12 @@ fn with_closure_expecting_fn_with_free_region(_: F) - where F: for<'a> FnOnce(fn(&'a u32), &i32) +where + F: for<'a> FnOnce(fn(&'a u32), &i32), { } fn with_closure_expecting_fn_with_bound_region(_: F) - where F: FnOnce(fn(&u32), &i32) +where + F: FnOnce(fn(&u32), &i32), { } @@ -28,14 +30,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() { @@ -44,7 +46,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 }); } @@ -52,8 +54,7 @@ fn expect_bound_supply_bound<'x>(x: &'x u32) { // No error in this case. The supplied type supplies the bound // regions, and hence we are able to figure out the type of `y` // from the expected type - with_closure_expecting_fn_with_bound_region(|x: for<'z> fn(&'z u32), y| { - }); + with_closure_expecting_fn_with_bound_region(|x: for<'z> fn(&'z u32), y| {}); } -fn main() { } +fn main() {} diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index fae41c4114abc..0de15dfa7357d 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -1,81 +1,68 @@ error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:14:52 + --> $DIR/expect-fn-supply-fn.rs:16:52 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^ lifetime mismatch | = note: expected fn pointer `fn(&u32)` found fn pointer `fn(&'x u32)` -note: the anonymous lifetime #2 defined on the body at 14:48... - --> $DIR/expect-fn-supply-fn.rs:14:48 +note: the anonymous lifetime #2 defined on the body at 16:48... + --> $DIR/expect-fn-supply-fn.rs:16:48 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^ -note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 11:36 - --> $DIR/expect-fn-supply-fn.rs:11:36 +note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 13:36 + --> $DIR/expect-fn-supply-fn.rs:13:36 | LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { | ^^ error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:14:52 + --> $DIR/expect-fn-supply-fn.rs:16:52 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^ lifetime mismatch | = note: expected fn pointer `fn(&u32)` found fn pointer `fn(&'x u32)` -note: the lifetime `'x` as defined on the function body at 11:36... - --> $DIR/expect-fn-supply-fn.rs:11:36 +note: the lifetime `'x` as defined on the function body at 13:36... + --> $DIR/expect-fn-supply-fn.rs:13:36 | LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { | ^^ -note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 14:48 - --> $DIR/expect-fn-supply-fn.rs:14:48 +note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 16:48 + --> $DIR/expect-fn-supply-fn.rs:16:48 | 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:32:52 | -LL | fn with_closure_expecting_fn_with_free_region(_: 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:39:53 | -LL | fn with_closure_expecting_fn_with_bound_region(_: 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:48:53 | -LL | fn with_closure_expecting_fn_with_bound_region(_: 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`. diff --git a/src/test/ui/closures/issue-41366.rs b/src/test/ui/closures/issue-41366.rs index 5cae0e76d1acb..af1e37ba867de 100644 --- a/src/test/ui/closures/issue-41366.rs +++ b/src/test/ui/closures/issue-41366.rs @@ -7,7 +7,6 @@ impl<'g> T<'g> for u32 { } fn main() { - (&|_|()) as &dyn for<'x> Fn(>::V); + (&|_| ()) as &dyn for<'x> Fn(>::V); //~^ ERROR: type mismatch in closure arguments - //~| ERROR: type mismatch resolving } diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr index 2f2871e9f0e90..9c4b7d529ef4d 100644 --- a/src/test/ui/closures/issue-41366.stderr +++ b/src/test/ui/closures/issue-41366.stderr @@ -1,23 +1,14 @@ error[E0631]: type mismatch in closure arguments --> $DIR/issue-41366.rs:10:5 | -LL | (&|_|()) as &dyn for<'x> Fn(>::V); - | ^^-----^ +LL | (&|_| ()) as &dyn for<'x> Fn(>::V); + | ^^------^ | | | - | | found signature of `fn(_) -> _` - | expected signature of `for<'x> fn(>::V) -> _` + | | found signature of `fn(u16) -> _` + | expected signature of `fn(>::V) -> _` | = note: required for the cast to the object type `dyn for<'x> std::ops::Fn(>::V)` -error[E0271]: type mismatch resolving `for<'x> <[closure@$DIR/issue-41366.rs:10:7: 10:12] as std::ops::FnOnce<(>::V,)>>::Output == ()` - --> $DIR/issue-41366.rs:10:5 - | -LL | (&|_|()) as &dyn for<'x> Fn(>::V); - | ^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime - | - = note: required for the cast to the object type `dyn for<'x> std::ops::Fn(>::V)` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/generator/resume-arg-late-bound.rs b/src/test/ui/generator/resume-arg-late-bound.rs index 87b1f1a065bc8..a8f657eaabe47 100644 --- a/src/test/ui/generator/resume-arg-late-bound.rs +++ b/src/test/ui/generator/resume-arg-late-bound.rs @@ -13,5 +13,6 @@ fn main() { *arg = true; }; test(gen); - //~^ ERROR type mismatch in function arguments + //~^ ERROR mismatched types + //~| ERROR mismatched types } diff --git a/src/test/ui/generator/resume-arg-late-bound.stderr b/src/test/ui/generator/resume-arg-late-bound.stderr index ffa440daed8c4..c379d9eae8ecd 100644 --- a/src/test/ui/generator/resume-arg-late-bound.stderr +++ b/src/test/ui/generator/resume-arg-late-bound.stderr @@ -1,15 +1,21 @@ -error[E0631]: type mismatch in function arguments - --> $DIR/resume-arg-late-bound.rs:15:10 +error[E0308]: mismatched types + --> $DIR/resume-arg-late-bound.rs:15:5 | -LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {} - | ------------------------------- required by this bound in `test` -... LL | test(gen); - | ^^^ - | | - | expected signature of `for<'a> fn(&'a mut bool) -> _` - | found signature of `fn(&mut bool) -> _` + | ^^^^ one type is more general than the other + | + = note: expected type `for<'a> std::ops::Generator<&'a mut bool>` + found type `std::ops::Generator<&mut bool>` + +error[E0308]: mismatched types + --> $DIR/resume-arg-late-bound.rs:15:5 + | +LL | test(gen); + | ^^^^ one type is more general than the other + | + = note: expected type `for<'a> std::ops::Generator<&'a mut bool>` + found type `std::ops::Generator<&mut bool>` -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0631`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr index 1da224a3e85e0..92a85825030c2 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:45: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_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr index 880a8c7be8305..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr +++ b/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:45:26 +error: fatal error triggered by #[rustc_error] + --> $DIR/hr-subtype.rs:102: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 fn(&'a u32, &'b u32)>` - found enum `std::option::Option 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`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr index 0cc30e479c7b9..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr @@ -1,5 +1,5 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:104:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr index 0cc30e479c7b9..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr @@ -1,5 +1,5 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:104:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr index d2abcc4a66091..98f5bff732762 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:45: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)) } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr index 0cc30e479c7b9..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr @@ -1,5 +1,5 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:104:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr index 0cc30e479c7b9..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr @@ -1,5 +1,5 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:104:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr index 0cc30e479c7b9..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr @@ -1,5 +1,5 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:104:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr index e1a16f5149cc6..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr @@ -1,17 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:45:26 +error: fatal error triggered by #[rustc_error] + --> $DIR/hr-subtype.rs:102: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 fn(Contra<'a>, Contra<'b>) -> Co<'a>>` - found enum `std::option::Option 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`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr index 5fec1e9a92eae..100ba6ac27e25 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:45: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_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr index 0cc30e479c7b9..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr @@ -1,5 +1,5 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:104:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr index 0cc30e479c7b9..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr @@ -1,5 +1,5 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:104:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | diff --git a/src/test/ui/hr-subtype/hr-subtype.rs b/src/test/ui/hr-subtype/hr-subtype.rs index 9e9c2ce9c61d7..ad9500eedca93 100644 --- a/src/test/ui/hr-subtype/hr-subtype.rs +++ b/src/test/ui/hr-subtype/hr-subtype.rs @@ -48,8 +48,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_contra_a_contra_b_ret_co_a]~^^^^^^^ ERROR } }; } @@ -109,4 +107,6 @@ fn main() { //[free_x_vs_free_x]~^^^^^ ERROR fatal error triggered by #[rustc_error] //[bound_co_a_b_vs_bound_co_a]~^^^^^^ ERROR //[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR + //[bound_a_b_vs_bound_a]~^^^^^^^^ ERROR + //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr index 328e98657effb..9914783d9767d 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr @@ -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)` diff --git a/src/test/ui/hrtb/issue-30786.migrate.stderr b/src/test/ui/hrtb/issue-30786.migrate.stderr index c0e3fd3cf4679..90a7cadca41b7 100644 --- a/src/test/ui/hrtb/issue-30786.migrate.stderr +++ b/src/test/ui/hrtb/issue-30786.migrate.stderr @@ -1,17 +1,43 @@ -error: implementation of `Stream` is not general enough - --> $DIR/issue-30786.rs:108:22 +error[E0599]: no method named `filterx` found for struct `Map` in the current scope + --> $DIR/issue-30786.rs:128:22 | -LL | / pub trait Stream { -LL | | type Item; -LL | | fn next(self) -> Option; -LL | | } - | |_- trait `Stream` defined here +LL | pub struct Map { + | -------------------- + | | + | method `filterx` not found for this + | doesn't satisfy `_: StreamExt` ... -LL | let map = source.map(|x: &_| x); - | ^^^ implementation of `Stream` is not general enough +LL | let filter = map.filterx(|x: &_| true); + | ^^^^^^^ method not found in `Map` | - = note: `Stream` would have to be implemented for the type `&'0 mut Map`, for any lifetime `'0`... - = note: ...but `Stream` is actually implemented for the type `&'1 mut Map`, for some specific lifetime `'1` + = note: the method `filterx` exists but the following trait bounds were not satisfied: + `&'a mut Map: Stream` + which is required by `Map: StreamExt` + `&'a mut &Map: Stream` + which is required by `&Map: StreamExt` + `&'a mut &mut Map: Stream` + which is required by `&mut Map: StreamExt` -error: aborting due to previous error +error[E0599]: no method named `countx` found for struct `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` in the current scope + --> $DIR/issue-30786.rs:141:24 + | +LL | pub struct Filter { + | ----------------------- + | | + | method `countx` not found for this + | doesn't satisfy `_: StreamExt` +... +LL | let count = filter.countx(); + | ^^^^^^ method not found in `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` + | + = note: the method `countx` exists but the following trait bounds were not satisfied: + `&'a mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + `&'a mut &Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `&Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + `&'a mut &mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `&mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr index c736c5479f848..90a7cadca41b7 100644 --- a/src/test/ui/hrtb/issue-30786.nll.stderr +++ b/src/test/ui/hrtb/issue-30786.nll.stderr @@ -1,56 +1,43 @@ -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:108:15 - | -LL | let map = source.map(|x: &_| x); - | ^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:114:18 - | -LL | let filter = map.filter(|x: &_| true); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:114:18 - | -LL | let filter = map.filter(|x: &_| true); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:114:18 - | -LL | let filter = map.filter(|x: &_| true); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:114:18 - | -LL | let filter = map.filter(|x: &_| true); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:119:17 - | -LL | let count = filter.count(); // Assert that we still have a valid stream. - | ^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:119:17 - | -LL | let count = filter.count(); // Assert that we still have a valid stream. - | ^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:119:17 - | -LL | let count = filter.count(); // Assert that we still have a valid stream. - | ^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:119:17 - | -LL | let count = filter.count(); // Assert that we still have a valid stream. - | ^^^^^^^^^^^^^^ - -error: aborting due to 9 previous errors - +error[E0599]: no method named `filterx` found for struct `Map` in the current scope + --> $DIR/issue-30786.rs:128:22 + | +LL | pub struct Map { + | -------------------- + | | + | method `filterx` not found for this + | doesn't satisfy `_: StreamExt` +... +LL | let filter = map.filterx(|x: &_| true); + | ^^^^^^^ method not found in `Map` + | + = note: the method `filterx` exists but the following trait bounds were not satisfied: + `&'a mut Map: Stream` + which is required by `Map: StreamExt` + `&'a mut &Map: Stream` + which is required by `&Map: StreamExt` + `&'a mut &mut Map: Stream` + which is required by `&mut Map: StreamExt` + +error[E0599]: no method named `countx` found for struct `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` in the current scope + --> $DIR/issue-30786.rs:141:24 + | +LL | pub struct Filter { + | ----------------------- + | | + | method `countx` not found for this + | doesn't satisfy `_: StreamExt` +... +LL | let count = filter.countx(); + | ^^^^^^ method not found in `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` + | + = note: the method `countx` exists but the following trait bounds were not satisfied: + `&'a mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + `&'a mut &Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `&Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + `&'a mut &mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `&mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/hrtb/issue-30786.rs b/src/test/ui/hrtb/issue-30786.rs index c656f84306536..8ce5c090b543e 100644 --- a/src/test/ui/hrtb/issue-30786.rs +++ b/src/test/ui/hrtb/issue-30786.rs @@ -16,7 +16,7 @@ //[nll]compile-flags: -Z borrowck=mir -pub trait Stream { //[migrate]~ NOTE trait `Stream` defined here +pub trait Stream { type Item; fn next(self) -> Option; } @@ -37,8 +37,9 @@ pub struct Map { } impl<'a, A, F, T> Stream for &'a mut Map -where &'a mut A: Stream, - F: FnMut(<&'a mut A as Stream>::Item) -> T, +where + &'a mut A: Stream, + F: FnMut(<&'a mut A as Stream>::Item) -> T, { type Item = T; fn next(self) -> Option { @@ -55,8 +56,9 @@ pub struct Filter { } impl<'a, A, F, T> Stream for &'a mut Filter -where for<'b> &'b mut A: Stream, // <---- BAD - F: FnMut(&T) -> bool, +where + for<'b> &'b mut A: Stream, // <---- BAD + F: FnMut(&T) -> bool, { type Item = <&'a mut A as Stream>::Item; fn next(self) -> Option { @@ -69,29 +71,29 @@ where for<'b> &'b mut A: Stream, // <---- BAD } } -pub trait StreamExt where for<'b> &'b mut Self: Stream { - fn map(self, func: F) -> Map - where Self: Sized, - for<'a> &'a mut Map: Stream, +pub trait StreamExt +where + for<'b> &'b mut Self: Stream, +{ + fn mapx(self, func: F) -> Map + where + Self: Sized, + for<'a> &'a mut Map: Stream, { - Map { - func: func, - stream: self, - } + Map { func: func, stream: self } } - fn filter(self, func: F) -> Filter - where Self: Sized, - for<'a> &'a mut Filter: Stream, + fn filterx(self, func: F) -> Filter + where + Self: Sized, + for<'a> &'a mut Filter: Stream, { - Filter { - func: func, - stream: self, - } + Filter { func: func, stream: self } } - fn count(mut self) -> usize - where Self: Sized, + fn countx(mut self) -> usize + where + Self: Sized, { let mut count = 0; while let Some(_) = self.next() { @@ -101,24 +103,44 @@ pub trait StreamExt where for<'b> &'b mut Self: Stream { } } -impl StreamExt for T where for<'a> &'a mut T: Stream { } +impl StreamExt for T where for<'a> &'a mut T: Stream {} -fn main() { +fn identity(x: &T) -> &T { + x +} + +fn variant1() { let source = Repeat(10); - let map = source.map(|x: &_| x); - //[nll]~^ ERROR higher-ranked subtype error - //[migrate]~^^ ERROR implementation of `Stream` is not general enough - //[migrate]~| NOTE `Stream` would have to be implemented for the type `&'0 mut Map - //[migrate]~| NOTE but `Stream` is actually implemented for the type `&'1 - //[migrate]~| NOTE implementation of `Stream` is not general enough - let filter = map.filter(|x: &_| true); - //[nll]~^ ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error - let count = filter.count(); // Assert that we still have a valid stream. - //[nll]~^ ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error + + // Here, the call to `mapx` returns a type `T` to which `StreamExt` + // is not applicable, because `for<'b> &'b mut T: Stream`) doesn't hold. + // + // More concretely, the type `T` is `Map`, and + // the where clause doesn't hold because the signature of the + // closure gets inferred to a signature like `|&'_ Stream| -> &'_` + // for some specific `'_`, rather than a more generic + // signature. + // + // Why *exactly* we opt for this signature is a bit unclear to me, + // we deduce it somehow from a reuqirement that `Map: Stream` I + // guess. + let map = source.mapx(|x: &_| x); + let filter = map.filterx(|x: &_| true); + //[migrate]~^ ERROR no method named `filterx` + //[nll]~^^ ERROR no method named `filterx` } + +fn variant2() { + let source = Repeat(10); + + // Here, we use a function, which is not subject to the vagaries + // of closure signature inference. In this case, we get the error + // on `countx` as, I think, the test originally expected. + let map = source.mapx(identity); + let filter = map.filterx(|x: &_| true); + let count = filter.countx(); + //[migrate]~^ ERROR no method named `countx` + //[nll]~^^ ERROR no method named `countx` +} + +fn main() {} diff --git a/src/test/ui/issues/issue-40000.stderr b/src/test/ui/issues/issue-40000.stderr index 983fdb13083a1..3eb3482ac910e 100644 --- a/src/test/ui/issues/issue-40000.stderr +++ b/src/test/ui/issues/issue-40000.stderr @@ -2,10 +2,10 @@ error[E0308]: mismatched types --> $DIR/issue-40000.rs:6:9 | LL | foo(bar); - | ^^^ expected concrete lifetime, found bound lifetime parameter + | ^^^ one type is more general than the other | - = note: expected struct `std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r i32) + 'static)>` - found struct `std::boxed::Box` + = note: expected trait object `dyn for<'r> std::ops::Fn(&'r i32)` + found trait object `dyn std::ops::Fn(&i32)` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-43623.rs b/src/test/ui/issues/issue-43623.rs index b259e9e269d06..99cae46fd9cf2 100644 --- a/src/test/ui/issues/issue-43623.rs +++ b/src/test/ui/issues/issue-43623.rs @@ -9,11 +9,12 @@ impl<'a> Trait<'a> for Type { } pub fn break_me(f: F) -where T: for<'b> Trait<'b>, - F: for<'b> FnMut(>::Assoc) { +where + T: for<'b> Trait<'b>, + F: for<'b> FnMut(>::Assoc), +{ break_me::; //~^ ERROR: type mismatch in function arguments - //~| ERROR: type mismatch resolving } fn main() {} diff --git a/src/test/ui/issues/issue-43623.stderr b/src/test/ui/issues/issue-43623.stderr index 99fb2a1f5d030..80aca482b3d29 100644 --- a/src/test/ui/issues/issue-43623.stderr +++ b/src/test/ui/issues/issue-43623.stderr @@ -1,29 +1,18 @@ error[E0631]: type mismatch in function arguments - --> $DIR/issue-43623.rs:14:5 + --> $DIR/issue-43623.rs:16:5 | LL | pub fn break_me(f: F) | -------- required by a bound in this -LL | where T: for<'b> Trait<'b>, -LL | F: for<'b> FnMut(>::Assoc) { - | -------------------------------------- required by this bound in `break_me` +... +LL | F: for<'b> FnMut(>::Assoc), + | ------------------------------ required by this bound in `break_me` +LL | { LL | break_me::; | ^^^^^^^^^^^^^^^^^^^^^^^ | | - | expected signature of `for<'b> fn(>::Assoc) -> _` - | found signature of `fn(_) -> _` + | expected signature of `fn(>::Assoc) -> _` + | found signature of `fn(()) -> _` -error[E0271]: type mismatch resolving `for<'b> >::Assoc,)>>::Output == ()` - --> $DIR/issue-43623.rs:14:5 - | -LL | pub fn break_me(f: F) - | -------- required by a bound in this -LL | where T: for<'b> Trait<'b>, -LL | F: for<'b> FnMut(>::Assoc) { - | ------------------------------ required by this bound in `break_me` -LL | break_me::; - | ^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'b, found concrete lifetime - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/issues/issue-60283.rs b/src/test/ui/issues/issue-60283.rs index e5a9caa32fae7..9c2b2dc9f4dae 100644 --- a/src/test/ui/issues/issue-60283.rs +++ b/src/test/ui/issues/issue-60283.rs @@ -7,11 +7,13 @@ impl<'a> Trait<'a> for () { } pub fn foo(_: T, _: F) -where T: for<'a> Trait<'a>, - F: for<'a> FnMut(>::Item) {} +where + T: for<'a> Trait<'a>, + F: for<'a> FnMut(>::Item), +{ +} fn main() { foo((), drop) //~^ ERROR type mismatch in function arguments - //~| ERROR type mismatch resolving } diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr index e74a34e247a67..ad679bfa22063 100644 --- a/src/test/ui/issues/issue-60283.stderr +++ b/src/test/ui/issues/issue-60283.stderr @@ -1,31 +1,18 @@ error[E0631]: type mismatch in function arguments - --> $DIR/issue-60283.rs:14:13 + --> $DIR/issue-60283.rs:17:13 | LL | pub fn foo(_: T, _: F) | --- required by a bound in this -LL | where T: for<'a> Trait<'a>, -LL | F: for<'a> FnMut(>::Item) {} - | ------------------------------------- required by this bound in `foo` +... +LL | F: for<'a> FnMut(>::Item), + | ----------------------------- required by this bound in `foo` ... LL | foo((), drop) | ^^^^ | | - | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _` - | found signature of `fn(_) -> _` - -error[E0271]: type mismatch resolving `for<'a> } as std::ops::FnOnce<(<() as Trait<'a>>::Item,)>>::Output == ()` - --> $DIR/issue-60283.rs:14:5 - | -LL | pub fn foo(_: T, _: F) - | --- required by a bound in this -LL | where T: for<'a> Trait<'a>, -LL | F: for<'a> FnMut(>::Item) {} - | ----------------------------- required by this bound in `foo` -... -LL | foo((), drop) - | ^^^ expected bound lifetime parameter 'a, found concrete lifetime + | expected signature of `fn(<() as Trait<'a>>::Item) -> _` + | found signature of `fn(()) -> _` -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.rs b/src/test/ui/lub-glb/old-lub-glb-hr.rs index bc7b787cd65ac..5e24a99bcc331 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr.rs +++ b/src/test/ui/lub-glb/old-lub-glb-hr.rs @@ -3,21 +3,21 @@ // error. However, now that we handle subtyping correctly, we no // longer get an error, because we recognize these two types as // equivalent! -// -// Whoops -- now that we reinstituted the leak-check, we get an error -// again. fn foo( x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8), ) { + // The two types above are actually equivalent. With the older + // leak check, though, we didn't consider them as equivalent, and + // hence we gave errors. But now we've fixed that. let z = match 22 { 0 => x, - _ => y, //~ ERROR `match` arms have incompatible types + _ => y, }; } -fn bar( +fn foo_cast( x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8), ) { @@ -28,5 +28,30 @@ fn bar( }; } +fn bar( + x: for<'a, 'b> fn(&'a u8, &'b u8)-> &'a u8, + y: for<'a> fn(&'a u8, &'a u8) -> &'a u8, +) { + // The two types above are not equivalent. With the older LUB/GLB + // algorithm, this may have worked (I don't remember), but now it + // doesn't because we require equality. + let z = match 22 { + 0 => x, + _ => y, //~ ERROR `match` arms have incompatible types + }; +} + +fn bar_cast( + x: for<'a, 'b> fn(&'a u8, &'b u8)-> &'a u8, + y: for<'a> fn(&'a u8, &'a u8) -> &'a u8, +) { + // But we can *upcast* explicitly the type of `x` and figure + // things out: + let z = match 22 { + 0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8, + _ => y, + }; +} + fn main() { } diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.stderr b/src/test/ui/lub-glb/old-lub-glb-hr.stderr index 6d5d51174699f..f9ad4e5814eeb 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-hr.stderr @@ -1,17 +1,17 @@ error[E0308]: `match` arms have incompatible types - --> $DIR/old-lub-glb-hr.rs:16:14 + --> $DIR/old-lub-glb-hr.rs:40:14 | LL | let z = match 22 { | _____________- LL | | 0 => x, - | | - this is found to be of type `for<'r, 's> fn(&'r u8, &'s u8)` + | | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` LL | | _ => y, - | | ^ expected bound lifetime parameter, found concrete lifetime + | | ^ one type is more general than the other LL | | }; | |_____- `match` arms have incompatible types | - = note: expected type `for<'r, 's> fn(&'r u8, &'s u8)` - found fn pointer `for<'a> fn(&'a u8, &'a u8)` + = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` error: aborting due to previous error diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr index 65c797f6b19d7..81f07df3f50bf 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-object.stderr @@ -1,18 +1,25 @@ -error[E0308]: `match` arms have incompatible types - --> $DIR/old-lub-glb-object.rs:12:14 +error[E0308]: mismatched types + --> $DIR/old-lub-glb-object.rs:10:13 | LL | let z = match 22 { - | _____________- + | _____________^ LL | | 0 => x, - | | - this is found to be of type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>` LL | | _ => y, - | | ^ expected bound lifetime parameter 'a, found concrete lifetime LL | | }; - | |_____- `match` arms have incompatible types + | |_____^ one type is more general than the other | - = note: expected type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>` - found reference `&dyn for<'a> Foo<&'a u8, &'a u8>` + = note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` + found trait object `dyn for<'a> Foo<&'a u8, &'a u8>` -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/old-lub-glb-object.rs:22:14 + | +LL | 0 => x as &dyn for<'a> Foo<&'a u8, &'a u8>, + | ^ one type is more general than the other + | + = note: expected trait object `dyn for<'a> Foo<&'a u8, &'a u8>` + found trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs index 521bd3695dfe5..fd4463b63e10e 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -8,5 +8,4 @@ fn main() { fn baz(_: F) {} fn _test<'a>(f: fn(*mut &'a u32)) { baz(f); //~ ERROR type mismatch - //~| ERROR type mismatch } diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 69a4b458ebf50..503899af33ed7 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -22,18 +22,6 @@ LL | a.iter().map(|_: (u16, u16)| 45); | | | expected signature of `fn(&(u32, u32)) -> _` -error[E0631]: type mismatch in function arguments - --> $DIR/closure-arg-type-mismatch.rs:10:9 - | -LL | fn baz(_: F) {} - | ------------- required by this bound in `baz` -LL | fn _test<'a>(f: fn(*mut &'a u32)) { -LL | baz(f); - | ^ - | | - | expected signature of `for<'r> fn(*mut &'r u32) -> _` - | found signature of `fn(*mut &'a u32) -> _` - error[E0271]: type mismatch resolving `for<'r> >::Output == ()` --> $DIR/closure-arg-type-mismatch.rs:10:5 | @@ -43,7 +31,7 @@ LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); | ^^^ expected bound lifetime parameter, found concrete lifetime -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0271, E0631. For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/mismatched_types/closure-mismatch.rs b/src/test/ui/mismatched_types/closure-mismatch.rs index 40a4641fe7196..cb2cb228c62e1 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-mismatch.rs @@ -6,5 +6,4 @@ fn baz(_: T) {} fn main() { baz(|_| ()); //~ ERROR type mismatch - //~^ ERROR type mismatch } diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index 389b21574465a..7fab9490ac93f 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -9,20 +9,6 @@ LL | baz(|_| ()); | = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` -error[E0631]: type mismatch in closure arguments - --> $DIR/closure-mismatch.rs:8:5 - | -LL | fn baz(_: T) {} - | --- required by this bound in `baz` -... -LL | baz(|_| ()); - | ^^^ ------ found signature of `fn(_) -> _` - | | - | expected signature of `for<'r> fn(&'r ()) -> _` - | - = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr index 6d75ace3c4698..c9ce936c7d43f 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr @@ -2,10 +2,10 @@ error[E0308]: mismatched types --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12 | LL | want_G(baz); - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx + | ^^^ one type is more general than the other | = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S` - found fn item `for<'r> fn(&'r S) -> &'r S {baz}` + found fn pointer `for<'r> fn(&'r S) -> &'r S` error: aborting due to previous error diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index 159d32b50b03c..b83e07663faba 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -20,12 +20,10 @@ error[E0308]: mismatched types --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^ one type is more general than the other | = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` + found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` error: aborting due to 3 previous errors diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index dda6129e19536..c93f2890f1110 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -31,12 +31,10 @@ error[E0308]: mismatched types --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 | LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; - | ----------------------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^ one type is more general than the other | = note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` - found fn item `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}` + found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)` error: aborting due to 4 previous errors diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr index 01f43aeebaf7c..2b2dd0dbbf250 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -20,12 +20,10 @@ error[E0308]: mismatched types --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^ one type is more general than the other | = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` + found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` error: aborting due to 3 previous errors diff --git a/src/test/ui/rfc1623.rs b/src/test/ui/rfc1623.rs index 55f5d0b94dcb0..0564d53b944e6 100644 --- a/src/test/ui/rfc1623.rs +++ b/src/test/ui/rfc1623.rs @@ -8,7 +8,6 @@ fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 { static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 = &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8); - struct SomeStruct<'x, 'y, 'z: 'x> { foo: &'x Foo<'z>, bar: &'x Bar<'z>, @@ -19,12 +18,12 @@ fn id(t: T) -> T { t } -static SOME_STRUCT: &SomeStruct = SomeStruct { //~ ERROR mismatched types +static SOME_STRUCT: &SomeStruct = SomeStruct { + //~^ ERROR mismatched types foo: &Foo { bools: &[false, true] }, bar: &Bar { bools: &[true, true] }, f: &id, - //~^ ERROR type mismatch in function arguments - //~| ERROR type mismatch resolving + //~^ ERROR type mismatch resolving }; // very simple test for a 'static static with default lifetime diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.stderr index 75df99137179b..90dc7cbfa5521 100644 --- a/src/test/ui/rfc1623.stderr +++ b/src/test/ui/rfc1623.stderr @@ -1,46 +1,35 @@ error[E0308]: mismatched types - --> $DIR/rfc1623.rs:22:35 + --> $DIR/rfc1623.rs:21:35 | LL | static SOME_STRUCT: &SomeStruct = SomeStruct { | ___________________________________^ +LL | | LL | | foo: &Foo { bools: &[false, true] }, LL | | bar: &Bar { bools: &[true, true] }, LL | | f: &id, LL | | -LL | | LL | | }; | |_^ expected `&SomeStruct<'static, 'static, 'static>`, found struct `SomeStruct` | help: consider borrowing here | LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { +LL | LL | foo: &Foo { bools: &[false, true] }, LL | bar: &Bar { bools: &[true, true] }, LL | f: &id, -LL | LL | ... -error[E0631]: type mismatch in function arguments - --> $DIR/rfc1623.rs:25:8 - | -LL | fn id(t: T) -> T { - | ------------------- found signature of `fn(_) -> _` -... -LL | f: &id, - | ^^^ expected signature of `for<'a, 'b> fn(&'a Foo<'b>) -> _` - | - = note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` - -error[E0271]: type mismatch resolving `for<'a, 'b> _ {id::<_>} as std::ops::FnOnce<(&'a Foo<'b>,)>>::Output == &'a Foo<'b>` +error[E0271]: type mismatch resolving `for<'a, 'b> ) -> &Foo<'_> {id::<&Foo<'_>>} as std::ops::FnOnce<(&'a Foo<'b>,)>>::Output == &'a Foo<'b>` --> $DIR/rfc1623.rs:25:8 | LL | f: &id, - | ^^^ expected bound lifetime parameter 'b, found concrete lifetime + | ^^^ expected bound lifetime parameter 'a, found concrete lifetime | = note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0271, E0308, E0631. +Some errors have detailed explanations: E0271, E0308. For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index 1c2051e7eaeeb..84111b1aef8d4 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -14,7 +14,7 @@ trait Foo { struct X; impl Foo for X { - type Bar = impl Baz; //~ ERROR type mismatch in closure arguments + type Bar = impl Baz; //~^ ERROR type mismatch resolving fn bar(&self) -> Self::Bar { diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr index cc121ac89fb8d..3cb8abcdcfd17 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -1,14 +1,3 @@ -error[E0631]: type mismatch in closure arguments - --> $DIR/issue-57611-trait-alias.rs:17:16 - | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ expected signature of `for<'r> fn(&'r X) -> _` -... -LL | |x| x - | ----- found signature of `fn(_) -> _` - | - = note: the return type of a function must have a statically known size - error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-57611-trait-alias.rs:21:9: 21:14] as std::ops::FnOnce<(&'r X,)>>::Output == &'r X` --> $DIR/issue-57611-trait-alias.rs:17:16 | @@ -17,7 +6,6 @@ LL | type Bar = impl Baz; | = note: the return type of a function must have a statically known size -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs index a6e26614a6a50..e2082d4f78e70 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs @@ -1,23 +1,29 @@ // Tests that unsafe extern fn pointers do not implement any Fn traits. -use std::ops::{Fn,FnMut,FnOnce}; +use std::ops::{Fn, FnMut, FnOnce}; -unsafe fn square(x: &isize) -> isize { (*x) * (*x) } +unsafe fn square(x: &isize) -> isize { + (*x) * (*x) +} -fn call_itisize>(_: &F, _: isize) -> isize { 0 } -fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } -fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } +fn call_it isize>(_: &F, _: isize) -> isize { + 0 +} +fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + 0 +} +fn call_it_once isize>(_: F, _: isize) -> isize { + 0 +} fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn c() { @@ -25,4 +31,4 @@ fn c() { //~^ ERROR E0277 } -fn main() { } +fn main() {} diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr index b9ee9e460201a..b06f745e7c1f1 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr @@ -1,30 +1,19 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:21 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:20:21 | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----------------- required by this bound in `call_it` +LL | fn call_it isize>(_: &F, _: isize) -> isize { + | ------------------- required by this bound in `call_it` ... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:21 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it` -... -LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` - error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:25 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:25:25 | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | -------------------- required by this bound in `call_it_mut` +LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + | ---------------------- required by this bound in `call_it_mut` ... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` @@ -32,27 +21,16 @@ LL | let y = call_it_mut(&mut square, 22); = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:25 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_mut` -... -LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` - -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:24:26 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:30:26 | -LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_once` +LL | fn call_it_once isize>(_: F, _: isize) -> isize { + | ----------------------- required by this bound in `call_it_once` ... LL | let z = call_it_once(square, 22); | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` + = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs index dd3b1afc39f31..dd76c597d28ad 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs @@ -1,23 +1,29 @@ // Tests that unsafe extern fn pointers do not implement any Fn traits. -use std::ops::{Fn,FnMut,FnOnce}; +use std::ops::{Fn, FnMut, FnOnce}; -extern "C" fn square(x: &isize) -> isize { (*x) * (*x) } +extern "C" fn square(x: &isize) -> isize { + (*x) * (*x) +} -fn call_itisize>(_: &F, _: isize) -> isize { 0 } -fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } -fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } +fn call_it isize>(_: &F, _: isize) -> isize { + 0 +} +fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + 0 +} +fn call_it_once isize>(_: F, _: isize) -> isize { + 0 +} fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn c() { @@ -25,4 +31,4 @@ fn c() { //~^ ERROR E0277 } -fn main() { } +fn main() {} diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr index 654b626cf65cc..8f6945cda806c 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr @@ -1,30 +1,19 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:12:21 + --> $DIR/unboxed-closures-wrong-abi.rs:20:21 | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----------------- required by this bound in `call_it` +LL | fn call_it isize>(_: &F, _: isize) -> isize { + | ------------------- required by this bound in `call_it` ... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:12:21 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it` -... -LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` - error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:18:25 + --> $DIR/unboxed-closures-wrong-abi.rs:25:25 | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | -------------------- required by this bound in `call_it_mut` +LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + | ---------------------- required by this bound in `call_it_mut` ... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` @@ -32,27 +21,16 @@ LL | let y = call_it_mut(&mut square, 22); = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:18:25 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_mut` -... -LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` - -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:24:26 + --> $DIR/unboxed-closures-wrong-abi.rs:30:26 | -LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_once` +LL | fn call_it_once isize>(_: F, _: isize) -> isize { + | ----------------------- required by this bound in `call_it_once` ... LL | let z = call_it_once(square, 22); | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` + = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs index c689d79266187..02e8b7b47ae19 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs @@ -1,24 +1,30 @@ // Tests that unsafe extern fn pointers do not implement any Fn traits. -use std::ops::{Fn,FnMut,FnOnce}; +use std::ops::{Fn, FnMut, FnOnce}; -unsafe fn square(x: isize) -> isize { x * x } +unsafe fn square(x: isize) -> isize { + x * x +} // note: argument type here is `isize`, not `&isize` -fn call_itisize>(_: &F, _: isize) -> isize { 0 } -fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } -fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } +fn call_it isize>(_: &F, _: isize) -> isize { + 0 +} +fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + 0 +} +fn call_it_once isize>(_: F, _: isize) -> isize { + 0 +} fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn c() { @@ -26,4 +32,4 @@ fn c() { //~^ ERROR E0277 } -fn main() { } +fn main() {} diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr index 434c8a579f671..93a645b485ef0 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr @@ -1,30 +1,19 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:21 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:21:21 | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----------------- required by this bound in `call_it` +LL | fn call_it isize>(_: &F, _: isize) -> isize { + | ------------------- required by this bound in `call_it` ... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:21 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it` -... -LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` - error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:25 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:26:25 | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | -------------------- required by this bound in `call_it_mut` +LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + | ---------------------- required by this bound in `call_it_mut` ... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` @@ -32,27 +21,16 @@ LL | let y = call_it_mut(&mut square, 22); = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:25 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_mut` -... -LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` - -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:25:26 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:31:26 | -LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_once` +LL | fn call_it_once isize>(_: F, _: isize) -> isize { + | ----------------------- required by this bound in `call_it_once` ... LL | let z = call_it_once(square, 22); | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` + = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. From 1e00e1b6debce8270dd75e795458ba8becdffe1f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 20 May 2020 14:31:51 +0000 Subject: [PATCH 05/13] upcasting traits requires only that things become more general Revert the code that states that upcasting traits requires full equality and change to require that the source type is a subtype of the target type, as one would expect. As the comment states, this was an old bug that we didn't want to fix yet as it interacted poorly with the old leak-check. This fixes the old-lub-glb-object test, which was previously reporting too many errors (i.e., in the previous commit). --- .../traits/select/confirmation.rs | 16 +--------------- ...s_of_reborrow.SimplifyCfg-initial.after.mir | 4 ++-- src/test/ui/lub-glb/old-lub-glb-object.rs | 18 ++++++------------ src/test/ui/lub-glb/old-lub-glb-object.stderr | 14 +++----------- 4 files changed, 12 insertions(+), 40 deletions(-) diff --git a/src/librustc_trait_selection/traits/select/confirmation.rs b/src/librustc_trait_selection/traits/select/confirmation.rs index 50c04e8fc3452..4837acbd1dedc 100644 --- a/src/librustc_trait_selection/traits/select/confirmation.rs +++ b/src/librustc_trait_selection/traits/select/confirmation.rs @@ -612,24 +612,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Require that the traits involved in this upcast are **equal**; // only the **lifetime bound** is changed. - // - // FIXME: This condition is arguably too strong -- it would - // suffice for the source trait to be a *subtype* of the target - // trait. In particular, changing from something like - // `for<'a, 'b> Foo<'a, 'b>` to `for<'a> Foo<'a, 'a>` should be - // permitted. And, indeed, in the in commit - // 904a0bde93f0348f69914ee90b1f8b6e4e0d7cbc, this - // condition was loosened. However, when the leak check was - // added back, using subtype here actually guides the coercion - // code in such a way that it accepts `old-lub-glb-object.rs`. - // This is probably a good thing, but I've modified this to `.eq` - // because I want to continue rejecting that test (as we have - // done for quite some time) before we are firmly comfortable - // with what our behavior should be there. -nikomatsakis let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) - .eq(target, source_trait) // FIXME -- see below + .sup(target, source_trait) .map_err(|_| Unimplemented)?; nested.extend(obligations); diff --git a/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir b/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir index 9742530bd812f..aeb38f3f91068 100644 --- a/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir @@ -12,7 +12,7 @@ | 8: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:16:12: 16:24 | 9: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:16:12: 16:24 | 10: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) } at $DIR/address-of.rs:18:5: 18:18 -| 11: Canonical { max_universe: U3, variables: [CanonicalVarInfo { kind: Region(U3) }], value: Ty(*const dyn std::marker::Send) } at $DIR/address-of.rs:20:5: 20:25 +| 11: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) } at $DIR/address-of.rs:20:5: 20:25 | 12: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) } at $DIR/address-of.rs:23:12: 23:20 | 13: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) } at $DIR/address-of.rs:23:12: 23:20 | 14: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) } at $DIR/address-of.rs:24:12: 24:28 @@ -22,7 +22,7 @@ | 18: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:26:12: 26:24 | 19: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:26:12: 26:24 | 20: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) } at $DIR/address-of.rs:28:5: 28:16 -| 21: Canonical { max_universe: U6, variables: [CanonicalVarInfo { kind: Region(U6) }], value: Ty(*mut dyn std::marker::Send) } at $DIR/address-of.rs:30:5: 30:23 +| 21: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*mut dyn std::marker::Send) } at $DIR/address-of.rs:30:5: 30:23 | 22: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) } at $DIR/address-of.rs:33:12: 33:18 | 23: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) } at $DIR/address-of.rs:33:12: 33:18 | 24: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32; 10]) } at $DIR/address-of.rs:34:12: 34:26 diff --git a/src/test/ui/lub-glb/old-lub-glb-object.rs b/src/test/ui/lub-glb/old-lub-glb-object.rs index 63bbae59991bc..39d351c235574 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.rs +++ b/src/test/ui/lub-glb/old-lub-glb-object.rs @@ -1,22 +1,17 @@ // Test that we give a note when the old LUB/GLB algorithm would have // succeeded but the new code (which is stricter) gives an error. -trait Foo { } +trait Foo {} -fn foo( - x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, - y: &dyn for<'a> Foo<&'a u8, &'a u8>, -) { +fn foo(x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, y: &dyn for<'a> Foo<&'a u8, &'a u8>) { let z = match 22 { + //~^ ERROR mismatched types 0 => x, - _ => y, //~ ERROR `match` arms have incompatible types + _ => y, }; } -fn bar( - x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, - y: &dyn for<'a> Foo<&'a u8, &'a u8>, -) { +fn bar(x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, y: &dyn for<'a> Foo<&'a u8, &'a u8>) { // Accepted with explicit case: let z = match 22 { 0 => x as &dyn for<'a> Foo<&'a u8, &'a u8>, @@ -24,5 +19,4 @@ fn bar( }; } -fn main() { -} +fn main() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr index 81f07df3f50bf..6eabe5eaeeeeb 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-object.stderr @@ -1,8 +1,9 @@ error[E0308]: mismatched types - --> $DIR/old-lub-glb-object.rs:10:13 + --> $DIR/old-lub-glb-object.rs:7:13 | LL | let z = match 22 { | _____________^ +LL | | LL | | 0 => x, LL | | _ => y, LL | | }; @@ -11,15 +12,6 @@ LL | | }; = note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` found trait object `dyn for<'a> Foo<&'a u8, &'a u8>` -error[E0308]: mismatched types - --> $DIR/old-lub-glb-object.rs:22:14 - | -LL | 0 => x as &dyn for<'a> Foo<&'a u8, &'a u8>, - | ^ one type is more general than the other - | - = note: expected trait object `dyn for<'a> Foo<&'a u8, &'a u8>` - found trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. From 70cf33fccaac072a153f6e211aa907c83c465fef Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 22 May 2020 17:48:07 +0000 Subject: [PATCH 06/13] remove snapshot calls from "match" operations during select Motivation: - we want to use leak-check sparingly, first off - these calls were essentially the same as doing the check during subtyping --- .../traits/select/candidate_assembly.rs | 10 +-- .../traits/select/confirmation.rs | 9 +- .../traits/select/mod.rs | 29 ++----- .../associated-types-eq-hr.rs | 35 ++++---- .../associated-types-eq-hr.stderr | 87 +++++++------------ src/test/ui/hrtb/hrtb-conflate-regions.stderr | 21 +++-- .../hrtb-exists-forall-trait-contravariant.rs | 2 +- ...b-exists-forall-trait-contravariant.stderr | 18 ++-- .../hrtb-exists-forall-trait-invariant.rs | 2 +- .../hrtb-exists-forall-trait-invariant.stderr | 18 ++-- src/test/ui/hrtb/hrtb-just-for-static.stderr | 41 +++++---- src/test/ui/hrtb/issue-46989.rs | 8 +- src/test/ui/hrtb/issue-46989.stderr | 15 ++-- src/test/ui/issues/issue-57362-2.stderr | 2 + src/test/ui/where-clauses/where-for-self-2.rs | 8 +- .../ui/where-clauses/where-for-self-2.stderr | 21 +++-- 16 files changed, 138 insertions(+), 188 deletions(-) diff --git a/src/librustc_trait_selection/traits/select/candidate_assembly.rs b/src/librustc_trait_selection/traits/select/candidate_assembly.rs index 9045451056b19..4dab5814f7b7e 100644 --- a/src/librustc_trait_selection/traits/select/candidate_assembly.rs +++ b/src/librustc_trait_selection/traits/select/candidate_assembly.rs @@ -163,9 +163,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => return, } - let result = self.infcx.probe(|snapshot| { - self.match_projection_obligation_against_definition_bounds(obligation, snapshot) - }); + let result = self + .infcx + .probe(|_| self.match_projection_obligation_against_definition_bounds(obligation)); if result { candidates.vec.push(ProjectionCandidate); @@ -345,8 +345,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.predicate.def_id(), obligation.predicate.skip_binder().trait_ref.self_ty(), |impl_def_id| { - self.infcx.probe(|snapshot| { - if let Ok(_substs) = self.match_impl(impl_def_id, obligation, snapshot) { + self.infcx.probe(|_| { + if let Ok(_substs) = self.match_impl(impl_def_id, obligation) { candidates.vec.push(ImplCandidate(impl_def_id)); } }); diff --git a/src/librustc_trait_selection/traits/select/confirmation.rs b/src/librustc_trait_selection/traits/select/confirmation.rs index 4837acbd1dedc..834bf17227d2e 100644 --- a/src/librustc_trait_selection/traits/select/confirmation.rs +++ b/src/librustc_trait_selection/traits/select/confirmation.rs @@ -121,9 +121,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) { - self.infcx.commit_unconditionally(|snapshot| { - let result = - self.match_projection_obligation_against_definition_bounds(obligation, snapshot); + self.infcx.commit_unconditionally(|_| { + let result = self.match_projection_obligation_against_definition_bounds(obligation); assert!(result); }) } @@ -265,8 +264,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // First, create the substitutions by matching the impl again, // this time not in a probe. - self.infcx.commit_unconditionally(|snapshot| { - let substs = self.rematch_impl(impl_def_id, obligation, snapshot); + self.infcx.commit_unconditionally(|_| { + let substs = self.rematch_impl(impl_def_id, obligation); debug!("confirm_impl_candidate: substs={:?}", substs); let cause = obligation.derived_cause(ImplDerivedObligation); ensure_sufficient_stack(|| { diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs index e5960e731033f..cff5efbfd0fd1 100644 --- a/src/librustc_trait_selection/traits/select/mod.rs +++ b/src/librustc_trait_selection/traits/select/mod.rs @@ -21,7 +21,7 @@ use super::{Normalized, ProjectionCacheKey}; use super::{ObligationCause, PredicateObligation, TraitObligation}; use super::{Overflow, SelectionError, Unimplemented}; -use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, TypeFreshener}; +use crate::infer::{InferCtxt, InferOk, TypeFreshener}; use crate::traits::error_reporting::InferCtxtExt; use crate::traits::project::ProjectionCacheKeyExt; use rustc_ast::attr; @@ -1268,7 +1268,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &TraitObligation<'tcx>, - snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> bool { let poly_trait_predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate); let (placeholder_trait_predicate, _) = @@ -1299,12 +1298,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let ty::PredicateKind::Trait(bound, _) = bound.kind() { let bound = bound.to_poly_trait_ref(); if self.infcx.probe(|_| { - self.match_projection( - obligation, - bound, - placeholder_trait_predicate.trait_ref, - snapshot, - ) + self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref) }) { return Some(bound); } @@ -1321,12 +1315,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { None => false, Some(bound) => { // Repeat the successful match, if any, this time outside of a probe. - let result = self.match_projection( - obligation, - bound, - placeholder_trait_predicate.trait_ref, - snapshot, - ); + let result = + self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref); assert!(result); true @@ -1339,14 +1329,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, trait_bound: ty::PolyTraitRef<'tcx>, placeholder_trait_ref: ty::TraitRef<'tcx>, - snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> bool { debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars()); self.infcx .at(&obligation.cause, obligation.param_env) .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) .is_ok() - && self.infcx.leak_check(false, snapshot).is_ok() } fn evaluate_where_clause<'o>( @@ -1811,9 +1799,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, - snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> Normalized<'tcx, SubstsRef<'tcx>> { - match self.match_impl(impl_def_id, obligation, snapshot) { + match self.match_impl(impl_def_id, obligation) { Ok(substs) => substs, Err(()) => { bug!( @@ -1829,7 +1816,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, - snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> Result>, ()> { let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap(); @@ -1872,11 +1858,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?; nested_obligations.extend(obligations); - if let Err(e) = self.infcx.leak_check(false, snapshot) { - debug!("match_impl: failed leak check due to `{}`", e); - return Err(()); - } - if !self.intercrate && self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation { diff --git a/src/test/ui/associated-types/associated-types-eq-hr.rs b/src/test/ui/associated-types/associated-types-eq-hr.rs index e6afa3f71c2f0..70e4be5929fb9 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.rs +++ b/src/test/ui/associated-types/associated-types-eq-hr.rs @@ -7,7 +7,7 @@ pub trait TheTrait { } struct IntStruct { - x: isize + x: isize, } impl<'a> TheTrait<&'a isize> for IntStruct { @@ -19,7 +19,7 @@ impl<'a> TheTrait<&'a isize> for IntStruct { } struct UintStruct { - x: isize + x: isize, } impl<'a> TheTrait<&'a isize> for UintStruct { @@ -30,8 +30,7 @@ impl<'a> TheTrait<&'a isize> for UintStruct { } } -struct Tuple { -} +struct Tuple {} impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { type A = &'a isize; @@ -42,37 +41,43 @@ impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { } fn foo() - where T : for<'x> TheTrait<&'x isize, A = &'x isize> +where + T: for<'x> TheTrait<&'x isize, A = &'x isize>, { // ok for IntStruct, but not UintStruct } fn bar() - where T : for<'x> TheTrait<&'x isize, A = &'x usize> +where + T: for<'x> TheTrait<&'x isize, A = &'x usize>, { // ok for UintStruct, but not IntStruct } fn tuple_one() - where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> +where + T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, { // not ok for tuple, two lifetimes and we pick first } fn tuple_two() - where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> +where + T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, { // not ok for tuple, two lifetimes and we pick second } fn tuple_three() - where T : for<'x> TheTrait<(&'x isize, &'x isize), A = &'x isize> +where + T: for<'x> TheTrait<(&'x isize, &'x isize), A = &'x isize>, { // ok for tuple } fn tuple_four() - where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)> +where + T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, { // not ok for tuple, two lifetimes, and lifetime matching is invariant } @@ -89,14 +94,12 @@ pub fn call_bar() { pub fn call_tuple_one() { tuple_one::(); - //~^ ERROR not satisfied - //~| ERROR type mismatch + //~^ ERROR type mismatch } pub fn call_tuple_two() { tuple_two::(); - //~^ ERROR not satisfied - //~| ERROR type mismatch + //~^ ERROR type mismatch } pub fn call_tuple_three() { @@ -105,7 +108,7 @@ pub fn call_tuple_three() { pub fn call_tuple_four() { tuple_four::(); - //~^ ERROR not satisfied + //~^ ERROR implementation of `TheTrait` is not general enough } -fn main() { } +fn main() {} diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 315d180844d7a..626cb55588fae 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -1,10 +1,11 @@ error[E0271]: type mismatch resolving `for<'x> >::A == &'x isize` - --> $DIR/associated-types-eq-hr.rs:82:5 + --> $DIR/associated-types-eq-hr.rs:87:5 | LL | fn foo() | --- required by a bound in this -LL | where T : for<'x> TheTrait<&'x isize, A = &'x isize> - | ------------- required by this bound in `foo` +LL | where +LL | T: for<'x> TheTrait<&'x isize, A = &'x isize>, + | ------------- required by this bound in `foo` ... LL | foo::(); | ^^^^^^^^^^^^^^^^^ expected `isize`, found `usize` @@ -13,12 +14,13 @@ LL | foo::(); found reference `&usize` error[E0271]: type mismatch resolving `for<'x> >::A == &'x usize` - --> $DIR/associated-types-eq-hr.rs:86:5 + --> $DIR/associated-types-eq-hr.rs:91:5 | LL | fn bar() | --- required by a bound in this -LL | where T : for<'x> TheTrait<&'x isize, A = &'x usize> - | ------------- required by this bound in `bar` +LL | where +LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>, + | ------------- required by this bound in `bar` ... LL | bar::(); | ^^^^^^^^^^^^^^^^ expected `usize`, found `isize` @@ -26,71 +28,46 @@ LL | bar::(); = note: expected reference `&usize` found reference `&isize` -error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:91:17 - | -LL | fn tuple_one() - | --------- required by a bound in this -LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> - | ---------------------------------------------------------- required by this bound in `tuple_one` -... -LL | tuple_one::(); - | ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` - | - = help: the following implementations were found: - > - error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'x isize` - --> $DIR/associated-types-eq-hr.rs:91:5 + --> $DIR/associated-types-eq-hr.rs:96:5 | LL | fn tuple_one() | --------- required by a bound in this -LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> - | ------------- required by this bound in `tuple_one` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, + | ------------- required by this bound in `tuple_one` ... LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'y, found concrete lifetime - -error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:97:17 - | -LL | fn tuple_two() - | --------- required by a bound in this -LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> - | ---------------------------------------------------------- required by this bound in `tuple_two` -... -LL | tuple_two::(); - | ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` - | - = help: the following implementations were found: - > + | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'y isize` - --> $DIR/associated-types-eq-hr.rs:97:5 + --> $DIR/associated-types-eq-hr.rs:101:5 | LL | fn tuple_two() | --------- required by a bound in this -LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> - | ------------- required by this bound in `tuple_two` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, + | ------------- required by this bound in `tuple_two` ... LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime + | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'y, found concrete lifetime -error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:107:18 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:110:5 | -LL | fn tuple_four() - | ---------- required by a bound in this -LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)> - | ------------------------------------------- required by this bound in `tuple_four` +LL | / pub trait TheTrait { +LL | | type A; +LL | | +LL | | fn get(&self, t: T) -> Self::A; +LL | | } + | |_- trait `TheTrait` defined here ... -LL | tuple_four::(); - | ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` +LL | tuple_four::(); + | ^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | - = help: the following implementations were found: - > + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index 7250935ea296b..45573814d13c0 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -1,17 +1,16 @@ -error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied - --> $DIR/hrtb-conflate-regions.rs:27:22 +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-conflate-regions.rs:27:10 | -LL | fn want_foo2() - | --------- required by a bound in this -LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> - | -------------------------------------- required by this bound in `want_foo2` +LL | / trait Foo { +LL | | fn foo(&self, x: X) { } +LL | | } + | |_- trait `Foo` defined here ... -LL | fn b() { want_foo2::(); } - | ^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct` +LL | fn b() { want_foo2::(); } + | ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = help: the following implementations were found: - > + = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `SomeStruct` actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs index 4c1d4d28a09b0..921061916fc95 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs @@ -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 } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr index 7a7285d3d76e0..fe8209d054c8a 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr @@ -1,18 +1,14 @@ -error[E0277]: the trait bound `(): Trait 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() - | --- required by a bound in this -LL | where -LL | T: Trait fn(&'b u32)>, - | -------------------------- required by this bound in `foo` +LL | trait Trait {} + | ----------------- trait `Trait` defined here ... LL | foo::<()>(); - | ^^ the trait `Trait fn(&'b u32)>` is not implemented for `()` + | ^^^^^^^^^ implementation of `Trait` is not general enough | - = help: the following implementations were found: - <() as Trait> + = note: `()` must implement `Trait fn(&'b u32)>` + = note: ...but `()` actually implements `Trait`, for some specific lifetime `'0` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs index 827a68beee8bd..b1b7ec6bcf1a5 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs @@ -25,5 +25,5 @@ fn main() { // yielding `fn(&!b u32)`, in a fresh universe U1 // - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`. - foo::<()>(); //~ ERROR not satisfied + foo::<()>(); //~ ERROR implementation of `Trait` is not general enough } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr index 9174ea4d8419d..720e2276d5343 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -1,18 +1,14 @@ -error[E0277]: the trait bound `(): Trait fn(std::cell::Cell<&'b u32>)>` is not satisfied - --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:11 +error: implementation of `Trait` is not general enough + --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 | -LL | fn foo() - | --- required by a bound in this -LL | where -LL | T: Trait fn(Cell<&'b u32>)>, - | -------------------------------- required by this bound in `foo` +LL | trait Trait {} + | ----------------- trait `Trait` defined here ... LL | foo::<()>(); - | ^^ the trait `Trait fn(std::cell::Cell<&'b u32>)>` is not implemented for `()` + | ^^^^^^^^^ implementation of `Trait` is not general enough | - = help: the following implementations were found: - <() as Trait)>> + = note: `()` must implement `Trait fn(std::cell::Cell<&'b u32>)>` + = note: ...but `()` actually implements `Trait)>`, for some specific lifetime `'0` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 4fa404624775b..5e3014317f5bc 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -1,31 +1,30 @@ -error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied - --> $DIR/hrtb-just-for-static.rs:24:17 +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-just-for-static.rs:24:5 | -LL | fn want_hrtb() - | --------- required by a bound in this -LL | where T : for<'a> Foo<&'a isize> - | ---------------------- required by this bound in `want_hrtb` +LL | / trait Foo { +LL | | fn foo(&self, x: X) { } +LL | | } + | |_- trait `Foo` defined here ... -LL | want_hrtb::() - | ^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt` +LL | want_hrtb::() + | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = help: the following implementations were found: - > + = note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... + = note: ...but `StaticInt` actually implements `Foo<&'1 isize>`, for some specific lifetime `'1` -error[E0277]: the trait bound `for<'a> &'a u32: Foo<&'a isize>` is not satisfied - --> $DIR/hrtb-just-for-static.rs:30:17 +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-just-for-static.rs:30:5 | -LL | fn want_hrtb() - | --------- required by a bound in this -LL | where T : for<'a> Foo<&'a isize> - | ---------------------- required by this bound in `want_hrtb` +LL | / trait Foo { +LL | | fn foo(&self, x: X) { } +LL | | } + | |_- trait `Foo` defined here ... -LL | want_hrtb::<&'a u32>() - | ^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `&'a u32` +LL | want_hrtb::<&'a u32>() + | ^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = help: the following implementations were found: - <&'a u32 as Foo<&'a isize>> + = note: `Foo<&'0 isize>` would have to be implemented for the type `&'a u32`, for any lifetime `'0`... + = note: ...but `Foo<&'1 isize>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/issue-46989.rs b/src/test/ui/hrtb/issue-46989.rs index 2c85905545807..4a09f4be156e2 100644 --- a/src/test/ui/hrtb/issue-46989.rs +++ b/src/test/ui/hrtb/issue-46989.rs @@ -28,15 +28,13 @@ // // holds because 'a can be instantiated to 'empty. -trait Foo { +trait Foo {} -} - -impl Foo for fn(A) { } +impl Foo for fn(A) {} fn assert_foo() {} fn main() { assert_foo::(); - //~^ ERROR the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied + //~^ ERROR implementation of `Foo` is not general enough } diff --git a/src/test/ui/hrtb/issue-46989.stderr b/src/test/ui/hrtb/issue-46989.stderr index 0a7382c4dd818..c85c37ff9239e 100644 --- a/src/test/ui/hrtb/issue-46989.stderr +++ b/src/test/ui/hrtb/issue-46989.stderr @@ -1,15 +1,14 @@ -error[E0277]: the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied - --> $DIR/issue-46989.rs:40:18 +error: implementation of `Foo` is not general enough + --> $DIR/issue-46989.rs:38:5 | -LL | fn assert_foo() {} - | --- required by this bound in `assert_foo` +LL | trait Foo {} + | ------------ trait `Foo` defined here ... LL | assert_foo::(); - | ^^^^^^^^ the trait `Foo` is not implemented for `for<'r> fn(&'r i32)` + | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = help: the following implementations were found: - + = note: `Foo` would have to be implemented for the type `for<'r> fn(&'r i32)` + = note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index 2edc009746455..47cc64ec470a5 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -4,6 +4,8 @@ error[E0599]: no function or associated item named `make_g` found for fn pointer LL | let x = ::make_g(); | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` | + = note: the method `make_g` exists but the following trait bounds were not satisfied: + `for<'r> fn(&'r ()): X` = help: items from traits can only be used if the trait is implemented and in scope note: `X` defines an item `make_g`, perhaps you need to implement it --> $DIR/issue-57362-2.rs:8:1 diff --git a/src/test/ui/where-clauses/where-for-self-2.rs b/src/test/ui/where-clauses/where-for-self-2.rs index 31174fd4cf163..37c6954fd52ee 100644 --- a/src/test/ui/where-clauses/where-for-self-2.rs +++ b/src/test/ui/where-clauses/where-for-self-2.rs @@ -14,9 +14,11 @@ impl Bar for &'static u32 { } fn foo(x: &T) - where for<'a> &'a T: Bar -{} +where + for<'a> &'a T: Bar, +{ +} fn main() { - foo(&X); //~ ERROR trait bound + foo(&X); //~ ERROR implementation of `Bar` is not general enough } diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index 9976243b200dc..30eb78b2da4f7 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -1,17 +1,16 @@ -error[E0277]: the trait bound `for<'a> &'a _: Bar` is not satisfied - --> $DIR/where-for-self-2.rs:21:5 +error: implementation of `Bar` is not general enough + --> $DIR/where-for-self-2.rs:23:5 | -LL | fn foo(x: &T) - | --- required by a bound in this -LL | where for<'a> &'a T: Bar - | --- required by this bound in `foo` +LL | / trait Bar { +LL | | fn bar(&self); +LL | | } + | |_- trait `Bar` defined here ... -LL | foo(&X); - | ^^^ the trait `for<'a> Bar` is not implemented for `&'a _` +LL | foo(&X); + | ^^^ implementation of `Bar` is not general enough | - = help: the following implementations were found: - <&'static u32 as Bar> + = note: `Bar` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... + = note: ...but `Bar` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. From 6873a76f2c34a318a540df65901d07baba1d217b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 22 May 2020 18:16:28 +0000 Subject: [PATCH 07/13] remove leak-check from project --- .../traits/project.rs | 3 +- .../associated-types-eq-hr.rs | 6 +- .../associated-types-eq-hr.stderr | 78 ++++++++++++++----- .../higher-ranked-projection.bad.stderr | 14 ++-- .../higher-ranked-projection.rs | 2 +- .../closure-arg-type-mismatch.rs | 6 +- .../closure-arg-type-mismatch.stderr | 43 ++++++++-- .../ui/mismatched_types/closure-mismatch.rs | 2 +- .../mismatched_types/closure-mismatch.stderr | 12 ++- src/test/ui/rfc1623.rs | 7 +- src/test/ui/rfc1623.stderr | 35 ++------- .../issue-57611-trait-alias.rs | 2 +- .../issue-57611-trait-alias.stderr | 9 ++- 13 files changed, 132 insertions(+), 87 deletions(-) diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index ae255c22f9dca..bc696214cbc66 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -149,13 +149,12 @@ pub fn poly_project_and_unify_type<'cx, 'tcx>( debug!("poly_project_and_unify_type(obligation={:?})", obligation); let infcx = selcx.infcx(); - infcx.commit_if_ok(|snapshot| { + infcx.commit_if_ok(|_snapshot| { let (placeholder_predicate, _) = infcx.replace_bound_vars_with_placeholders(&obligation.predicate); let placeholder_obligation = obligation.with(placeholder_predicate); let result = project_and_unify_type(selcx, &placeholder_obligation)?; - infcx.leak_check(false, snapshot).map_err(|err| MismatchedProjectionTypes { err })?; Ok(result) }) } diff --git a/src/test/ui/associated-types/associated-types-eq-hr.rs b/src/test/ui/associated-types/associated-types-eq-hr.rs index 70e4be5929fb9..fb391913c321e 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.rs +++ b/src/test/ui/associated-types/associated-types-eq-hr.rs @@ -94,12 +94,14 @@ pub fn call_bar() { pub fn call_tuple_one() { tuple_one::(); - //~^ ERROR type mismatch + //~^ ERROR implementation of `TheTrait` is not general enough + //~| ERROR implementation of `TheTrait` is not general enough } pub fn call_tuple_two() { tuple_two::(); - //~^ ERROR type mismatch + //~^ ERROR implementation of `TheTrait` is not general enough + //~| ERROR implementation of `TheTrait` is not general enough } pub fn call_tuple_three() { diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 626cb55588fae..127ab8673556d 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -28,32 +28,72 @@ LL | bar::(); = note: expected reference `&usize` found reference `&isize` -error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'x isize` +error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | fn tuple_one() - | --------- required by a bound in this -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ------------- required by this bound in `tuple_one` +LL | / pub trait TheTrait { +LL | | type A; +LL | | +LL | | fn get(&self, t: T) -> Self::A; +LL | | } + | |_- trait `TheTrait` defined here ... -LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` -error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'y isize` - --> $DIR/associated-types-eq-hr.rs:101:5 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | fn tuple_two() - | --------- required by a bound in this -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, - | ------------- required by this bound in `tuple_two` +LL | / pub trait TheTrait { +LL | | type A; +LL | | +LL | | fn get(&self, t: T) -> Self::A; +LL | | } + | |_- trait `TheTrait` defined here ... -LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'y, found concrete lifetime +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:102:5 + | +LL | / pub trait TheTrait { +LL | | type A; +LL | | +LL | | fn get(&self, t: T) -> Self::A; +LL | | } + | |_- trait `TheTrait` defined here +... +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:102:5 + | +LL | / pub trait TheTrait { +LL | | type A; +LL | | +LL | | fn get(&self, t: T) -> Self::A; +LL | | } + | |_- trait `TheTrait` defined here +... +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: implementation of `TheTrait` is not general enough - --> $DIR/associated-types-eq-hr.rs:110:5 + --> $DIR/associated-types-eq-hr.rs:112:5 | LL | / pub trait TheTrait { LL | | type A; @@ -68,6 +108,6 @@ LL | tuple_four::(); = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index 3b3e4c3ea117a..811c9a8f5e12b 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -1,14 +1,12 @@ -error[E0271]: type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _` +error[E0308]: mismatched types --> $DIR/higher-ranked-projection.rs:25:5 | -LL | fn foo(_t: T) - | --- required by a bound in this -LL | where for<'a> &'a T: Mirror - | ------- required by this bound in `foo` -... LL | foo(()); - | ^^^ expected bound lifetime parameter 'a, found concrete lifetime + | ^^^ one type is more general than the other + | + = note: expected type `&'a ()` + found type `&()` error: aborting due to previous error -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.rs b/src/test/ui/associated-types/higher-ranked-projection.rs index 5315e21b0f5a9..1b5476d4c364f 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.rs +++ b/src/test/ui/associated-types/higher-ranked-projection.rs @@ -23,5 +23,5 @@ fn foo(_t: T) #[rustc_error] fn main() { //[good]~ ERROR fatal error triggered by #[rustc_error] foo(()); - //[bad]~^ ERROR type mismatch + //[bad]~^ ERROR mismatched types } diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs index fd4463b63e10e..e278049c8cc42 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -7,5 +7,9 @@ fn main() { fn baz(_: F) {} fn _test<'a>(f: fn(*mut &'a u32)) { - baz(f); //~ ERROR type mismatch + baz(f); + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types } diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 503899af33ed7..664fa4bcaf328 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -22,16 +22,43 @@ LL | a.iter().map(|_: (u16, u16)| 45); | | | expected signature of `fn(&(u32, u32)) -> _` -error[E0271]: type mismatch resolving `for<'r> >::Output == ()` +error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | fn baz(_: F) {} - | ------------- required by this bound in `baz` -LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); - | ^^^ expected bound lifetime parameter, found concrete lifetime + | ^^^ one type is more general than the other + | + = note: expected type `for<'r> std::ops::Fn<(*mut &'r u32,)>` + found type `std::ops::Fn<(*mut &'a u32,)>` + +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); + | ^^^ one type is more general than the other + | + = note: expected type `std::ops::FnOnce<(*mut &u32,)>` + found type `std::ops::FnOnce<(*mut &'a u32,)>` + +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); + | ^^^ one type is more general than the other + | + = note: expected type `for<'r> std::ops::Fn<(*mut &'r u32,)>` + found type `std::ops::Fn<(*mut &'a u32,)>` + +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); + | ^^^ one type is more general than the other + | + = note: expected type `std::ops::FnOnce<(*mut &u32,)>` + found type `std::ops::FnOnce<(*mut &'a u32,)>` -error: aborting due to 4 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0308, E0631. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/closure-mismatch.rs b/src/test/ui/mismatched_types/closure-mismatch.rs index cb2cb228c62e1..d2b78b4b7dba5 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-mismatch.rs @@ -5,5 +5,5 @@ impl Foo for T {} fn baz(_: T) {} fn main() { - baz(|_| ()); //~ ERROR type mismatch + baz(|_| ()); //~ ERROR mismatched types } diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index 7fab9490ac93f..d6c17d125cf1e 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -1,14 +1,12 @@ -error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.rs:8:9: 8:15] as std::ops::FnOnce<(&'r (),)>>::Output == ()` +error[E0308]: mismatched types --> $DIR/closure-mismatch.rs:8:5 | -LL | fn baz(_: T) {} - | --- required by this bound in `baz` -... LL | baz(|_| ()); - | ^^^ expected bound lifetime parameter, found concrete lifetime + | ^^^ one type is more general than the other | - = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` + = note: expected type `for<'r> std::ops::Fn<(&'r (),)>` + found type `std::ops::Fn<(&(),)>` error: aborting due to previous error -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/rfc1623.rs b/src/test/ui/rfc1623.rs index 0564d53b944e6..aa6b1c0012c93 100644 --- a/src/test/ui/rfc1623.rs +++ b/src/test/ui/rfc1623.rs @@ -11,19 +11,18 @@ static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 = struct SomeStruct<'x, 'y, 'z: 'x> { foo: &'x Foo<'z>, bar: &'x Bar<'z>, - f: &'y dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Bar<'b>, + f: &'y dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>, } fn id(t: T) -> T { t } -static SOME_STRUCT: &SomeStruct = SomeStruct { - //~^ ERROR mismatched types +static SOME_STRUCT: &SomeStruct = &SomeStruct { foo: &Foo { bools: &[false, true] }, bar: &Bar { bools: &[true, true] }, f: &id, - //~^ ERROR type mismatch resolving + //~^ ERROR mismatched types }; // very simple test for a 'static static with default lifetime diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.stderr index 90dc7cbfa5521..2efc58ac3819c 100644 --- a/src/test/ui/rfc1623.stderr +++ b/src/test/ui/rfc1623.stderr @@ -1,35 +1,12 @@ error[E0308]: mismatched types - --> $DIR/rfc1623.rs:21:35 - | -LL | static SOME_STRUCT: &SomeStruct = SomeStruct { - | ___________________________________^ -LL | | -LL | | foo: &Foo { bools: &[false, true] }, -LL | | bar: &Bar { bools: &[true, true] }, -LL | | f: &id, -LL | | -LL | | }; - | |_^ expected `&SomeStruct<'static, 'static, 'static>`, found struct `SomeStruct` - | -help: consider borrowing here - | -LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { -LL | -LL | foo: &Foo { bools: &[false, true] }, -LL | bar: &Bar { bools: &[true, true] }, -LL | f: &id, -LL | - ... - -error[E0271]: type mismatch resolving `for<'a, 'b> ) -> &Foo<'_> {id::<&Foo<'_>>} as std::ops::FnOnce<(&'a Foo<'b>,)>>::Output == &'a Foo<'b>` - --> $DIR/rfc1623.rs:25:8 + --> $DIR/rfc1623.rs:24:8 | LL | f: &id, - | ^^^ expected bound lifetime parameter 'a, found concrete lifetime + | ^^^ one type is more general than the other | - = note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` + = note: expected type `std::ops::FnOnce<(&'a Foo<'b>,)>` + found type `std::ops::FnOnce<(&Foo<'_>,)>` -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0308. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index 84111b1aef8d4..41e019247c942 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -15,7 +15,7 @@ struct X; impl Foo for X { type Bar = impl Baz; - //~^ ERROR type mismatch resolving + //~^ ERROR mismatched types fn bar(&self) -> Self::Bar { |x| x diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr index 3cb8abcdcfd17..cd637056c94ad 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -1,11 +1,12 @@ -error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-57611-trait-alias.rs:21:9: 21:14] as std::ops::FnOnce<(&'r X,)>>::Output == &'r X` +error[E0308]: mismatched types --> $DIR/issue-57611-trait-alias.rs:17:16 | LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: the return type of a function must have a statically known size + = note: expected type `std::ops::FnOnce<(&X,)>` + found type `std::ops::FnOnce<(&X,)>` error: aborting due to previous error -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. From 3a68d56de307cae00dd0a9f6908e52889006a1ff Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 22 May 2020 18:19:54 +0000 Subject: [PATCH 08/13] remove `leak_check` from the outlives predicate evaluations --- src/librustc_infer/infer/mod.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 0e569be34aa66..8f8ce03d638c0 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -991,14 +991,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { return None; } - Some(self.commit_if_ok(|snapshot| { + Some(self.commit_if_ok(|_snapshot| { let (ty::SubtypePredicate { a_is_expected, a, b }, _) = self.replace_bound_vars_with_placeholders(&predicate); let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; - self.leak_check(false, snapshot)?; - Ok(ok.unit()) })) } @@ -1008,14 +1006,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { cause: &traits::ObligationCause<'tcx>, predicate: ty::PolyRegionOutlivesPredicate<'tcx>, ) -> UnitResult<'tcx> { - self.commit_if_ok(|snapshot| { + self.commit_if_ok(|_snapshot| { let (ty::OutlivesPredicate(r_a, r_b), _) = self.replace_bound_vars_with_placeholders(&predicate); let origin = SubregionOrigin::from_obligation_cause(cause, || { RelateRegionParamBound(cause.span) }); self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` - self.leak_check(false, snapshot)?; Ok(()) }) } From be0d10f149579d3ed53507ff8c2f6511b56456f7 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 22 May 2020 11:05:09 +0000 Subject: [PATCH 09/13] add new tests from MCP and the tracking issue --- .../coherence/coherence-fn-implied-bounds.rs | 14 +++++++ .../coherence-fn-implied-bounds.stderr | 20 ++++++++++ src/test/ui/coherence/coherence-fn-inputs.rs | 27 ++++++++++++++ .../ui/coherence/coherence-fn-inputs.stderr | 13 +++++++ .../coherence-free-vs-bound-region.rs | 21 +++++++++++ .../coherence-free-vs-bound-region.stderr | 20 ++++++++++ .../ui/coherence/coherence-wasm-bindgen.rs | 37 +++++++++++++++++++ .../coherence/coherence-wasm-bindgen.stderr | 32 ++++++++++++++++ src/test/ui/hr-subtype/return-static.rs | 13 +++++++ 9 files changed, 197 insertions(+) create mode 100644 src/test/ui/coherence/coherence-fn-implied-bounds.rs create mode 100644 src/test/ui/coherence/coherence-fn-implied-bounds.stderr create mode 100644 src/test/ui/coherence/coherence-fn-inputs.rs create mode 100644 src/test/ui/coherence/coherence-fn-inputs.stderr create mode 100644 src/test/ui/coherence/coherence-free-vs-bound-region.rs create mode 100644 src/test/ui/coherence/coherence-free-vs-bound-region.stderr create mode 100644 src/test/ui/coherence/coherence-wasm-bindgen.rs create mode 100644 src/test/ui/coherence/coherence-wasm-bindgen.stderr create mode 100644 src/test/ui/hr-subtype/return-static.rs diff --git a/src/test/ui/coherence/coherence-fn-implied-bounds.rs b/src/test/ui/coherence/coherence-fn-implied-bounds.rs new file mode 100644 index 0000000000000..ba89a072f3441 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-implied-bounds.rs @@ -0,0 +1,14 @@ +// Example of coherence impls that we accept + +#![deny(coherence_leak_check)] + +trait Trait {} + +impl Trait for for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32 {} + +impl Trait for for<'c> fn(&'c &'c u32, &'c &'c u32) -> &'c u32 { + //~^ ERROR conflicting implementations + //~| WARNING this was previously accepted by the compiler +} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-fn-implied-bounds.stderr b/src/test/ui/coherence/coherence-fn-implied-bounds.stderr new file mode 100644 index 0000000000000..d7853a0b1ebc3 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-implied-bounds.stderr @@ -0,0 +1,20 @@ +error: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32`: + --> $DIR/coherence-fn-implied-bounds.rs:9:1 + | +LL | impl Trait for for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32 {} + | ------------------------------------------------------------------ first implementation here +LL | +LL | impl Trait for for<'c> fn(&'c &'c u32, &'c &'c u32) -> &'c u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32` + | +note: the lint level is defined here + --> $DIR/coherence-fn-implied-bounds.rs:3:9 + | +LL | #![deny(coherence_leak_check)] + | ^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + diff --git a/src/test/ui/coherence/coherence-fn-inputs.rs b/src/test/ui/coherence/coherence-fn-inputs.rs new file mode 100644 index 0000000000000..8c10899304127 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-inputs.rs @@ -0,0 +1,27 @@ +// Test that we consider these two types completely equal: +// +// * `for<'a, 'b> fn(&'a u32, &'b u32)` +// * `for<'c> fn(&'c u32, &'c u32)` +// +// For a long time we considered these to be distinct types. But in fact they +// are equivalent, if you work through the implications of subtyping -- this is +// because: +// +// * `'c` can be the intersection of `'a` and `'b` (and there is always an intersection) +// * `'a` and `'b` can both be equal to `'c` + +#![deny(coherence_leak_check)] + +trait Trait {} +impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {} +impl Trait for for<'c> fn(&'c u32, &'c u32) { + //~^ ERROR conflicting implementations + // + // Note in particular that we do NOT get a future-compatibility warning + // here. This is because the new leak-check proposed in [MCP 295] does not + // "error" when these two types are equated. + // + // [MCP 295]: /~https://github.com/rust-lang/compiler-team/issues/295 +} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-fn-inputs.stderr b/src/test/ui/coherence/coherence-fn-inputs.stderr new file mode 100644 index 0000000000000..a80357526e09d --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-inputs.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)`: + --> $DIR/coherence-fn-inputs.rs:17:1 + | +LL | impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {} + | ----------------------------------------------- first implementation here +LL | impl Trait for for<'c> fn(&'c u32, &'c u32) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u32, &'b u32)` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence/coherence-free-vs-bound-region.rs b/src/test/ui/coherence/coherence-free-vs-bound-region.rs new file mode 100644 index 0000000000000..2f5c49d293d5d --- /dev/null +++ b/src/test/ui/coherence/coherence-free-vs-bound-region.rs @@ -0,0 +1,21 @@ +// Capture a coherence pattern from wasm-bindgen that we discovered as part of +// future-compatibility warning #56105. This pattern currently receives a lint +// warning but we probably want to support it long term. +// +// Key distinction: we are implementing once for `A` (take ownership) and one +// for `&A` (borrow). +// +// c.f. #56105 + +#![deny(coherence_leak_check)] + +trait TheTrait {} + +impl<'a> TheTrait for fn(&'a u8) {} + +impl TheTrait for fn(&u8) { + //~^ ERROR conflicting implementations of trait + //~| WARNING this was previously accepted by the compiler +} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-free-vs-bound-region.stderr b/src/test/ui/coherence/coherence-free-vs-bound-region.stderr new file mode 100644 index 0000000000000..97aa491272143 --- /dev/null +++ b/src/test/ui/coherence/coherence-free-vs-bound-region.stderr @@ -0,0 +1,20 @@ +error: conflicting implementations of trait `TheTrait` for type `fn(&u8)`: + --> $DIR/coherence-free-vs-bound-region.rs:16:1 + | +LL | impl<'a> TheTrait for fn(&'a u8) {} + | -------------------------------- first implementation here +LL | +LL | impl TheTrait for fn(&u8) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(&u8)` + | +note: the lint level is defined here + --> $DIR/coherence-free-vs-bound-region.rs:10:9 + | +LL | #![deny(coherence_leak_check)] + | ^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + diff --git a/src/test/ui/coherence/coherence-wasm-bindgen.rs b/src/test/ui/coherence/coherence-wasm-bindgen.rs new file mode 100644 index 0000000000000..ee09a72449be1 --- /dev/null +++ b/src/test/ui/coherence/coherence-wasm-bindgen.rs @@ -0,0 +1,37 @@ +// Capture a coherence pattern from wasm-bindgen that we discovered as part of +// future-compatibility warning #56105. This pattern currently receives a lint +// warning but we probably want to support it long term. +// +// Key distinction: we are implementing once for `A` (take ownership) and one +// for `&A` (borrow). +// +// c.f. #56105 + +#![deny(coherence_leak_check)] + +trait IntoWasmAbi { + fn some_method(&self) {} +} + +trait FromWasmAbi {} +trait RefFromWasmAbi {} +trait ReturnWasmAbi {} + +impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b) +where + A: FromWasmAbi, + R: ReturnWasmAbi, +{ +} + +// Explicitly writing the bound lifetime. +impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn for<'x> Fn(&'x A) -> R + 'b) +where + A: RefFromWasmAbi, + R: ReturnWasmAbi, +{ + //~^^^^^ ERROR conflicting implementation + //~| WARNING this was previously accepted +} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-wasm-bindgen.stderr b/src/test/ui/coherence/coherence-wasm-bindgen.stderr new file mode 100644 index 0000000000000..c77483bb847f5 --- /dev/null +++ b/src/test/ui/coherence/coherence-wasm-bindgen.stderr @@ -0,0 +1,32 @@ +error: conflicting implementations of trait `IntoWasmAbi` for type `&dyn std::ops::Fn(&_) -> _`: + --> $DIR/coherence-wasm-bindgen.rs:28:1 + | +LL | / impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b) +LL | | where +LL | | A: FromWasmAbi, +LL | | R: ReturnWasmAbi, +LL | | { +LL | | } + | |_- first implementation here +... +LL | / impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn for<'x> Fn(&'x A) -> R + 'b) +LL | | where +LL | | A: RefFromWasmAbi, +LL | | R: ReturnWasmAbi, +... | +LL | | +LL | | } + | |_^ conflicting implementation for `&dyn std::ops::Fn(&_) -> _` + | +note: the lint level is defined here + --> $DIR/coherence-wasm-bindgen.rs:10:9 + | +LL | #![deny(coherence_leak_check)] + | ^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 + = note: downstream crates may implement trait `FromWasmAbi` for type `&_` + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + diff --git a/src/test/ui/hr-subtype/return-static.rs b/src/test/ui/hr-subtype/return-static.rs new file mode 100644 index 0000000000000..6455854f34db8 --- /dev/null +++ b/src/test/ui/hr-subtype/return-static.rs @@ -0,0 +1,13 @@ +// check-pass + +fn make() -> T { + panic!() +} + +fn take(x: T) {} + +fn main() { + let x: for<'a> fn(&'a u32) -> _ = make(); + let y: &'static u32 = x(&22); + take:: fn(&'b u32) -> &'b u32>(x); +} From 93e29823a9eb8de01c33fe48e9f47caf822a2fda Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 5 Jun 2020 21:14:34 +0000 Subject: [PATCH 10/13] add new coherence tests and update the documentation --- .../coherence-fn-covariant-bound-vs-static.rs | 26 +++++++++++++++++++ ...erence-fn-covariant-bound-vs-static.stderr | 13 ++++++++++ .../coherence/coherence-fn-implied-bounds.rs | 14 +++++++++- src/test/ui/coherence/coherence-fn-inputs.rs | 2 -- .../ui/coherence/coherence-fn-inputs.stderr | 2 +- 5 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.rs create mode 100644 src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr diff --git a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.rs b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.rs new file mode 100644 index 0000000000000..99f805f7f0f63 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.rs @@ -0,0 +1,26 @@ +// Test that impls for these two types are considered ovelapping: +// +// * `for<'r> fn(fn(&'r u32))` +// * `fn(fn(&'a u32)` where `'a` is free +// +// This is because, for `'a = 'static`, the two types overlap. +// Effectively for them to be equal to you get: +// +// * `for<'r> fn(fn(&'r u32)) <: fn(fn(&'static u32))` +// * true if `exists<'r> { 'r: 'static }` (obviously true) +// * `fn(fn(&'static u32)) <: for<'r> fn(fn(&'r u32))` +// * true if `forall<'r> { 'static: 'r }` (also true) + +trait Trait {} + +impl Trait for for<'r> fn(fn(&'r ())) {} +impl<'a> Trait for fn(fn(&'a ())) {} +//~^ ERROR conflicting implementations +// +// Note in particular that we do NOT get a future-compatibility warning +// here. This is because the new leak-check proposed in [MCP 295] does not +// "error" when these two types are equated. +// +// [MCP 295]: /~https://github.com/rust-lang/compiler-team/issues/295 + +fn main() {} diff --git a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr new file mode 100644 index 0000000000000..1f3a18c7fad9a --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))`: + --> $DIR/coherence-fn-covariant-bound-vs-static.rs:14:1 + | +LL | impl Trait for for<'r> fn(fn(&'r ())) {} + | ------------------------------------- first implementation here +LL | impl<'a> Trait for fn(fn(&'a ())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(fn(&'r ()))` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence/coherence-fn-implied-bounds.rs b/src/test/ui/coherence/coherence-fn-implied-bounds.rs index ba89a072f3441..4539af9a32e38 100644 --- a/src/test/ui/coherence/coherence-fn-implied-bounds.rs +++ b/src/test/ui/coherence/coherence-fn-implied-bounds.rs @@ -1,4 +1,16 @@ -// Example of coherence impls that we accept +// Test that our leak-check is not smart enough to take implied bounds +// into account (yet). Here we have two types that look like they +// should not be equivalent, but because of the rules on implied +// bounds we ought to know that, in fact, `'a = 'b` must always hold, +// and hence they are. +// +// Rustc can't figure this out and hence it accepts the impls but +// gives a future-compatibility warning (because we'd like to make +// this an error someday). +// +// Note that while we would like to make this a hard error, we also +// give the same warning for `coherence-wasm-bindgen.rs`, which ought +// to be accepted. #![deny(coherence_leak_check)] diff --git a/src/test/ui/coherence/coherence-fn-inputs.rs b/src/test/ui/coherence/coherence-fn-inputs.rs index 8c10899304127..3afec5c5459af 100644 --- a/src/test/ui/coherence/coherence-fn-inputs.rs +++ b/src/test/ui/coherence/coherence-fn-inputs.rs @@ -10,8 +10,6 @@ // * `'c` can be the intersection of `'a` and `'b` (and there is always an intersection) // * `'a` and `'b` can both be equal to `'c` -#![deny(coherence_leak_check)] - trait Trait {} impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {} impl Trait for for<'c> fn(&'c u32, &'c u32) { diff --git a/src/test/ui/coherence/coherence-fn-inputs.stderr b/src/test/ui/coherence/coherence-fn-inputs.stderr index a80357526e09d..56ab873a39320 100644 --- a/src/test/ui/coherence/coherence-fn-inputs.stderr +++ b/src/test/ui/coherence/coherence-fn-inputs.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)`: - --> $DIR/coherence-fn-inputs.rs:17:1 + --> $DIR/coherence-fn-inputs.rs:15:1 | LL | impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {} | ----------------------------------------------- first implementation here From c88a76e37b869d6ca343c6ba5d9f0c65deddbca2 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 6 Jun 2020 10:31:51 +0000 Subject: [PATCH 11/13] WIP bless test and compare-mode=nll --- ...ect-fn-ret-invariant.krisskross.nll.stderr | 20 +++--- ...project-fn-ret-invariant.oneuse.nll.stderr | 22 +++---- ...ject-fn-ret-invariant.transmute.nll.stderr | 8 +-- .../expect-fn-supply-fn.nll.stderr | 63 ++++++++++--------- ...erence-fn-covariant-bound-vs-static.stderr | 2 +- .../coherence-fn-implied-bounds.stderr | 4 +- ...ubtype.free_inv_x_vs_free_inv_y.nll.stderr | 20 +++--- .../hr-subtype.free_x_vs_free_y.nll.stderr | 10 +-- ...time-bounds-on-fns-where-clause.nll.stderr | 44 ++++++++++--- ...time-bounds-on-fns-where-clause.nll.stderr | 50 ++++++++++++--- .../regions-lifetime-bounds-on-fns.nll.stderr | 44 ++++++++++--- 11 files changed, 186 insertions(+), 101 deletions(-) diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr index 71a533a36f418..4fc336122fa9d 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr @@ -1,26 +1,26 @@ error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:55:4 + --> $DIR/project-fn-ret-invariant.rs:56:5 | -LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -- -- lifetime `'b` defined here +LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here ... -LL | (a, b) - | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` +LL | (a, b) + | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:55:4 + --> $DIR/project-fn-ret-invariant.rs:56:5 | -LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -- -- lifetime `'b` defined here +LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here ... -LL | (a, b) - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` +LL | (a, b) + | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr index c39030fbed1e1..44850df7b2f42 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr @@ -1,26 +1,26 @@ error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:38:12 + --> $DIR/project-fn-ret-invariant.rs:39:13 | -LL | fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -- -- lifetime `'b` defined here +LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | let f = foo; // <-- No consistent type can be inferred for `f` here. -LL | let a = bar(f, x); - | ^^^^^^^^^ argument requires that `'a` must outlive `'b` +LL | let f = foo; // <-- No consistent type can be inferred for `f` here. +LL | let a = bar(f, x); + | ^^^^^^^^^ argument requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:39:12 + --> $DIR/project-fn-ret-invariant.rs:40:13 | -LL | fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -- -- lifetime `'b` defined here +LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here ... -LL | let b = bar(f, y); - | ^^^^^^^^^ argument requires that `'b` must outlive `'a` +LL | let b = bar(f, y); + | ^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr index f74d4ba73bf4e..db82c9fd43794 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr @@ -1,11 +1,11 @@ error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:48:4 + --> $DIR/project-fn-ret-invariant.rs:49:5 | -LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { +LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { | -- lifetime `'a` defined here ... -LL | bar(foo, x) - | ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` +LL | bar(foo, x) + | ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` | = help: consider replacing `'a` with `'static` diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr index 97fdb76dd11c7..64a0b52a1fac5 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr @@ -1,42 +1,43 @@ -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:30:5 +error: lifetime may not live long enough + --> $DIR/expect-fn-supply-fn.rs:16:49 | -LL | fn with_closure_expecting_fn_with_free_region(_: 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 | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { + | -- lifetime `'x` defined here ... -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) -> _` +LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); + | ^ + | | + | has type `fn(&'1 u32)` + | requires that `'1` must outlive `'x` -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:37:5 +error: lifetime may not live long enough + --> $DIR/expect-fn-supply-fn.rs:16:49 | -LL | fn with_closure_expecting_fn_with_bound_region(_: 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 | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { + | -- lifetime `'x` defined here ... +LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); + | ^ requires that `'x` must outlive `'static` + | + = help: consider replacing `'x` with `'static` + +error: higher-ranked subtype error + --> $DIR/expect-fn-supply-fn.rs:32:49 + | +LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); + | ^ + +error: higher-ranked subtype error + --> $DIR/expect-fn-supply-fn.rs:39:50 + | 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) -> _` + | ^ -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:46:5 +error: higher-ranked subtype error + --> $DIR/expect-fn-supply-fn.rs:48:50 | -LL | fn with_closure_expecting_fn_with_bound_region(_: 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) -> _` + | ^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr index 1f3a18c7fad9a..49271edf8e5e4 100644 --- a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr +++ b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))`: - --> $DIR/coherence-fn-covariant-bound-vs-static.rs:14:1 + --> $DIR/coherence-fn-covariant-bound-vs-static.rs:17:1 | LL | impl Trait for for<'r> fn(fn(&'r ())) {} | ------------------------------------- first implementation here diff --git a/src/test/ui/coherence/coherence-fn-implied-bounds.stderr b/src/test/ui/coherence/coherence-fn-implied-bounds.stderr index d7853a0b1ebc3..a3e7f0bcde376 100644 --- a/src/test/ui/coherence/coherence-fn-implied-bounds.stderr +++ b/src/test/ui/coherence/coherence-fn-implied-bounds.stderr @@ -1,5 +1,5 @@ error: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32`: - --> $DIR/coherence-fn-implied-bounds.rs:9:1 + --> $DIR/coherence-fn-implied-bounds.rs:21:1 | LL | impl Trait for for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32 {} | ------------------------------------------------------------------ first implementation here @@ -8,7 +8,7 @@ LL | impl Trait for for<'c> fn(&'c &'c u32, &'c &'c u32) -> &'c u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32` | note: the lint level is defined here - --> $DIR/coherence-fn-implied-bounds.rs:3:9 + --> $DIR/coherence-fn-implied-bounds.rs:15:9 | LL | #![deny(coherence_leak_check)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr index 6b5e7a5a6345a..af5cf41be0a48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr @@ -1,33 +1,33 @@ error: lifetime may not live long enough - --> $DIR/hr-subtype.rs:33:13 + --> $DIR/hr-subtype.rs:39:13 | -LL | fn subtype<'x,'y:'x,'z:'y>() { - | -- -- lifetime `'y` defined here +LL | fn subtype<'x, 'y: 'x, 'z: 'y>() { + | -- -- lifetime `'y` defined here | | | lifetime `'x` defined here LL | gimme::<$t2>(None::<$t1>); | ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y` ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation | = help: consider adding the following bound: `'x: 'y` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: lifetime may not live long enough - --> $DIR/hr-subtype.rs:39:13 + --> $DIR/hr-subtype.rs:45:13 | -LL | fn supertype<'x,'y:'x,'z:'y>() { - | -- -- lifetime `'y` defined here +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { + | -- -- lifetime `'y` defined here | | | lifetime `'x` defined here LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y` ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation | = help: consider adding the following bound: `'x: 'y` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr index 7c0770924daaa..75d7e0e46b72a 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr @@ -1,16 +1,16 @@ error: lifetime may not live long enough - --> $DIR/hr-subtype.rs:39:13 + --> $DIR/hr-subtype.rs:45:13 | -LL | fn supertype<'x,'y:'x,'z:'y>() { - | -- -- lifetime `'y` defined here +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { + | -- -- lifetime `'y` defined here | | | lifetime `'x` defined here LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y` ... LL | / check! { free_x_vs_free_y: (fn(&'x u32), -LL | | fn(&'y u32)) } - | |__________________________________________- in this macro invocation +LL | | fn(&'y u32)) } + | |______________- in this macro invocation | = help: consider adding the following bound: `'x: 'y` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr index c3e8789a903b1..695f5506d5e38 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr @@ -1,14 +1,40 @@ -error[E0308]: mismatched types - --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 +error: lifetime may not live long enough + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:8:5 + | +LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:14:5 + | +LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y); + | ^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: higher-ranked subtype error + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12 | - = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` +LL | let _: fn(&mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr index 2aadd8f4f8c7e..a28f7aa3e08ca 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr @@ -1,14 +1,46 @@ -error[E0308]: mismatched types - --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 +error: lifetime may not live long enough + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:9:5 + | +LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:16:5 + | +LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y, z); + | ^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: higher-ranked subtype error + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 | LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; - | ----------------------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 | - = note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` - found fn item `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}` +LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 + | +LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr index 434a3e47b492a..37f7fcf2e331a 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr @@ -1,14 +1,40 @@ -error[E0308]: mismatched types - --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 +error: lifetime may not live long enough + --> $DIR/regions-lifetime-bounds-on-fns.rs:8:5 + | +LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/regions-lifetime-bounds-on-fns.rs:14:5 + | +LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y); + | ^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: higher-ranked subtype error + --> $DIR/regions-lifetime-bounds-on-fns.rs:20:12 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/regions-lifetime-bounds-on-fns.rs:20:12 | - = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` +LL | let _: fn(&mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. From 6929013b850db7c8ac55de4bcd0df8310ddb788b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 8 Jun 2020 23:12:01 +0000 Subject: [PATCH 12/13] fix subtle bug in NLL type checker The bug was revealed by the behavior of the old-lub-glb-hr-noteq1.rs test. The old-lub-glb-hr-noteq2 test shows the current 'order dependent' behavior of coercions around higher-ranked functions, at least when running with `-Zborrowck=mir`. Also, run compare-mode=nll. --- src/librustc_infer/infer/nll_relate/mod.rs | 8 ++- .../borrow_check/type_check/relate_tys.rs | 2 +- src/librustc_typeck/check/coercion.rs | 20 +++++- .../associated-types-eq-hr.nll.stderr | 33 +++++++++ .../higher-ranked-projection.bad.nll.stderr | 8 +++ .../resume-arg-late-bound.nll.stderr | 8 +++ ...ound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr | 14 ++++ .../hr-subtype.bound_a_vs_free_x.nll.stderr | 14 ++++ ...pe.bound_inv_a_b_vs_bound_inv_a.nll.stderr | 26 +++++++ .../ui/hrtb/hrtb-conflate-regions.nll.stderr | 14 ++++ .../ui/hrtb/hrtb-exists-forall-fn.nll.stderr | 8 +++ ...ists-forall-trait-contravariant.nll.stderr | 8 +++ ...b-exists-forall-trait-invariant.nll.stderr | 8 +++ .../ui/hrtb/hrtb-just-for-static.nll.stderr | 24 +++++++ src/test/ui/hrtb/issue-46989.nll.stderr | 8 +++ src/test/ui/issues/issue-40000.nll.stderr | 8 +++ src/test/ui/lub-glb/old-lub-glb-hr-eq.rs | 27 ++++++++ .../lub-glb/old-lub-glb-hr-noteq1.nll.stderr | 8 +++ src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs | 24 +++++++ ...hr.stderr => old-lub-glb-hr-noteq1.stderr} | 2 +- src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs | 33 +++++++++ .../ui/lub-glb/old-lub-glb-hr-noteq2.stderr | 18 +++++ src/test/ui/lub-glb/old-lub-glb-hr.rs | 57 ---------------- .../ui/lub-glb/old-lub-glb-object.nll.stderr | 14 ++++ .../closure-arg-type-mismatch.nll.stderr | 27 ++++++++ .../closure-mismatch.nll.stderr | 14 ++++ ...fn-subtyping-return-static-fail.nll.stderr | 8 +++ src/test/ui/rfc1623.nll.stderr | 68 +++++++++++++++++++ .../issue-57611-trait-alias.nll.stderr | 14 ++++ .../where-clauses/where-for-self-2.nll.stderr | 8 +++ 30 files changed, 472 insertions(+), 61 deletions(-) create mode 100644 src/test/ui/associated-types/associated-types-eq-hr.nll.stderr create mode 100644 src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr create mode 100644 src/test/ui/generator/resume-arg-late-bound.nll.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr create mode 100644 src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr create mode 100644 src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr create mode 100644 src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.nll.stderr create mode 100644 src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.nll.stderr create mode 100644 src/test/ui/hrtb/hrtb-just-for-static.nll.stderr create mode 100644 src/test/ui/hrtb/issue-46989.nll.stderr create mode 100644 src/test/ui/issues/issue-40000.nll.stderr create mode 100644 src/test/ui/lub-glb/old-lub-glb-hr-eq.rs create mode 100644 src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr create mode 100644 src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs rename src/test/ui/lub-glb/{old-lub-glb-hr.stderr => old-lub-glb-hr-noteq1.stderr} (93%) create mode 100644 src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs create mode 100644 src/test/ui/lub-glb/old-lub-glb-hr-noteq2.stderr delete mode 100644 src/test/ui/lub-glb/old-lub-glb-hr.rs create mode 100644 src/test/ui/lub-glb/old-lub-glb-object.nll.stderr create mode 100644 src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr create mode 100644 src/test/ui/mismatched_types/closure-mismatch.nll.stderr create mode 100644 src/test/ui/regions-fn-subtyping-return-static-fail.nll.stderr create mode 100644 src/test/ui/rfc1623.nll.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr create mode 100644 src/test/ui/where-clauses/where-for-self-2.nll.stderr diff --git a/src/librustc_infer/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs index 8de8925100608..2350c28dfaaff 100644 --- a/src/librustc_infer/infer/nll_relate/mod.rs +++ b/src/librustc_infer/infer/nll_relate/mod.rs @@ -522,7 +522,13 @@ where } if a == b { - return Ok(a); + // Subtle: if a or b has a bound variable that we are lazilly + // substituting, then even if a == b, it could be that the values we + // will substitute for those bound variables are *not* the same, and + // hence returning `Ok(a)` is incorrect. + if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() { + return Ok(a); + } } match (&a.kind, &b.kind) { diff --git a/src/librustc_mir/borrow_check/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/type_check/relate_tys.rs index 7ff12820db815..285d9ed64691a 100644 --- a/src/librustc_mir/borrow_check/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/type_check/relate_tys.rs @@ -25,7 +25,7 @@ pub(super) fn relate_types<'tcx>( category: ConstraintCategory, borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>, ) -> Fallible<()> { - debug!("eq_types(a={:?}, b={:?}, locations={:?})", a, b, locations); + debug!("relate_types(a={:?}, v={:?}, b={:?}, locations={:?})", a, v, b, locations); TypeRelating::new( infcx, NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category), diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index dec53c369bb18..b6cd8da236260 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -895,7 +895,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let prev_ty = self.resolve_vars_with_obligations(prev_ty); let new_ty = self.resolve_vars_with_obligations(new_ty); - debug!("coercion::try_find_coercion_lub({:?}, {:?})", prev_ty, new_ty); + debug!( + "coercion::try_find_coercion_lub({:?}, {:?}, exprs={:?} exprs)", + prev_ty, + new_ty, + exprs.len() + ); // Special-case that coercion alone cannot handle: // Function items or non-capturing closures of differing IDs or InternalSubsts. @@ -1001,6 +1006,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(ok) => { let (adjustments, target) = self.register_infer_ok_obligations(ok); self.apply_adjustments(new, adjustments); + debug!( + "coercion::try_find_coercion_lub: was able to coerce from previous type {:?} to new type {:?}", + prev_ty, new_ty, + ); return Ok(target); } Err(e) => first_error = Some(e), @@ -1031,6 +1040,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if !noop { + debug!( + "coercion::try_find_coercion_lub: older expression {:?} had adjustments, requiring LUB", + expr, + ); + return self .commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) .map(|ok| self.register_infer_ok_obligations(ok)); @@ -1048,6 +1062,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } Ok(ok) => { + debug!( + "coercion::try_find_coercion_lub: was able to coerce previous type {:?} to new type {:?}", + prev_ty, new_ty, + ); let (adjustments, target) = self.register_infer_ok_obligations(ok); for expr in exprs { let expr = expr.as_coercion_site(); diff --git a/src/test/ui/associated-types/associated-types-eq-hr.nll.stderr b/src/test/ui/associated-types/associated-types-eq-hr.nll.stderr new file mode 100644 index 0000000000000..25e9f726ba53a --- /dev/null +++ b/src/test/ui/associated-types/associated-types-eq-hr.nll.stderr @@ -0,0 +1,33 @@ +error[E0271]: type mismatch resolving `for<'x> >::A == &'x isize` + --> $DIR/associated-types-eq-hr.rs:87:5 + | +LL | fn foo() + | --- required by a bound in this +LL | where +LL | T: for<'x> TheTrait<&'x isize, A = &'x isize>, + | ------------- required by this bound in `foo` +... +LL | foo::(); + | ^^^^^^^^^^^^^^^^^ expected `isize`, found `usize` + | + = note: expected reference `&isize` + found reference `&usize` + +error[E0271]: type mismatch resolving `for<'x> >::A == &'x usize` + --> $DIR/associated-types-eq-hr.rs:91:5 + | +LL | fn bar() + | --- required by a bound in this +LL | where +LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>, + | ------------- required by this bound in `bar` +... +LL | bar::(); + | ^^^^^^^^^^^^^^^^ expected `usize`, found `isize` + | + = note: expected reference `&usize` + found reference `&isize` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr new file mode 100644 index 0000000000000..2e03986a9ed8f --- /dev/null +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/higher-ranked-projection.rs:25:5 + | +LL | foo(()); + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/generator/resume-arg-late-bound.nll.stderr b/src/test/ui/generator/resume-arg-late-bound.nll.stderr new file mode 100644 index 0000000000000..7d71219192407 --- /dev/null +++ b/src/test/ui/generator/resume-arg-late-bound.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/resume-arg-late-bound.rs:15:5 + | +LL | test(gen); + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr new file mode 100644 index 0000000000000..d5343566633d5 --- /dev/null +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/hr-subtype.rs:45:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, +LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } + | |_____________________________________________- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr new file mode 100644 index 0000000000000..f115609396756 --- /dev/null +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/hr-subtype.rs:45:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), +LL | | fn(&'x u32)) } + | |______________- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr new file mode 100644 index 0000000000000..4541c462ee056 --- /dev/null +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr @@ -0,0 +1,26 @@ +error: higher-ranked subtype error + --> $DIR/hr-subtype.rs:45:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), +LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } + | |__________________________________- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: higher-ranked subtype error + --> $DIR/hr-subtype.rs:45:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), +LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } + | |__________________________________- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr new file mode 100644 index 0000000000000..f290a93326f37 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/hrtb-conflate-regions.rs:27:10 + | +LL | fn b() { want_foo2::(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/hrtb-conflate-regions.rs:27:10 + | +LL | fn b() { want_foo2::(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr new file mode 100644 index 0000000000000..11390d9e2d265 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/hrtb-exists-forall-fn.rs:17:12 + | +LL | let _: for<'b> fn(&'b u32) = foo(); + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.nll.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.nll.stderr new file mode 100644 index 0000000000000..a4c3ffd1f6c08 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 + | +LL | foo::<()>(); + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.nll.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.nll.stderr new file mode 100644 index 0000000000000..e2a399b2faa9d --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 + | +LL | foo::<()>(); + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr b/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr new file mode 100644 index 0000000000000..8901a1b46817d --- /dev/null +++ b/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr @@ -0,0 +1,24 @@ +error: higher-ranked subtype error + --> $DIR/hrtb-just-for-static.rs:24:5 + | +LL | want_hrtb::() + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/hrtb-just-for-static.rs:30:5 + | +LL | fn give_some<'a>() { + | -- lifetime `'a` defined here +LL | want_hrtb::<&'a u32>() + | ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + | + = help: consider replacing `'a` with `'static` + +error: higher-ranked subtype error + --> $DIR/hrtb-just-for-static.rs:30:5 + | +LL | want_hrtb::<&'a u32>() + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/hrtb/issue-46989.nll.stderr b/src/test/ui/hrtb/issue-46989.nll.stderr new file mode 100644 index 0000000000000..6c127b92d97d1 --- /dev/null +++ b/src/test/ui/hrtb/issue-46989.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/issue-46989.rs:38:5 + | +LL | assert_foo::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/issues/issue-40000.nll.stderr b/src/test/ui/issues/issue-40000.nll.stderr new file mode 100644 index 0000000000000..f673fbae8b79c --- /dev/null +++ b/src/test/ui/issues/issue-40000.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/issue-40000.rs:6:9 + | +LL | foo(bar); + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-eq.rs b/src/test/ui/lub-glb/old-lub-glb-hr-eq.rs new file mode 100644 index 0000000000000..fbf4aee02045d --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-eq.rs @@ -0,0 +1,27 @@ +// Test that we give a note when the old LUB/GLB algorithm would have +// succeeded but the new code (which requires equality) gives an +// error. However, now that we handle subtyping correctly, we no +// longer get an error, because we recognize these two types as +// equivalent! +// +// check-pass + +fn foo(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) { + // The two types above are actually equivalent. With the older + // leak check, though, we didn't consider them as equivalent, and + // hence we gave errors. But now we've fixed that. + let z = match 22 { + 0 => x, + _ => y, + }; +} + +fn foo_cast(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) { + let z = match 22 { + // No error with an explicit cast: + 0 => x as for<'a> fn(&'a u8, &'a u8), + _ => y, + }; +} + +fn main() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr new file mode 100644 index 0000000000000..b95e247d2a8cf --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/old-lub-glb-hr-noteq1.rs:11:14 + | +LL | _ => y, + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs new file mode 100644 index 0000000000000..918542d471b58 --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs @@ -0,0 +1,24 @@ +// Test taking the LUB of two function types that are not equatable but where one is more +// general than the other. Test the case where the more general type (`x`) is the first +// match arm specifically. + +fn foo(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // The two types above are not equivalent. With the older LUB/GLB + // algorithm, this may have worked (I don't remember), but now it + // doesn't because we require equality. + let z = match 22 { + 0 => x, + _ => y, //~ ERROR `match` arms have incompatible types + }; +} + +fn foo_cast(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // But we can *upcast* explicitly the type of `x` and figure + // things out: + let z = match 22 { + 0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8, + _ => y, + }; +} + +fn main() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.stderr similarity index 93% rename from src/test/ui/lub-glb/old-lub-glb-hr.stderr rename to src/test/ui/lub-glb/old-lub-glb-hr-noteq1.stderr index f9ad4e5814eeb..305e952d6046b 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.stderr @@ -1,5 +1,5 @@ error[E0308]: `match` arms have incompatible types - --> $DIR/old-lub-glb-hr.rs:40:14 + --> $DIR/old-lub-glb-hr-noteq1.rs:11:14 | LL | let z = match 22 { | _____________- diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs new file mode 100644 index 0000000000000..0e069bc6f84e9 --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs @@ -0,0 +1,33 @@ +// Test taking the LUB of two function types that are not equatable but where +// one is more general than the other. Test the case where the more general type +// (`x`) is the second match arm specifically. +// +// Skip for compare-mode because the pure NLL checker accepts this test. (Note +// that it still errors in old-lub-glb-hr-noteq1.rs). What happens is that, due +// to the ordering of the match arms, we pick the correct "more general" fn +// type, and we ignore the errors from the non-NLL type checker that requires +// equality. The NLL type checker only requires a subtyping relationship, and +// that holds. +// +// ignore-compare-mode-nll + +fn foo(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // The two types above are not equivalent. With the older LUB/GLB + // algorithm, this may have worked (I don't remember), but now it + // doesn't because we require equality. + let z = match 22 { + 0 => y, + _ => x, //~ ERROR `match` arms have incompatible types + }; +} + +fn foo_cast(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // But we can *upcast* explicitly the type of `x` and figure + // things out: + let z = match 22 { + 0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8, + _ => y, + }; +} + +fn main() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.stderr new file mode 100644 index 0000000000000..252e13aada054 --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.stderr @@ -0,0 +1,18 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/old-lub-glb-hr-noteq2.rs:20:14 + | +LL | let z = match 22 { + | _____________- +LL | | 0 => y, + | | - this is found to be of type `for<'a> fn(&'a u8, &'a u8) -> &'a u8` +LL | | _ => x, + | | ^ one type is more general than the other +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` + found fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.rs b/src/test/ui/lub-glb/old-lub-glb-hr.rs deleted file mode 100644 index 5e24a99bcc331..0000000000000 --- a/src/test/ui/lub-glb/old-lub-glb-hr.rs +++ /dev/null @@ -1,57 +0,0 @@ -// Test that we give a note when the old LUB/GLB algorithm would have -// succeeded but the new code (which requires equality) gives an -// error. However, now that we handle subtyping correctly, we no -// longer get an error, because we recognize these two types as -// equivalent! - -fn foo( - x: fn(&u8, &u8), - y: for<'a> fn(&'a u8, &'a u8), -) { - // The two types above are actually equivalent. With the older - // leak check, though, we didn't consider them as equivalent, and - // hence we gave errors. But now we've fixed that. - let z = match 22 { - 0 => x, - _ => y, - }; -} - -fn foo_cast( - x: fn(&u8, &u8), - y: for<'a> fn(&'a u8, &'a u8), -) { - let z = match 22 { - // No error with an explicit cast: - 0 => x as for<'a> fn(&'a u8, &'a u8), - _ => y, - }; -} - -fn bar( - x: for<'a, 'b> fn(&'a u8, &'b u8)-> &'a u8, - y: for<'a> fn(&'a u8, &'a u8) -> &'a u8, -) { - // The two types above are not equivalent. With the older LUB/GLB - // algorithm, this may have worked (I don't remember), but now it - // doesn't because we require equality. - let z = match 22 { - 0 => x, - _ => y, //~ ERROR `match` arms have incompatible types - }; -} - -fn bar_cast( - x: for<'a, 'b> fn(&'a u8, &'b u8)-> &'a u8, - y: for<'a> fn(&'a u8, &'a u8) -> &'a u8, -) { - // But we can *upcast* explicitly the type of `x` and figure - // things out: - let z = match 22 { - 0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8, - _ => y, - }; -} - -fn main() { -} diff --git a/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr b/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr new file mode 100644 index 0000000000000..51bf96f32335b --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/old-lub-glb-object.rs:10:14 + | +LL | _ => y, + | ^ + +error: higher-ranked subtype error + --> $DIR/old-lub-glb-object.rs:10:14 + | +LL | _ => y, + | ^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr new file mode 100644 index 0000000000000..6ed91b20ab8a6 --- /dev/null +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr @@ -0,0 +1,27 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:3:14 + | +LL | a.iter().map(|_: (u32, u32)| 45); + | ^^^ ------------------ found signature of `fn((u32, u32)) -> _` + | | + | expected signature of `fn(&(u32, u32)) -> _` + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:4:14 + | +LL | a.iter().map(|_: &(u16, u16)| 45); + | ^^^ ------------------- found signature of `for<'r> fn(&'r (u16, u16)) -> _` + | | + | expected signature of `fn(&(u32, u32)) -> _` + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:5:14 + | +LL | a.iter().map(|_: (u16, u16)| 45); + | ^^^ ------------------ found signature of `fn((u16, u16)) -> _` + | | + | expected signature of `fn(&(u32, u32)) -> _` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/mismatched_types/closure-mismatch.nll.stderr b/src/test/ui/mismatched_types/closure-mismatch.nll.stderr new file mode 100644 index 0000000000000..745a61b866ed2 --- /dev/null +++ b/src/test/ui/mismatched_types/closure-mismatch.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/closure-mismatch.rs:8:5 + | +LL | baz(|_| ()); + | ^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/closure-mismatch.rs:8:5 + | +LL | baz(|_| ()); + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.nll.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.nll.stderr new file mode 100644 index 0000000000000..d762f55f9d5f1 --- /dev/null +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:5 + | +LL | want_G(baz); + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/rfc1623.nll.stderr b/src/test/ui/rfc1623.nll.stderr new file mode 100644 index 0000000000000..848d4fef1abfc --- /dev/null +++ b/src/test/ui/rfc1623.nll.stderr @@ -0,0 +1,68 @@ +error[E0277]: `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` cannot be shared between threads safely + --> $DIR/rfc1623.rs:21:1 + | +LL | / static SOME_STRUCT: &SomeStruct = &SomeStruct { +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |__^ `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` cannot be shared between threads safely + | + = help: within `&SomeStruct`, the trait `std::marker::Sync` is not implemented for `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` + = note: required because it appears within the type `&dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` + = note: required because it appears within the type `SomeStruct` + = note: required because it appears within the type `&SomeStruct` + = note: shared static variables must have a type that implements `Sync` + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr new file mode 100644 index 0000000000000..8c9cb742fac91 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/issue-57611-trait-alias.rs:21:9 + | +LL | |x| x + | ^^^^^ + +error: higher-ranked subtype error + --> $DIR/issue-57611-trait-alias.rs:21:9 + | +LL | |x| x + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/where-clauses/where-for-self-2.nll.stderr b/src/test/ui/where-clauses/where-for-self-2.nll.stderr new file mode 100644 index 0000000000000..d0c476dc6ec05 --- /dev/null +++ b/src/test/ui/where-clauses/where-for-self-2.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/where-for-self-2.rs:23:5 + | +LL | foo(&X); + | ^^^^^^^ + +error: aborting due to previous error + From d57689f9cde9a7066ffc8ca1125ea7e0d23df2c5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 8 Jun 2020 23:22:10 +0000 Subject: [PATCH 13/13] cite issue 73154 --- src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs index 0e069bc6f84e9..4bdd05b4f92fa 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs @@ -2,12 +2,12 @@ // one is more general than the other. Test the case where the more general type // (`x`) is the second match arm specifically. // -// Skip for compare-mode because the pure NLL checker accepts this test. (Note -// that it still errors in old-lub-glb-hr-noteq1.rs). What happens is that, due -// to the ordering of the match arms, we pick the correct "more general" fn -// type, and we ignore the errors from the non-NLL type checker that requires -// equality. The NLL type checker only requires a subtyping relationship, and -// that holds. +// FIXME(#73154) Skip for compare-mode because the pure NLL checker accepts this +// test. (Note that it still errors in old-lub-glb-hr-noteq1.rs). What happens +// is that, due to the ordering of the match arms, we pick the correct "more +// general" fn type, and we ignore the errors from the non-NLL type checker that +// requires equality. The NLL type checker only requires a subtyping +// relationship, and that holds. // // ignore-compare-mode-nll