1
Fork 0

only avoid blaming assignments from argument patterns

This commit is contained in:
dianne 2024-12-21 13:23:57 -08:00
parent 1b2281a493
commit fe8b12f8cf
14 changed files with 54 additions and 67 deletions

View file

@ -2911,7 +2911,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
( (
name, name,
BorrowExplanation::MustBeValidFor { BorrowExplanation::MustBeValidFor {
category: ConstraintCategory::Assignment { .. }, category: ConstraintCategory::Assignment,
from_closure: false, from_closure: false,
region_name: region_name:
RegionName { RegionName {

View file

@ -41,7 +41,7 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
fn description(&self) -> &'static str { fn description(&self) -> &'static str {
// Must end with a space. Allows for empty names to be provided. // Must end with a space. Allows for empty names to be provided.
match self { match self {
ConstraintCategory::Assignment { .. } => "assignment ", ConstraintCategory::Assignment => "assignment ",
ConstraintCategory::Return(_) => "returning this value ", ConstraintCategory::Return(_) => "returning this value ",
ConstraintCategory::Yield => "yielding this value ", ConstraintCategory::Yield => "yielding this value ",
ConstraintCategory::UseAsConst => "using this value as a constant ", ConstraintCategory::UseAsConst => "using this value as a constant ",
@ -481,7 +481,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
(ConstraintCategory::Return(kind), true, false) if self.is_closure_fn_mut(fr) => { (ConstraintCategory::Return(kind), true, false) if self.is_closure_fn_mut(fr) => {
self.report_fnmut_error(&errci, kind) self.report_fnmut_error(&errci, kind)
} }
(ConstraintCategory::Assignment { .. }, true, false) (ConstraintCategory::Assignment, true, false)
| (ConstraintCategory::CallArgument(_), true, false) => { | (ConstraintCategory::CallArgument(_), true, false) => {
let mut db = self.report_escaping_data_error(&errci); let mut db = self.report_escaping_data_error(&errci);
@ -673,7 +673,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
// Revert to the normal error in these cases. // Revert to the normal error in these cases.
// Assignments aren't "escapes" in function items. // Assignments aren't "escapes" in function items.
if (fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none()) if (fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none())
|| (matches!(category, ConstraintCategory::Assignment { .. }) || (*category == ConstraintCategory::Assignment
&& self.regioncx.universal_regions().defining_ty.is_fn_def()) && self.regioncx.universal_regions().defining_ty.is_fn_def())
|| self.regioncx.universal_regions().defining_ty.is_const() || self.regioncx.universal_regions().defining_ty.is_const()
{ {

View file

@ -2080,25 +2080,22 @@ impl<'tcx> RegionInferenceContext<'tcx> {
| ConstraintCategory::CallArgument(_) | ConstraintCategory::CallArgument(_)
| ConstraintCategory::CopyBound | ConstraintCategory::CopyBound
| ConstraintCategory::SizedBound | ConstraintCategory::SizedBound
| ConstraintCategory::Assignment { has_interesting_ty: true } | ConstraintCategory::Assignment
| ConstraintCategory::Usage | ConstraintCategory::Usage
| ConstraintCategory::ClosureUpvar(_) => 2, | ConstraintCategory::ClosureUpvar(_) => 2,
// Give assignments a lower priority when flagged as less likely to be interesting.
// In particular, de-prioritize MIR assignments lowered from argument patterns.
ConstraintCategory::Assignment { has_interesting_ty: false } => 3,
// Generic arguments are unlikely to be what relates regions together // Generic arguments are unlikely to be what relates regions together
ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg) => 4, ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg) => 3,
// We handle predicates and opaque types specially; don't prioritize them here. // We handle predicates and opaque types specially; don't prioritize them here.
ConstraintCategory::Predicate(_) | ConstraintCategory::OpaqueType => 5, ConstraintCategory::Predicate(_) | ConstraintCategory::OpaqueType => 4,
// `Boring` constraints can correspond to user-written code and have useful spans, // `Boring` constraints can correspond to user-written code and have useful spans,
// but don't provide any other useful information for diagnostics. // but don't provide any other useful information for diagnostics.
ConstraintCategory::Boring => 6, ConstraintCategory::Boring => 5,
// `BoringNoLocation` constraints can point to user-written code, but are less // `BoringNoLocation` constraints can point to user-written code, but are less
// specific, and are not used for relations that would make sense to blame. // specific, and are not used for relations that would make sense to blame.
ConstraintCategory::BoringNoLocation => 7, ConstraintCategory::BoringNoLocation => 6,
// Do not blame internal constraints. // Do not blame internal constraints.
ConstraintCategory::Internal => 8, ConstraintCategory::Internal => 7,
ConstraintCategory::IllegalUniverse => 9, ConstraintCategory::IllegalUniverse => 8,
} }
}; };

View file

@ -892,18 +892,20 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
Some(l) if !body.local_decls[l].is_user_variable() => { Some(l) if !body.local_decls[l].is_user_variable() => {
ConstraintCategory::Boring ConstraintCategory::Boring
} }
Some(l) => ConstraintCategory::Assignment { Some(_)
has_interesting_ty: body.local_decls[l].user_ty.is_some() if let Some(body_id) = tcx
|| matches!( .hir_node_by_def_id(body.source.def_id().expect_local())
body.local_decls[l].local_info(), .body_id()
LocalInfo::User(BindingForm::Var(VarBindingForm { && let params = tcx.hir().body(body_id).params
opt_ty_info: Some(_), && params
.. .iter()
})) .any(|param| param.span.contains(stmt.source_info.span)) =>
), {
}, // Assignments generated from lowering argument patterns shouldn't be called
// Assignments to projections should be considered interesting. // "assignments" in diagnostics and aren't interesting to blame for errors.
_ => ConstraintCategory::Assignment { has_interesting_ty: true }, ConstraintCategory::Boring
}
_ => ConstraintCategory::Assignment,
}; };
debug!( debug!(
"assignment category: {:?} {:?}", "assignment category: {:?} {:?}",
@ -1238,7 +1240,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ConstraintCategory::Boring ConstraintCategory::Boring
} }
// The return type of a call is interesting for diagnostics. // The return type of a call is interesting for diagnostics.
_ => ConstraintCategory::Assignment { has_interesting_ty: true }, _ => ConstraintCategory::Assignment,
}; };
let locations = term_location.to_locations(); let locations = term_location.to_locations();

View file

@ -242,12 +242,7 @@ pub enum ConstraintCategory<'tcx> {
CallArgument(Option<Ty<'tcx>>), CallArgument(Option<Ty<'tcx>>),
CopyBound, CopyBound,
SizedBound, SizedBound,
Assignment { Assignment,
/// Whether this assignment is likely to be interesting to refer to in diagnostics.
/// Currently, this is true when it's assigning to a projection, when it's assigning from
/// the return value of a call, and when it has a user-provided type annotation.
has_interesting_ty: bool,
},
/// A constraint that came from a usage of a variable (e.g. in an ADT expression /// A constraint that came from a usage of a variable (e.g. in an ADT expression
/// like `Foo { field: my_val }`) /// like `Foo { field: my_val }`)
Usage, Usage,

View file

@ -17,8 +17,8 @@
| '?2 live at {bb1[0]} | '?2 live at {bb1[0]}
| '?3 live at {bb1[1..=3]} | '?3 live at {bb1[1..=3]}
| '?4 live at {bb1[4..=7], bb2[0..=2]} | '?4 live at {bb1[4..=7], bb2[0..=2]}
| '?2: '?3 due to Assignment { has_interesting_ty: false } at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:19:13: 19:18 (#0) | '?2: '?3 due to Assignment at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:19:13: 19:18 (#0)
| '?3: '?4 due to Assignment { has_interesting_ty: false } at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:20:13: 20:14 (#0) | '?3: '?4 due to Assignment at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:20:13: 20:14 (#0)
| |
| Borrows | Borrows
| bw0: issued at bb1[0] in '?2 | bw0: issued at bb1[0] in '?2

View file

@ -17,8 +17,8 @@
| '?2 live at {bb1[0]} | '?2 live at {bb1[0]}
| '?3 live at {bb1[1..=3]} | '?3 live at {bb1[1..=3]}
| '?4 live at {bb1[4..=7], bb2[0..=2]} | '?4 live at {bb1[4..=7], bb2[0..=2]}
| '?2: '?3 due to Assignment { has_interesting_ty: false } at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:19:13: 19:18 (#0) | '?2: '?3 due to Assignment at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:19:13: 19:18 (#0)
| '?3: '?4 due to Assignment { has_interesting_ty: false } at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:20:13: 20:14 (#0) | '?3: '?4 due to Assignment at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:20:13: 20:14 (#0)
| |
| Borrows | Borrows
| bw0: issued at bb1[0] in '?2 | bw0: issued at bb1[0] in '?2

View file

@ -15,7 +15,7 @@
| '?1 live at {bb0[0..=22]} | '?1 live at {bb0[0..=22]}
| '?2 live at {bb0[10]} | '?2 live at {bb0[10]}
| '?3 live at {bb0[11]} | '?3 live at {bb0[11]}
| '?2: '?3 due to Assignment { has_interesting_ty: false } at Single(bb0[10]) ($DIR/storage_ranges.rs:7:17: 7:25 (#0) | '?2: '?3 due to Assignment at Single(bb0[10]) ($DIR/storage_ranges.rs:7:17: 7:25 (#0)
| |
| Borrows | Borrows
| bw0: issued at bb0[10] in '?2 | bw0: issued at bb0[10] in '?2

View file

@ -47,11 +47,11 @@ fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
let x = match true { let x = match true {
true => foo::<&'c ()>, //~ ERROR lifetime may not live long enough true => foo::<&'c ()>, //~ ERROR lifetime may not live long enough
false => foo::<&'a ()>, false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough
}; };
x(a); x(a);
x(b); //~ ERROR lifetime may not live long enough x(b);
x(c); x(c);
} }

View file

@ -133,17 +133,20 @@ LL | true => foo::<&'c ()>,
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/fn_def_coercion.rs:54:5 --> $DIR/fn_def_coercion.rs:50:18
| |
LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
... ...
LL | x(b); LL | false => foo::<&'a ()>,
| ^^^^ argument requires that `'b` must outlive `'a` | ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
| |
= help: consider adding the following bound: `'b: 'a` = help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of a function pointer to `foo`
= note: the function `foo` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: the following changes may resolve your lifetime errors help: the following changes may resolve your lifetime errors
| |

View file

@ -4,11 +4,9 @@ error[E0597]: `c` does not live long enough
LL | let c = 66; LL | let c = 66;
| - binding `c` declared here | - binding `c` declared here
LL | let f = SomeStruct::<&'static u32>; LL | let f = SomeStruct::<&'static u32>;
| -------------------------- assignment requires that `c` is borrowed for `'static`
LL | f(&c); LL | f(&c);
| --^^- | ^^ borrowed value does not live long enough
| | |
| | borrowed value does not live long enough
| argument requires that `c` is borrowed for `'static`
LL | } LL | }
| - `c` dropped here while still borrowed | - `c` dropped here while still borrowed
@ -20,11 +18,9 @@ LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
LL | let c = 66; LL | let c = 66;
| - binding `c` declared here | - binding `c` declared here
LL | let f = SomeStruct::<&'a u32>; LL | let f = SomeStruct::<&'a u32>;
| --------------------- assignment requires that `c` is borrowed for `'a`
LL | f(&c); LL | f(&c);
| --^^- | ^^ borrowed value does not live long enough
| | |
| | borrowed value does not live long enough
| argument requires that `c` is borrowed for `'a`
LL | } LL | }
| - `c` dropped here while still borrowed | - `c` dropped here while still borrowed
@ -37,11 +33,9 @@ LL | let _closure = || {
LL | let c = 66; LL | let c = 66;
| - binding `c` declared here | - binding `c` declared here
LL | let f = SomeStruct::<&'a u32>; LL | let f = SomeStruct::<&'a u32>;
| --------------------- assignment requires that `c` is borrowed for `'a`
LL | f(&c); LL | f(&c);
| --^^- | ^^ borrowed value does not live long enough
| | |
| | borrowed value does not live long enough
| argument requires that `c` is borrowed for `'a`
LL | }; LL | };
| - `c` dropped here while still borrowed | - `c` dropped here while still borrowed

View file

@ -4,11 +4,10 @@ error[E0597]: `a` does not live long enough
LL | let a = 22; LL | let a = 22;
| - binding `a` declared here | - binding `a` declared here
... ...
LL | let x = <&'static u32 as Bazoom<_>>::method;
| ----------------------------------- assignment requires that `a` is borrowed for `'static`
LL | x(&a, b, c); LL | x(&a, b, c);
| --^^------- | ^^ borrowed value does not live long enough
| | |
| | borrowed value does not live long enough
| argument requires that `a` is borrowed for `'static`
LL | } LL | }
| - `a` dropped here while still borrowed | - `a` dropped here while still borrowed

View file

@ -4,11 +4,10 @@ error[E0597]: `a` does not live long enough
LL | let a = 22; LL | let a = 22;
| - binding `a` declared here | - binding `a` declared here
... ...
LL | let x = <&'static u32 as Bazoom<_>>::method;
| ----------------------------------- assignment requires that `a` is borrowed for `'static`
LL | x(&a, b, c); LL | x(&a, b, c);
| --^^------- | ^^ borrowed value does not live long enough
| | |
| | borrowed value does not live long enough
| argument requires that `a` is borrowed for `'static`
LL | } LL | }
| - `a` dropped here while still borrowed | - `a` dropped here while still borrowed

View file

@ -6,11 +6,9 @@ LL | fn foo<'a>() {
LL | let x = 0; LL | let x = 0;
| - binding `x` declared here | - binding `x` declared here
LL | let f = &drop::<&'a i32>; LL | let f = &drop::<&'a i32>;
| ---------------- assignment requires that `x` is borrowed for `'a`
LL | f(&x); LL | f(&x);
| --^^- | ^^ borrowed value does not live long enough
| | |
| | borrowed value does not live long enough
| argument requires that `x` is borrowed for `'a`
LL | LL |
LL | } LL | }
| - `x` dropped here while still borrowed | - `x` dropped here while still borrowed