mirror of
https://github.com/rust-lang/rust.git
synced 2025-10-02 10:18:25 +00:00
diagnostics :3
This commit is contained in:
parent
8365ad17da
commit
c2a0fa86ad
@ -244,7 +244,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindOpaqueRegion<'_, 'tcx> {
|
||||
|
||||
// Find a path between the borrow region and our opaque capture.
|
||||
if let Some((path, _)) =
|
||||
self.regioncx.find_constraint_paths_between_regions(self.borrow_region, |r| {
|
||||
self.regioncx.find_constraint_path_between_regions(self.borrow_region, |r| {
|
||||
r == opaque_region_vid
|
||||
})
|
||||
{
|
||||
|
@ -1405,18 +1405,39 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
}
|
||||
|
||||
/// Walks the graph of constraints (where `'a: 'b` is considered
|
||||
/// an edge `'a -> 'b`) to find all paths from `from_region` to
|
||||
/// `to_region`. The paths are accumulated into the vector
|
||||
/// `results`. The paths are stored as a series of
|
||||
/// `ConstraintIndex` values -- in other words, a list of *edges*.
|
||||
/// an edge `'a -> 'b`) to find a path from `from_region` to
|
||||
/// `to_region`.
|
||||
///
|
||||
/// Returns: a series of constraints as well as the region `R`
|
||||
/// that passed the target test.
|
||||
#[instrument(skip(self, target_test), ret)]
|
||||
pub(crate) fn find_constraint_paths_between_regions(
|
||||
pub(crate) fn find_constraint_path_between_regions(
|
||||
&self,
|
||||
from_region: RegionVid,
|
||||
target_test: impl Fn(RegionVid) -> bool,
|
||||
) -> Option<(Vec<OutlivesConstraint<'tcx>>, RegionVid)> {
|
||||
self.find_constraint_path_between_regions_inner(true, from_region, &target_test).or_else(
|
||||
|| self.find_constraint_path_between_regions_inner(false, from_region, &target_test),
|
||||
)
|
||||
}
|
||||
|
||||
/// The constraints we get from equating the hidden type of each use of an opaque
|
||||
/// with its final concrete type may end up getting preferred over other, potentially
|
||||
/// longer constraint paths.
|
||||
///
|
||||
/// Given that we compute the final concrete type by relying on this existing constraint
|
||||
/// path, this can easily end up hiding the actual reason for why we require these regions
|
||||
/// to be equal.
|
||||
///
|
||||
/// To handle this, we first look at the path while ignoring these constraints and then
|
||||
/// retry while considering them. This is not perfect, as the `from_region` may have already
|
||||
/// been partially related to its argument region, so while we rely on a member constraint
|
||||
/// to get a complete path, the most relevant step of that path already existed before then.
|
||||
fn find_constraint_path_between_regions_inner(
|
||||
&self,
|
||||
ignore_opaque_type_constraints: bool,
|
||||
from_region: RegionVid,
|
||||
target_test: impl Fn(RegionVid) -> bool,
|
||||
) -> Option<(Vec<OutlivesConstraint<'tcx>>, RegionVid)> {
|
||||
let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
|
||||
context[from_region] = Trace::StartRegion;
|
||||
@ -1431,7 +1452,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
||||
while let Some(r) = deque.pop_front() {
|
||||
debug!(
|
||||
"find_constraint_paths_between_regions: from_region={:?} r={:?} value={}",
|
||||
"find_constraint_path_between_regions: from_region={:?} r={:?} value={}",
|
||||
from_region,
|
||||
r,
|
||||
self.region_value_str(r),
|
||||
@ -1503,9 +1524,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
let edges = self.constraint_graph.outgoing_edges_from_graph(r, &self.constraints);
|
||||
// This loop can be hot.
|
||||
for constraint in edges {
|
||||
if matches!(constraint.category, ConstraintCategory::IllegalUniverse) {
|
||||
debug!("Ignoring illegal universe constraint: {constraint:?}");
|
||||
continue;
|
||||
match constraint.category {
|
||||
ConstraintCategory::IllegalUniverse => {
|
||||
debug!("Ignoring illegal universe constraint: {constraint:?}");
|
||||
continue;
|
||||
}
|
||||
ConstraintCategory::OpaqueType if ignore_opaque_type_constraints => {
|
||||
debug!("Ignoring member constraint: {constraint:?}");
|
||||
continue;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
debug_assert_eq!(constraint.sup, r);
|
||||
handle_trace(constraint.sub, Trace::FromGraph(constraint));
|
||||
@ -1521,7 +1549,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, location: Location) -> RegionVid {
|
||||
trace!(scc = ?self.constraint_sccs.scc(fr1));
|
||||
trace!(universe = ?self.max_nameable_universe(self.constraint_sccs.scc(fr1)));
|
||||
self.find_constraint_paths_between_regions(fr1, |r| {
|
||||
self.find_constraint_path_between_regions(fr1, |r| {
|
||||
// First look for some `r` such that `fr1: r` and `r` is live at `location`
|
||||
trace!(?r, liveness_constraints=?self.liveness_constraints.pretty_print_live_points(r));
|
||||
self.liveness_constraints.is_live_at(r, location)
|
||||
@ -1531,9 +1559,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// `fr1: r` and `r` is a placeholder from some universe
|
||||
// `fr1` cannot name. This would force `fr1` to be
|
||||
// `'static`.
|
||||
self.find_constraint_paths_between_regions(fr1, |r| {
|
||||
self.cannot_name_placeholder(fr1, r)
|
||||
})
|
||||
self.find_constraint_path_between_regions(fr1, |r| self.cannot_name_placeholder(fr1, r))
|
||||
})
|
||||
.or_else(|| {
|
||||
// If we fail to find THAT, it may be that `fr1` is a
|
||||
@ -1546,9 +1572,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// must be able to name the universe of R2, because R2 will
|
||||
// be at least `'empty(Universe(R2))`, and `R1` must be at
|
||||
// larger than that.
|
||||
self.find_constraint_paths_between_regions(fr1, |r| {
|
||||
self.cannot_name_placeholder(r, fr1)
|
||||
})
|
||||
self.find_constraint_path_between_regions(fr1, |r| self.cannot_name_placeholder(r, fr1))
|
||||
})
|
||||
.map(|(_path, r)| r)
|
||||
.unwrap()
|
||||
@ -1604,9 +1628,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
) -> (BlameConstraint<'tcx>, Vec<OutlivesConstraint<'tcx>>) {
|
||||
// Find all paths
|
||||
let (path, target_region) = self
|
||||
.find_constraint_paths_between_regions(from_region, target_test)
|
||||
.find_constraint_path_between_regions(from_region, target_test)
|
||||
.or_else(|| {
|
||||
self.find_constraint_paths_between_regions(from_region, |r| {
|
||||
self.find_constraint_path_between_regions(from_region, |r| {
|
||||
self.cannot_name_placeholder(from_region, r)
|
||||
})
|
||||
})
|
||||
|
@ -53,7 +53,7 @@ LL | || let y = &*x;
|
||||
LL | || *x += 1;
|
||||
LL | || y
|
||||
LL | || })()
|
||||
| ||______^_- opaque type requires that borrow lasts for `'1`
|
||||
| ||______^_- argument requires that borrow lasts for `'1`
|
||||
| |_______|
|
||||
| creates a temporary value which is freed while still in use
|
||||
LL | }
|
||||
@ -102,7 +102,7 @@ LL | || let y = &*x;
|
||||
LL | || *x += 1;
|
||||
LL | || y
|
||||
LL | || })()
|
||||
| ||______^_- opaque type requires that borrow lasts for `'1`
|
||||
| ||______^_- argument requires that borrow lasts for `'1`
|
||||
| |_______|
|
||||
| creates a temporary value which is freed while still in use
|
||||
LL | }
|
||||
|
@ -17,8 +17,8 @@ impl<'a> Future for ListFut<'a> {
|
||||
}
|
||||
|
||||
async fn fut(bufs: &mut [&mut [u8]]) {
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
ListFut(bufs).await
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
pub struct ListFut2<'a>(&'a mut [&'a mut [u8]]);
|
||||
@ -31,8 +31,8 @@ impl<'a> Future for ListFut2<'a> {
|
||||
}
|
||||
|
||||
async fn fut2(bufs: &mut [&mut [u8]]) -> i32 {
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
ListFut2(bufs).await
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,15 +1,12 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/issue-76547.rs:19:38
|
||||
--> $DIR/issue-76547.rs:20:13
|
||||
|
|
||||
LL | async fn fut(bufs: &mut [&mut [u8]]) {
|
||||
| ____________________-_____-___________^
|
||||
| | | |
|
||||
| | | let's call the lifetime of this reference `'2`
|
||||
| | let's call the lifetime of this reference `'1`
|
||||
LL | |
|
||||
LL | | ListFut(bufs).await
|
||||
LL | | }
|
||||
| |_^ opaque type requires that `'1` must outlive `'2`
|
||||
LL | async fn fut(bufs: &mut [&mut [u8]]) {
|
||||
| - - let's call the lifetime of this reference `'2`
|
||||
| |
|
||||
| let's call the lifetime of this reference `'1`
|
||||
LL | ListFut(bufs).await
|
||||
| ^^^^ this usage requires that `'1` must outlive `'2`
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
@ -17,17 +14,14 @@ LL | async fn fut<'a>(bufs: &'a mut [&'a mut [u8]]) {
|
||||
| ++++ ++ ++
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/issue-76547.rs:33:46
|
||||
--> $DIR/issue-76547.rs:34:14
|
||||
|
|
||||
LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 {
|
||||
| _____________________-_____-__________________^
|
||||
| | | |
|
||||
| | | let's call the lifetime of this reference `'2`
|
||||
| | let's call the lifetime of this reference `'1`
|
||||
LL | |
|
||||
LL | | ListFut2(bufs).await
|
||||
LL | | }
|
||||
| |_^ opaque type requires that `'1` must outlive `'2`
|
||||
LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 {
|
||||
| - - let's call the lifetime of this reference `'2`
|
||||
| |
|
||||
| let's call the lifetime of this reference `'1`
|
||||
LL | ListFut2(bufs).await
|
||||
| ^^^^ this usage requires that `'1` must outlive `'2`
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
|
@ -9,7 +9,7 @@ LL | async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trai
|
||||
LL | |
|
||||
LL | | (a, b)
|
||||
LL | | }
|
||||
| |_^ opaque type requires that `'a` must outlive `'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`
|
||||
|
||||
|
@ -6,7 +6,7 @@ LL | fn boom<'a, 'b>() -> impl Extend<'a, 'b> {
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | None::<&'_ &'_ ()>
|
||||
| ^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'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`
|
||||
|
||||
|
@ -18,7 +18,7 @@ mod bav {
|
||||
impl Bar for i32 {}
|
||||
|
||||
fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> {
|
||||
val.use_self() //~ ERROR `val` does not live long enough
|
||||
val.use_self() //~ ERROR cannot return value referencing function parameter `val`
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,11 @@
|
||||
error[E0597]: `val` does not live long enough
|
||||
error[E0515]: cannot return value referencing function parameter `val`
|
||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9
|
||||
|
|
||||
LL | fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> {
|
||||
| -- --- binding `val` declared here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | val.use_self()
|
||||
| ^^^-----------
|
||||
| ---^^^^^^^^^^^
|
||||
| |
|
||||
| borrowed value does not live long enough
|
||||
| opaque type requires that `val` is borrowed for `'a`
|
||||
LL | }
|
||||
| - `val` dropped here while still borrowed
|
||||
| returns a value referencing data owned by the current function
|
||||
| `val` is borrowed here
|
||||
|
||||
error[E0515]: cannot return value referencing function parameter `val`
|
||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9
|
||||
@ -76,5 +70,5 @@ LL | val.use_self()
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0515, E0521, E0597.
|
||||
Some errors have detailed explanations: E0515, E0521.
|
||||
For more information about an error, try `rustc --explain E0515`.
|
||||
|
@ -8,7 +8,7 @@ LL | |
|
||||
LL | | current: None,
|
||||
LL | | remaining: self.0.iter(),
|
||||
LL | | }
|
||||
| |_________^ opaque type requires that `'1` must outlive `'static`
|
||||
| |_________^ returning this value requires that `'1` must outlive `'static`
|
||||
|
|
||||
help: to declare that `impl Iterator<Item = Box<(dyn Foo + 'static)>>` captures data from argument `self`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
@ -63,7 +63,7 @@ LL | |
|
||||
LL | | current: None,
|
||||
LL | | remaining: self.0.iter(),
|
||||
LL | | }
|
||||
| |_________^ opaque type requires that `'a` must outlive `'static`
|
||||
| |_________^ returning this value requires that `'a` must outlive `'static`
|
||||
|
|
||||
help: to declare that `impl Iterator<Item = Box<(dyn Foo + 'static)>>` captures data from argument `self`, you can add an explicit `'a` lifetime bound
|
||||
|
|
||||
|
Loading…
x
Reference in New Issue
Block a user