Skip to content

Commit

Permalink
Rollup merge of rust-lang#125667 - oli-obk:taintify, r=TaKO8Ki
Browse files Browse the repository at this point in the history
Silence follow-up errors directly based on error types and regions

During type_of, we used to just return an error type if there were any errors encountered. This is problematic, because it means a struct declared as `struct Foo<'static>` will end up not finding any inherent or trait impls because those impl blocks' `Self` type will be `{type error}` instead of `Foo<'re_error>`. Now it's the latter, silencing nonsensical follow-up errors about `Foo` not having any methods.

Unfortunately that now allows for new follow-up errors, because borrowck treats `'re_error` as `'static`, causing nonsensical errors about non-error lifetimes not outliving `'static`. So what I also did was to just strip all outlives bounds that borrowck found, thus never letting it check them. There are probably more nuanced ways to do this, but I worried there would be other nonsensical errors if some outlives bounds were missing. Also from the test changes, it looked like an improvement everywhere.
  • Loading branch information
compiler-errors committed Jun 4, 2024
2 parents 85f90a4 + 39b39da commit 5019bb6
Show file tree
Hide file tree
Showing 43 changed files with 271 additions and 297 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
4 changes: 3 additions & 1 deletion compiler/rustc_hir_analysis/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
bug!("unexpected sort of node in type_of(): {:?}", x);
}
};
if let Err(e) = icx.check_tainted_by_errors() {
if let Err(e) = icx.check_tainted_by_errors()
&& !output.references_error()
{
ty::EarlyBinder::bind(Ty::new_error(tcx, e))
} else {
ty::EarlyBinder::bind(output)
Expand Down
13 changes: 8 additions & 5 deletions tests/rustdoc-ui/unable-fulfill-trait.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
// This test ensures that it's not crashing rustdoc.

pub struct Foo<'a, 'b, T> {
field1: dyn Bar<'a, 'b,>,
field1: dyn Bar<'a, 'b>,
//~^ ERROR
//~| ERROR
//~| ERROR
}

pub trait Bar<'x, 's, U>
where U: 'x,
Self:'x,
Self:'s
{}
where
U: 'x,
Self: 'x,
Self: 's,
{
}
31 changes: 24 additions & 7 deletions tests/rustdoc-ui/unable-fulfill-trait.stderr
Original file line number Diff line number Diff line change
@@ -1,26 +1,43 @@
error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/unable-fulfill-trait.rs:4:17
|
LL | field1: dyn Bar<'a, 'b,>,
LL | field1: dyn Bar<'a, 'b>,
| ^^^ expected 1 generic argument
|
note: trait defined here, with 1 generic parameter: `U`
--> $DIR/unable-fulfill-trait.rs:9:11
--> $DIR/unable-fulfill-trait.rs:10:11
|
LL | pub trait Bar<'x, 's, U>
| ^^^ -
help: add missing generic argument
|
LL | field1: dyn Bar<'a, 'b, U,>,
LL | field1: dyn Bar<'a, 'b, U>,
| +++

error[E0227]: ambiguous lifetime bound, explicit lifetime bound required
--> $DIR/unable-fulfill-trait.rs:4:13
|
LL | field1: dyn Bar<'a, 'b,>,
| ^^^^^^^^^^^^^^^^
LL | field1: dyn Bar<'a, 'b>,
| ^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors
error[E0478]: lifetime bound not satisfied
--> $DIR/unable-fulfill-trait.rs:4:13
|
LL | field1: dyn Bar<'a, 'b>,
| ^^^^^^^^^^^^^^^
|
note: lifetime parameter instantiated with the lifetime `'b` as defined here
--> $DIR/unable-fulfill-trait.rs:3:20
|
LL | pub struct Foo<'a, 'b, T> {
| ^^
note: but lifetime parameter must outlive the lifetime `'a` as defined here
--> $DIR/unable-fulfill-trait.rs:3:16
|
LL | pub struct Foo<'a, 'b, T> {
| ^^

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0107, E0227.
Some errors have detailed explanations: E0107, E0227, E0478.
For more information about an error, try `rustc --explain E0107`.
2 changes: 1 addition & 1 deletion tests/ui/associated-inherent-types/issue-109071.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ impl<T> Windows { //~ ERROR: missing generics for struct `Windows`

impl<T> Windows<T> {
fn T() -> Option<Self::Item> {}
//~^ ERROR: ambiguous associated type
//[no_gate]~^ ERROR: ambiguous associated type
}

fn main() {}
17 changes: 2 additions & 15 deletions tests/ui/associated-inherent-types/issue-109071.with_gate.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,7 @@ help: add missing generic argument
LL | impl<T> Windows<T> {
| +++

error[E0223]: ambiguous associated type
--> $DIR/issue-109071.rs:15:22
|
LL | fn T() -> Option<Self::Item> {}
| ^^^^^^^^^^
|
help: use fully-qualified syntax
|
LL | fn T() -> Option<<Windows<T> as IntoAsyncIterator>::Item> {}
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LL | fn T() -> Option<<Windows<T> as IntoIterator>::Item> {}
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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

Some errors have detailed explanations: E0107, E0223, E0637.
Some errors have detailed explanations: E0107, E0637.
For more information about an error, try `rustc --explain E0107`.
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`.
2 changes: 1 addition & 1 deletion tests/ui/const-generics/issues/issue-71381.full.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ LL | pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "
= note: type parameters may not be used in the type of const parameters

error[E0770]: the type of const parameters must not depend on other generic parameters
--> $DIR/issue-71381.rs:22:40
--> $DIR/issue-71381.rs:23:40
|
LL | const FN: unsafe extern "C" fn(Args),
| ^^^^ the type must not depend on the parameter `Args`
Expand Down
20 changes: 18 additions & 2 deletions tests/ui/const-generics/issues/issue-71381.min.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,29 @@ LL | pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "
= note: type parameters may not be used in the type of const parameters

error[E0770]: the type of const parameters must not depend on other generic parameters
--> $DIR/issue-71381.rs:22:40
--> $DIR/issue-71381.rs:23:40
|
LL | const FN: unsafe extern "C" fn(Args),
| ^^^^ the type must not depend on the parameter `Args`
|
= note: type parameters may not be used in the type of const parameters

error: aborting due to 2 previous errors
error: using function pointers as const generic parameters is forbidden
--> $DIR/issue-71381.rs:14:61
|
LL | pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`

error: using function pointers as const generic parameters is forbidden
--> $DIR/issue-71381.rs:23:19
|
LL | const FN: unsafe extern "C" fn(Args),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0770`.
2 changes: 2 additions & 0 deletions tests/ui/const-generics/issues/issue-71381.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ unsafe extern "C" fn pass(args: PassArg) {
impl Test {
pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
//~^ ERROR: the type of const parameters must not depend on other generic parameters
//[min]~^^ ERROR: using function pointers as const generic parameters is forbidden
self.0 = Self::trampiline::<Args, IDX, FN> as _
}

Expand All @@ -21,6 +22,7 @@ impl Test {
const IDX: usize,
const FN: unsafe extern "C" fn(Args),
//~^ ERROR: the type of const parameters must not depend on other generic parameters
//[min]~^^ ERROR: using function pointers as const generic parameters is forbidden
>(
args: Args,
) {
Expand Down
10 changes: 9 additions & 1 deletion tests/ui/const-generics/issues/issue-71611.min.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ LL | fn func<A, const F: fn(inner: A)>(outer: A) {
|
= note: type parameters may not be used in the type of const parameters

error: aborting due to 1 previous error
error: using function pointers as const generic parameters is forbidden
--> $DIR/issue-71611.rs:5:21
|
LL | fn func<A, const F: fn(inner: A)>(outer: A) {
| ^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0770`.
1 change: 1 addition & 0 deletions tests/ui/const-generics/issues/issue-71611.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

fn func<A, const F: fn(inner: A)>(outer: A) {
//~^ ERROR: the type of const parameters must not depend on other generic parameters
//[min]~| ERROR: using function pointers as const generic parameters is forbidden
F(outer);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ impl Opcode2 {
pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) {
move |i| match msg_type {
Opcode2::OP2 => unimplemented!(),
//~^ ERROR: could not evaluate constant pattern
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ help: you might be missing a type parameter
LL | pub struct Opcode2<S>(&'a S);
| +++

error: aborting due to 2 previous errors
error: could not evaluate constant pattern
--> $DIR/ice-type-mismatch-when-copying-112824.rs:15:9
|
LL | Opcode2::OP2 => unimplemented!(),
| ^^^^^^^^^^^^

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0261, E0412.
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
}
Loading

0 comments on commit 5019bb6

Please sign in to comment.