mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-29 03:27:44 +00:00

The SCCs of the region graph are not a reliable heuristic to use for blaming an interesting constraint for diagnostics. For region errors, if the outlived region is `'static`, or the involved types are invariant in their lifetiems, there will be cycles in the constraint graph containing both the target region and the most interesting constraints to blame. To get better diagnostics in these cases, this commit removes that heuristic.
205 lines
6.5 KiB
Rust
205 lines
6.5 KiB
Rust
//@ edition: 2024
|
|
|
|
use std::fmt::Display;
|
|
|
|
fn display_len<T>(x: &Vec<T>) -> impl Display {
|
|
//~^ NOTE in this expansion of desugaring of `impl Trait`
|
|
//~| NOTE in this expansion of desugaring of `impl Trait`
|
|
//~| NOTE in this expansion of desugaring of `impl Trait`
|
|
//~| NOTE in this expansion of desugaring of `impl Trait`
|
|
//~| NOTE in this expansion of desugaring of `impl Trait`
|
|
x.len()
|
|
}
|
|
|
|
fn conflicting_borrow() {
|
|
let mut x = vec![];
|
|
let a = display_len(&x);
|
|
//~^ NOTE this call may capture more lifetimes than intended
|
|
//~| NOTE immutable borrow occurs here
|
|
x.push(1);
|
|
//~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
|
|
//~| NOTE mutable borrow occurs here
|
|
println!("{a}");
|
|
//~^ NOTE immutable borrow later used here
|
|
}
|
|
|
|
fn needs_static() {
|
|
let x = vec![1];
|
|
//~^ NOTE binding `x` declared here
|
|
let a = display_len(&x);
|
|
//~^ ERROR `x` does not live long enough
|
|
//~| NOTE this call may capture more lifetimes than intended
|
|
//~| NOTE borrowed value does not live long enoug
|
|
|
|
fn needs_static(_: impl Sized + 'static) {}
|
|
needs_static(a);
|
|
//~^ NOTE argument requires that `x` is borrowed for `'static`
|
|
}
|
|
//~^ NOTE `x` dropped here while still borrowed
|
|
|
|
fn is_moved() {
|
|
let x = vec![1];
|
|
//~^ NOTE binding `x` declared here
|
|
let a = display_len(&x);
|
|
//~^ NOTE this call may capture more lifetimes than intended
|
|
//~| NOTE borrow of `x` occurs here
|
|
|
|
fn mv(_: impl Sized) {}
|
|
mv(x);
|
|
//~^ ERROR cannot move out of `x` because it is borrowed
|
|
//~| NOTE move out of `x` occurs here
|
|
}
|
|
//~^ NOTE borrow might be used here, when `a` is dropped
|
|
|
|
fn display_len_mut<T>(x: &mut Vec<T>) -> impl Display {
|
|
//~^ NOTE in this expansion of desugaring of `impl Trait`
|
|
//~| NOTE in this expansion of desugaring of `impl Trait`
|
|
//~| NOTE in this expansion of desugaring of `impl Trait`
|
|
x.len()
|
|
}
|
|
|
|
fn conflicting_borrow_mut() {
|
|
let mut x = vec![];
|
|
let a = display_len_mut(&mut x);
|
|
//~^ NOTE this call may capture more lifetimes than intended
|
|
//~| NOTE first mutable borrow occurs here
|
|
x.push(1);
|
|
//~^ ERROR cannot borrow `x` as mutable more than once
|
|
//~| NOTE second mutable borrow occurs here
|
|
println!("{a}");
|
|
//~^ NOTE first borrow later used here
|
|
}
|
|
|
|
fn needs_static_mut() {
|
|
let mut x = vec![1];
|
|
//~^ NOTE binding `x` declared here
|
|
let a = display_len_mut(&mut x);
|
|
//~^ ERROR `x` does not live long enough
|
|
//~| NOTE this call may capture more lifetimes than intended
|
|
//~| NOTE borrowed value does not live long enough
|
|
|
|
fn needs_static(_: impl Sized + 'static) {}
|
|
needs_static(a);
|
|
//~^ NOTE argument requires that `x` is borrowed for `'static`
|
|
}
|
|
//~^ NOTE `x` dropped here while still borrowed
|
|
|
|
fn is_move_mut() {
|
|
let mut x = vec![1];
|
|
//~^ NOTE binding `x` declared here
|
|
let a = display_len_mut(&mut x);
|
|
//~^ NOTE this call may capture more lifetimes than intended
|
|
//~| NOTE borrow of `x` occurs here
|
|
|
|
fn mv(_: impl Sized) {}
|
|
mv(x);
|
|
//~^ ERROR cannot move out of `x` because it is borrowed
|
|
//~| NOTE move out of `x` occurs here
|
|
}
|
|
//~^ NOTE borrow might be used here, when `a` is dropped
|
|
|
|
struct S { f: i32 }
|
|
|
|
fn display_field<T: Copy + Display>(t: &T) -> impl Display {
|
|
//~^ NOTE in this expansion of desugaring of `impl Trait`
|
|
//~| NOTE in this expansion of desugaring of `impl Trait`
|
|
//~| NOTE in this expansion of desugaring of `impl Trait`
|
|
*t
|
|
}
|
|
|
|
fn conflicting_borrow_field() {
|
|
let mut s = S { f: 0 };
|
|
let a = display_field(&s.f);
|
|
//~^ NOTE this call may capture more lifetimes than intended
|
|
//~| NOTE `s.f` is borrowed here
|
|
s.f = 1;
|
|
//~^ ERROR cannot assign to `s.f` because it is borrowed
|
|
//~| NOTE `s.f` is assigned to here but it was already borrowed
|
|
println!("{a}");
|
|
//~^ NOTE borrow later used here
|
|
}
|
|
|
|
fn display_field_mut<T: Copy + Display>(t: &mut T) -> impl Display {
|
|
*t
|
|
}
|
|
|
|
fn conflicting_borrow_field_mut() {
|
|
let mut s = S { f: 0 };
|
|
let a = display_field(&mut s.f);
|
|
//~^ NOTE this call may capture more lifetimes than intended
|
|
//~| NOTE `s.f` is borrowed here
|
|
s.f = 1;
|
|
//~^ ERROR cannot assign to `s.f` because it is borrowed
|
|
//~| NOTE `s.f` is assigned to here but it was already borrowed
|
|
println!("{a}");
|
|
//~^ NOTE borrow later used here
|
|
}
|
|
|
|
fn field_move() {
|
|
let mut s = S { f: 0 };
|
|
let a = display_field(&mut s.f);
|
|
//~^ NOTE this call may capture more lifetimes than intended
|
|
//~| NOTE `s.f` is borrowed here
|
|
s.f;
|
|
//~^ ERROR cannot use `s.f` because it was mutably borrowed
|
|
//~| NOTE use of borrowed `s.f`
|
|
println!("{a}");
|
|
//~^ NOTE borrow later used here
|
|
}
|
|
|
|
struct Z {
|
|
f: Vec<i32>,
|
|
}
|
|
|
|
fn live_long() {
|
|
let x;
|
|
{
|
|
let z = Z { f: vec![1] };
|
|
//~^ NOTE binding `z` declared here
|
|
x = display_len(&z.f);
|
|
//~^ ERROR `z.f` does not live long enough
|
|
//~| NOTE this call may capture more lifetimes than intended
|
|
//~| NOTE values in a scope are dropped in the opposite order they are defined
|
|
//~| NOTE borrowed value does not live long enough
|
|
}
|
|
//~^ NOTE `z.f` dropped here while still borrowed
|
|
}
|
|
//~^ NOTE borrow might be used here, when `x` is dropped
|
|
|
|
fn temp() {
|
|
let x = { let x = display_len(&mut vec![0]); x };
|
|
//~^ ERROR temporary value dropped while borrowed
|
|
//~| NOTE this call may capture more lifetimes than intended
|
|
//~| NOTE consider using a `let` binding to create a longer lived value
|
|
//~| NOTE borrow later used here
|
|
//~| NOTE temporary value is freed at the end of this statement
|
|
}
|
|
|
|
// FIXME: This doesn't display a useful Rust 2024 suggestion :(
|
|
fn returned() -> impl Sized {
|
|
let x = vec![0];
|
|
//~^ NOTE binding `x` declared here
|
|
display_len(&x)
|
|
//~^ ERROR `x` does not live long enough
|
|
//~| NOTE borrowed value does not live long enough
|
|
//~| NOTE argument requires that `x` is borrowed for `'static`
|
|
}
|
|
//~^ NOTE `x` dropped here while still borrowed
|
|
|
|
fn capture_apit(x: &impl Sized) -> impl Sized {}
|
|
//~^ NOTE you could use a `use<...>` bound to explicitly specify captures, but
|
|
|
|
fn test_apit() {
|
|
let x = String::new();
|
|
//~^ NOTE binding `x` declared here
|
|
let y = capture_apit(&x);
|
|
//~^ NOTE borrow of `x` occurs here
|
|
//~| NOTE this call may capture more lifetimes than intended
|
|
drop(x);
|
|
//~^ ERROR cannot move out of `x` because it is borrowed
|
|
//~| NOTE move out of `x` occurs here
|
|
}
|
|
//~^ NOTE borrow might be used here, when `y` is dropped
|
|
|
|
fn main() {}
|