Skip to content

Commit

Permalink
Stop proving outlives constraints on regions we already reported erro…
Browse files Browse the repository at this point in the history
…rs on
  • Loading branch information
oli-obk committed May 28, 2024
1 parent a04ac26 commit 8e7a7f9
Show file tree
Hide file tree
Showing 23 changed files with 65 additions and 234 deletions.
14 changes: 12 additions & 2 deletions compiler/rustc_borrowck/src/nll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
placeholder_indices,
placeholder_index_to_region: _,
liveness_constraints,
outlives_constraints,
member_constraints,
mut outlives_constraints,
mut member_constraints,
universe_causes,
type_tests,
} = constraints;
Expand All @@ -144,6 +144,16 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
&universal_region_relations,
);

if let Some(guar) = universal_regions.tainted_by_errors() {
// Suppress unhelpful extra errors in `infer_opaque_types` by clearing out all
// outlives bounds that we may end up checking.
outlives_constraints = Default::default();
member_constraints = Default::default();

// Also taint the entire scope.
infcx.set_tainted_by_errors(guar);
}

let mut regioncx = RegionInferenceContext::new(
infcx,
var_origins,
Expand Down
20 changes: 17 additions & 3 deletions compiler/rustc_borrowck/src/universal_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ use rustc_middle::ty::{self, InlineConstArgs, InlineConstArgsParts, RegionVid, T
use rustc_middle::ty::{GenericArgs, GenericArgsRef};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::{kw, sym};
use rustc_span::Symbol;
use rustc_span::{ErrorGuaranteed, Symbol};
use std::cell::Cell;
use std::iter;

use crate::renumber::RegionCtxt;
Expand Down Expand Up @@ -186,6 +187,10 @@ struct UniversalRegionIndices<'tcx> {

/// The vid assigned to `'static`. Used only for diagnostics.
pub fr_static: RegionVid,

/// Whether we've encountered an error region. If we have, cancel all
/// outlives errors, as they are likely bogus.
pub tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
}

#[derive(Debug, PartialEq)]
Expand Down Expand Up @@ -408,6 +413,10 @@ impl<'tcx> UniversalRegions<'tcx> {
}
}
}

pub fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
self.indices.tainted_by_errors.get()
}
}

struct UniversalRegionsBuilder<'cx, 'tcx> {
Expand Down Expand Up @@ -663,7 +672,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
let arg_mapping = iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var()));

UniversalRegionIndices { indices: global_mapping.chain(arg_mapping).collect(), fr_static }
UniversalRegionIndices {
indices: global_mapping.chain(arg_mapping).collect(),
fr_static,
tainted_by_errors: Cell::new(None),
}
}

fn compute_inputs_and_output(
Expand Down Expand Up @@ -868,7 +881,8 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
if let ty::ReVar(..) = *r {
r.as_var()
} else if r.is_error() {
} else if let ty::ReError(guar) = *r {
self.tainted_by_errors.set(Some(guar));
// We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the
// `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if
// errors are being emitted and 2) it leaves the happy path unaffected.
Expand Down
1 change: 0 additions & 1 deletion tests/ui/associated-inherent-types/issue-109299.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@ impl Lexer<'d> { //~ ERROR use of undeclared lifetime name `'d`
}

fn test(_: Lexer::Cursor) {}
//~^ ERROR: lifetime may not live long enough

fn main() {}
11 changes: 1 addition & 10 deletions tests/ui/associated-inherent-types/issue-109299.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,6 @@ LL | impl Lexer<'d> {
| |
| help: consider introducing lifetime `'d` here: `<'d>`

error: lifetime may not live long enough
--> $DIR/issue-109299.rs:10:1
|
LL | fn test(_: Lexer::Cursor) {}
| ^^^^^^^^-^^^^^^^^^^^^^^^^
| | |
| | has type `Lexer<'1>::Cursor`
| requires that `'1` must outlive `'static`

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0261`.
1 change: 0 additions & 1 deletion tests/ui/borrowck/generic_const_early_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ struct DataWrapper<'static> {
//~^ ERROR invalid lifetime parameter name: `'static`
data: &'a [u8; Self::SIZE],
//~^ ERROR use of undeclared lifetime name `'a`
//~^^ ERROR lifetime may not live long enough
}

impl DataWrapper<'a> {
Expand Down
10 changes: 2 additions & 8 deletions tests/ui/borrowck/generic_const_early_param.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ LL | data: &'a [u8; Self::SIZE],
| ^^ undeclared lifetime

error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/generic_const_early_param.rs:11:18
--> $DIR/generic_const_early_param.rs:10:18
|
LL | impl DataWrapper<'a> {
| - ^^ undeclared lifetime
Expand All @@ -30,13 +30,7 @@ LL | #![feature(generic_const_exprs)]
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
= note: `#[warn(incomplete_features)]` on by default

error: lifetime may not live long enough
--> $DIR/generic_const_early_param.rs:6:20
|
LL | data: &'a [u8; Self::SIZE],
| ^^^^^^^^^^ requires that `'_` must outlive `'static`

error: aborting due to 4 previous errors; 1 warning emitted
error: aborting due to 3 previous errors; 1 warning emitted

Some errors have detailed explanations: E0261, E0262.
For more information about an error, try `rustc --explain E0261`.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ impl<T> X for T { //~ ERROR: not all trait items implemented
//~^ ERROR missing generics for associated type
//~^^ ERROR missing generics for associated type
//~| ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters
//~| ERROR may not live long enough
t
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,7 @@ help: add missing lifetime argument
LL | fn foo<'a, T1: X<Y<'a> = T1>>(t : T1) -> T1::Y<'a> {
| ++++

error: lifetime may not live long enough
--> $DIR/gat-trait-path-missing-lifetime.rs:8:3
|
LL | fn foo<'a, T1: X<Y = T1>>(t : T1) -> T1::Y<'a> {
| ^^^^^^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | lifetime `'a` defined here
| requires that `'a` must outlive `'static`

error: aborting due to 5 previous errors
error: aborting due to 4 previous errors

Some errors have detailed explanations: E0046, E0049, E0107.
For more information about an error, try `rustc --explain E0046`.
1 change: 0 additions & 1 deletion tests/ui/generic-associated-types/issue-70304.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,4 @@ fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
pub fn main() {
let doc = create_doc();
let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc);
//~^ ERROR: `doc` does not live long enough
}
18 changes: 2 additions & 16 deletions tests/ui/generic-associated-types/issue-70304.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,7 @@ LL | type Cursor<'a>: DocCursor<'a>;
= note: this bound is currently required to ensure that impls have maximum flexibility
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information

error[E0597]: `doc` does not live long enough
--> $DIR/issue-70304.rs:54:59
|
LL | let doc = create_doc();
| --- binding `doc` declared here
LL | let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc);
| ------------^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `doc` is borrowed for `'static`
LL |
LL | }
| - `doc` dropped here while still borrowed

error: aborting due to 4 previous errors
error: aborting due to 3 previous errors

Some errors have detailed explanations: E0106, E0597, E0637.
Some errors have detailed explanations: E0106, E0637.
For more information about an error, try `rustc --explain E0106`.
3 changes: 1 addition & 2 deletions tests/ui/generic-associated-types/issue-80433.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ fn test_simpler<'a>(dst: &'a mut impl TestMut<Output = &'a mut f32>)
//~^ ERROR missing generics for associated type
{
for n in 0i16..100 {
*dst.test_mut() = n.into(); //~ ERROR: cannot borrow
//~^ ERROR: borrowed data escapes outside of function
*dst.test_mut() = n.into();
}
}

Expand Down
28 changes: 2 additions & 26 deletions tests/ui/generic-associated-types/issue-80433.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -25,30 +25,6 @@ help: add missing lifetime argument
LL | fn test_simpler<'a>(dst: &'a mut impl TestMut<Output<'a> = &'a mut f32>)
| ++++

error[E0499]: cannot borrow `*dst` as mutable more than once at a time
--> $DIR/issue-80433.rs:25:10
|
LL | *dst.test_mut() = n.into();
| ^^^-----------
| |
| `*dst` was mutably borrowed here in the previous iteration of the loop
| argument requires that `*dst` is borrowed for `'static`

error[E0521]: borrowed data escapes outside of function
--> $DIR/issue-80433.rs:25:10
|
LL | fn test_simpler<'a>(dst: &'a mut impl TestMut<Output = &'a mut f32>)
| -- --- `dst` is a reference that is only valid in the function body
| |
| lifetime `'a` defined here
...
LL | *dst.test_mut() = n.into();
| ^^^^^^^^^^^^^^
| |
| `dst` escapes the function body here
| argument requires that `'a` must outlive `'static`

error: aborting due to 4 previous errors
error: aborting due to 2 previous errors

Some errors have detailed explanations: E0107, E0499, E0521.
For more information about an error, try `rustc --explain E0107`.
For more information about this error, try `rustc --explain E0107`.
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
// issue: 114146


trait Foo {
fn bar<'other: 'a>() -> impl Sized + 'a {}
//~^ ERROR use of undeclared lifetime name `'a`
//~| ERROR use of undeclared lifetime name `'a`
//~| ERROR expected generic lifetime parameter, found `'static`
}

fn main() {}
17 changes: 4 additions & 13 deletions tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/bad-item-bound-within-rpitit-2.rs:5:20
--> $DIR/bad-item-bound-within-rpitit-2.rs:4:20
|
LL | fn bar<'other: 'a>() -> impl Sized + 'a {}
| ^^ undeclared lifetime
Expand All @@ -14,7 +14,7 @@ LL | trait Foo<'a> {
| ++++

error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/bad-item-bound-within-rpitit-2.rs:5:42
--> $DIR/bad-item-bound-within-rpitit-2.rs:4:42
|
LL | fn bar<'other: 'a>() -> impl Sized + 'a {}
| ^^ undeclared lifetime
Expand All @@ -28,15 +28,6 @@ help: consider introducing lifetime `'a` here
LL | trait Foo<'a> {
| ++++

error[E0792]: expected generic lifetime parameter, found `'static`
--> $DIR/bad-item-bound-within-rpitit-2.rs:5:45
|
LL | fn bar<'other: 'a>() -> impl Sized + 'a {}
| ------ ^^
| |
| cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

Some errors have detailed explanations: E0261, E0792.
For more information about an error, try `rustc --explain E0261`.
For more information about this error, try `rustc --explain E0261`.
7 changes: 2 additions & 5 deletions tests/ui/impl-trait/issues/issue-67830.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ struct Wrap<F>(F);

impl<A, B, F> MyFn<A> for Wrap<F>
where
F: Fn(A) -> B
F: Fn(A) -> B,
{
type Output = B;

Expand All @@ -16,13 +16,10 @@ where
}
}


struct A;
fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
fn test() -> impl for<'a> MyFn<&'a A, Output = impl Iterator + 'a> {
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
Wrap(|a| Some(a).into_iter())
//~^ ERROR implementation of `FnOnce` is not general enough
//~| ERROR implementation of `FnOnce` is not general enough
}

fn main() {}
31 changes: 6 additions & 25 deletions tests/ui/impl-trait/issues/issue-67830.stderr
Original file line number Diff line number Diff line change
@@ -1,34 +1,15 @@
error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
--> $DIR/issue-67830.rs:21:62
--> $DIR/issue-67830.rs:20:64
|
LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
| ^^
LL | fn test() -> impl for<'a> MyFn<&'a A, Output = impl Iterator + 'a> {
| ^^
|
note: lifetime declared here
--> $DIR/issue-67830.rs:21:23
--> $DIR/issue-67830.rs:20:23
|
LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
LL | fn test() -> impl for<'a> MyFn<&'a A, Output = impl Iterator + 'a> {
| ^^

error: implementation of `FnOnce` is not general enough
--> $DIR/issue-67830.rs:23:5
|
LL | Wrap(|a| Some(a).into_iter())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
= note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`

error: implementation of `FnOnce` is not general enough
--> $DIR/issue-67830.rs:23:5
|
LL | Wrap(|a| Some(a).into_iter())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
= note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 3 previous errors
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0657`.
5 changes: 0 additions & 5 deletions tests/ui/impl-trait/issues/issue-88236-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,11 @@ fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
&()
//~^ ERROR implementation of `Hrtb` is not general enough
//~| ERROR implementation of `Hrtb` is not general enough
}

fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
x
//~^ ERROR implementation of `Hrtb` is not general enough
//~| ERROR implementation of `Hrtb` is not general enough
//~| ERROR lifetime may not live long enough
}

fn main() {}
Loading

0 comments on commit 8e7a7f9

Please sign in to comment.