From 512cf3ae88b26f50a92ebfcb69c24ca39acd72e6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 13 Jul 2025 21:01:25 +0000 Subject: [PATCH] Gate things properly --- .../src/type_check/constraint_conversion.rs | 4 ++- .../rustc_infer/src/infer/outlives/mod.rs | 14 +++++---- .../src/infer/outlives/obligations.rs | 7 +++-- compiler/rustc_session/src/options.rs | 2 ++ ...olved-typeck-results.no_assumptions.stderr | 25 +++++++++++++++ ...drop-tracking-unresolved-typeck-results.rs | 5 ++- .../issue-110963-early.no_assumptions.stderr | 31 +++++++++++++++++++ .../issue-110963-early.rs | 5 ++- ...ine-param-outlives-2.no_assumptions.stderr | 24 ++++++++++++++ ...igher-ranked-coroutine-param-outlives-2.rs | 5 ++- ...utine-param-outlives.no_assumptions.stderr | 8 +++++ .../higher-ranked-coroutine-param-outlives.rs | 5 ++- 12 files changed, 121 insertions(+), 14 deletions(-) create mode 100644 tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr create mode 100644 tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr create mode 100644 tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.no_assumptions.stderr create mode 100644 tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.no_assumptions.stderr diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index fec3e415f75b..989d2cc70dd9 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -160,7 +160,9 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { let mut next_outlives_predicates = vec![]; for (pred, constraint_category) in outlives_predicates { // Constraint is implied by a coroutine's well-formedness. - if higher_ranked_assumptions.contains(&pred) { + if self.infcx.tcx.sess.opts.unstable_opts.higher_ranked_assumptions + && higher_ranked_assumptions.contains(&pred) + { continue; } diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index db668032f1f2..19911bfbd48b 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -69,12 +69,14 @@ impl<'tcx> InferCtxt<'tcx> { // Filter out any region-region outlives assumptions that are implied by // coroutine well-formedness. - storage.data.constraints.retain(|(constraint, _)| match *constraint { - Constraint::RegSubReg(r1, r2) => !outlives_env - .higher_ranked_assumptions() - .contains(&ty::OutlivesPredicate(r2.into(), r1)), - _ => true, - }); + if self.tcx.sess.opts.unstable_opts.higher_ranked_assumptions { + storage.data.constraints.retain(|(constraint, _)| match *constraint { + Constraint::RegSubReg(r1, r2) => !outlives_env + .higher_ranked_assumptions() + .contains(&ty::OutlivesPredicate(r2.into(), r1)), + _ => true, + }); + } let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map()); diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 2066cdd717e0..1ca59c8d1301 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -235,9 +235,10 @@ impl<'tcx> InferCtxt<'tcx> { let (sup_type, sub_region) = (sup_type, sub_region).fold_with(&mut OpportunisticRegionResolver::new(self)); - if outlives_env - .higher_ranked_assumptions() - .contains(&ty::OutlivesPredicate(sup_type.into(), sub_region)) + if self.tcx.sess.opts.unstable_opts.higher_ranked_assumptions + && outlives_env + .higher_ranked_assumptions() + .contains(&ty::OutlivesPredicate(sup_type.into(), sub_region)) { continue; } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 626262c84425..2bdde2f887a3 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2256,6 +2256,8 @@ options! { environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)"), has_thread_local: Option = (None, parse_opt_bool, [TRACKED], "explicitly enable the `cfg(target_thread_local)` directive"), + higher_ranked_assumptions: bool = (false, parse_bool, [TRACKED], + "allow deducing higher-ranked outlives assumptions from coroutines when proving auto traits"), hint_mostly_unused: bool = (false, parse_bool, [TRACKED], "hint that most of this crate will go unused, to minimize work for uncalled functions"), human_readable_cgu_names: bool = (false, parse_bool, [TRACKED], diff --git a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr new file mode 100644 index 000000000000..d5560bf89203 --- /dev/null +++ b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr @@ -0,0 +1,25 @@ +error: implementation of `FnOnce` is not general enough + --> $DIR/drop-tracking-unresolved-typeck-results.rs:102:5 + | +LL | / send(async { +LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await +LL | | }); + | |______^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` + +error: implementation of `FnOnce` is not general enough + --> $DIR/drop-tracking-unresolved-typeck-results.rs:102:5 + | +LL | / send(async { +LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await +LL | | }); + | |______^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs index 51945e023529..16f929331cb4 100644 --- a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs +++ b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs @@ -1,6 +1,9 @@ //@ incremental //@ edition: 2021 -//@ check-pass +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 use std::future::*; use std::marker::PhantomData; diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr new file mode 100644 index 000000000000..bb4363649240 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr @@ -0,0 +1,31 @@ +error: implementation of `Send` is not general enough + --> $DIR/issue-110963-early.rs:17:5 + | +LL | / spawn(async move { +LL | | let mut hc = hc; +LL | | if !hc.check().await { +LL | | log_health_check_failure().await; +LL | | } +LL | | }); + | |______^ implementation of `Send` is not general enough + | + = note: `Send` would have to be implemented for the type `impl Future { ::check<'0>(..) }`, for any two lifetimes `'0` and `'1`... + = note: ...but `Send` is actually implemented for the type `impl Future { ::check<'2>(..) }`, for some specific lifetime `'2` + +error: implementation of `Send` is not general enough + --> $DIR/issue-110963-early.rs:17:5 + | +LL | / spawn(async move { +LL | | let mut hc = hc; +LL | | if !hc.check().await { +LL | | log_health_check_failure().await; +LL | | } +LL | | }); + | |______^ implementation of `Send` is not general enough + | + = note: `Send` would have to be implemented for the type `impl Future { ::check<'0>(..) }`, for any two lifetimes `'0` and `'1`... + = note: ...but `Send` is actually implemented for the type `impl Future { ::check<'2>(..) }`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.rs b/tests/ui/async-await/return-type-notation/issue-110963-early.rs index 7985f2e2de1a..8c3180c01191 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-early.rs +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.rs @@ -1,5 +1,8 @@ //@ edition: 2021 -//@ check-pass +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 #![feature(return_type_notation)] diff --git a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.no_assumptions.stderr b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.no_assumptions.stderr new file mode 100644 index 000000000000..8b62fb6a2547 --- /dev/null +++ b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.no_assumptions.stderr @@ -0,0 +1,24 @@ +error: lifetime bound not satisfied + --> $DIR/higher-ranked-coroutine-param-outlives-2.rs:14:5 + | +LL | / async { // a coroutine checked for autotrait impl `Send` +LL | | let x = None::>; // a type referencing GAT +LL | | async {}.await; // a yield point +LL | | } + | |_____^ + | + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-coroutine-param-outlives-2.rs:21:5 + | +LL | / async { // a coroutine checked for autotrait impl `Send` +LL | | let x = None::>; // a type referencing GAT +LL | | async {}.await; // a yield point +LL | | } + | |_____^ + | + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: aborting due to 2 previous errors + diff --git a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.rs b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.rs index f77626001654..a5ed162d62c9 100644 --- a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.rs +++ b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.rs @@ -1,5 +1,8 @@ -//@ check-pass //@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 pub trait FutureIterator { type Future<'s, 'cx>: Send diff --git a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.no_assumptions.stderr b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.no_assumptions.stderr new file mode 100644 index 000000000000..f747ba9a7334 --- /dev/null +++ b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.no_assumptions.stderr @@ -0,0 +1,8 @@ +error: `C` does not live long enough + --> $DIR/higher-ranked-coroutine-param-outlives.rs:21:5 + | +LL | async move { c.connect().await } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.rs b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.rs index 33a085ad26bc..5f683bd82fa4 100644 --- a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.rs +++ b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.rs @@ -1,5 +1,8 @@ //@ edition:2018 -//@ check-pass +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 use std::future::Future;