From 5cdbe83af82e0e48a05bc87ff41ef381e45391dc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 27 Feb 2024 23:30:07 +0000 Subject: [PATCH] Opportunistically resolve regions when processing region outlives obligations --- .../src/infer/outlives/obligations.rs | 10 +++++++++- .../impl-implied-bounds-compatibility.rs | 2 +- .../impl-implied-bounds-compatibility.stderr | 20 ++++--------------- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index c0a99e5cc4177..8dd3a1f40cc10 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -62,6 +62,7 @@ use crate::infer::outlives::components::{push_outlives_components, Component}; use crate::infer::outlives::env::RegionBoundPairs; use crate::infer::outlives::verify::VerifyBoundCx; +use crate::infer::resolve::OpportunisticRegionResolver; use crate::infer::{ self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound, }; @@ -69,7 +70,9 @@ use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::query::NoSolution; -use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{ + self, GenericArgsRef, Region, Ty, TyCtxt, TypeFoldable as _, TypeVisitableExt, +}; use rustc_middle::ty::{GenericArgKind, PolyTypeOutlivesPredicate}; use rustc_span::DUMMY_SP; use smallvec::smallvec; @@ -176,6 +179,11 @@ impl<'tcx> InferCtxt<'tcx> { .map_err(|NoSolution| (outlives, origin.clone()))? .no_bound_vars() .expect("started with no bound vars, should end with no bound vars"); + // `TypeOutlives` is structural, so we should try to opportunistically resolve all + // region vids before processing regions, so we have a better chance to match clauses + // in our param-env. + let (sup_type, sub_region) = + (sup_type, sub_region).fold_with(&mut OpportunisticRegionResolver::new(self)); debug!(?sup_type, ?sub_region, ?origin); diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.rs b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.rs index 7f3817b326adc..5e3d21eb26ad7 100644 --- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.rs +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.rs @@ -10,7 +10,7 @@ pub trait MessageListenersInterface { impl<'a> MessageListenersInterface for MessageListeners<'a> { fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { - //~^ ERROR cannot infer an appropriate lifetime for lifetime parameter 'b in generic type due to conflicting requirements + //~^ ERROR in type `&'a MessageListeners<'_>`, reference has a longer lifetime than the data it references self } } diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr index 6a412eb5e4bee..e0cf15d0d1f33 100644 --- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr @@ -1,27 +1,15 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'b in generic type due to conflicting requirements +error[E0491]: in type `&'a MessageListeners<'_>`, reference has a longer lifetime than the data it references --> $DIR/impl-implied-bounds-compatibility.rs:12:5 | LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'c` as defined here... - --> $DIR/impl-implied-bounds-compatibility.rs:12:5 - | -LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...so that the method type is compatible with trait - --> $DIR/impl-implied-bounds-compatibility.rs:12:5 - | -LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: expected `fn(&'c MessageListeners<'_>) -> &'c MessageListeners<'c>` - found `fn(&MessageListeners<'_>) -> &'a MessageListeners<'_>` -note: but, the lifetime must be valid for the lifetime `'a` as defined here... +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/impl-implied-bounds-compatibility.rs:11:6 | LL | impl<'a> MessageListenersInterface for MessageListeners<'a> { | ^^ -note: ...so that the reference type `&'a MessageListeners<'_>` does not outlive the data it points at +note: but the referenced data is only valid for the lifetime `'c` as defined here --> $DIR/impl-implied-bounds-compatibility.rs:12:5 | LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { @@ -29,4 +17,4 @@ LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0491`.