Skip to content

Commit

Permalink
Rollup merge of rust-lang#127202 - oli-obk:do_not_count_errors, r=wes…
Browse files Browse the repository at this point in the history
…leywiser

Remove global error count checks from typeck

Some of these are not reachable anymore, others can now rely on information local to the current typeck run. One check was actually invalid, because it was relying on wfcheck running before typeck, which is not guaranteed in the query system and usually easy to create ICEing examples for via const eval (which runs typeck before wfcheck)
  • Loading branch information
matthiaskrgr authored Jul 2, 2024
2 parents b0d8e78 + 814bfe9 commit 9a4e4e0
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 31 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// else an error would have been flagged by the
// `loops` pass for using break with an expression
// where you are not supposed to.
assert!(expr_opt.is_none() || self.dcx().has_errors().is_some());
assert!(expr_opt.is_none() || self.tainted_by_errors().is_some());
}

// If we encountered a `break`, then (no surprise) it may be possible to break from the
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_hir_typeck/src/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -734,9 +734,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
// struct; however, when EUV is run during typeck, it
// may not. This will generate an error earlier in typeck,
// so we can just ignore it.
if self.cx.tcx().dcx().has_errors().is_none() {
span_bug!(with_expr.span, "with expression doesn't evaluate to a struct");
}
span_bug!(with_expr.span, "with expression doesn't evaluate to a struct");
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1652,7 +1652,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement");

// Hide the outer diverging and `has_errors` flags.
// Hide the outer diverging flags.
let old_diverges = self.diverges.replace(Diverges::Maybe);

match stmt.kind {
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_hir_typeck/src/method/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,9 +510,12 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
.report_mismatched_types(&cause, method_self_ty, self_ty, terr)
.emit();
} else {
error!("{self_ty} was a subtype of {method_self_ty} but now is not?");
// This must already have errored elsewhere.
self.dcx().has_errors().unwrap();
// This has/will have errored in wfcheck, which we cannot depend on from here, as typeck on functions
// may run before wfcheck if the function is used in const eval.
self.dcx().span_delayed_bug(
cause.span(),
format!("{self_ty} was a subtype of {method_self_ty} but now is not?"),
);
}
}
}
Expand Down
25 changes: 3 additions & 22 deletions compiler/rustc_hir_typeck/src/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,28 +219,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
fn fix_index_builtin_expr(&mut self, e: &hir::Expr<'_>) {
if let hir::ExprKind::Index(ref base, ref index, _) = e.kind {
// All valid indexing looks like this; might encounter non-valid indexes at this point.
let base_ty = self.typeck_results.expr_ty_adjusted_opt(base);
if base_ty.is_none() {
// When encountering `return [0][0]` outside of a `fn` body we can encounter a base
// that isn't in the type table. We assume more relevant errors have already been
// emitted. (#64638)
assert!(self.tcx().dcx().has_errors().is_some(), "bad base: `{base:?}`");
}
if let Some(base_ty) = base_ty
&& let ty::Ref(_, base_ty_inner, _) = *base_ty.kind()
{
let index_ty =
self.typeck_results.expr_ty_adjusted_opt(index).unwrap_or_else(|| {
// When encountering `return [0][0]` outside of a `fn` body we would attempt
// to access an nonexistent index. We assume that more relevant errors will
// already have been emitted, so we only gate on this with an ICE if no
// error has been emitted. (#64638)
Ty::new_error_with_message(
self.fcx.tcx,
e.span,
format!("bad index {index:?} for base: `{base:?}`"),
)
});
let base_ty = self.typeck_results.expr_ty_adjusted(base);
if let ty::Ref(_, base_ty_inner, _) = *base_ty.kind() {
let index_ty = self.typeck_results.expr_ty_adjusted(index);
if self.is_builtin_index(e, base_ty_inner, index_ty) {
// Remove the method call record
self.typeck_results.type_dependent_defs_mut().remove(e.hir_id);
Expand Down
29 changes: 29 additions & 0 deletions tests/ui/self/arbitrary-self-from-method-substs-ice.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//! The same as the non-ICE test, but const eval will run typeck of
//! `get` before running wfcheck (as that may in itself trigger const
//! eval again, and thus cause bogus cycles). This used to ICE because
//! we asserted that an error had already been emitted.
use std::ops::Deref;

struct Foo(u32);
impl Foo {
const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
//~^ ERROR: `R` cannot be used as the type of `self`
//~| ERROR destructor of `R` cannot be evaluated at compile-time
self.0
//~^ ERROR cannot borrow here, since the borrowed element may contain interior mutability
//~| ERROR cannot call non-const fn `<R as Deref>::deref` in constant function
}
}

const FOO: () = {
let foo = Foo(1);
foo.get::<&Foo>();
};

const BAR: [(); {
FOO;
0
}] = [];

fn main() {}
46 changes: 46 additions & 0 deletions tests/ui/self/arbitrary-self-from-method-substs-ice.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
--> $DIR/arbitrary-self-from-method-substs-ice.rs:13:9
|
LL | self.0
| ^^^^
|
= note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
= help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error[E0015]: cannot call non-const fn `<R as Deref>::deref` in constant functions
--> $DIR/arbitrary-self-from-method-substs-ice.rs:13:9
|
LL | self.0
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|

error[E0493]: destructor of `R` cannot be evaluated at compile-time
--> $DIR/arbitrary-self-from-method-substs-ice.rs:10:43
|
LL | const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
| ^^^^ the destructor for this type cannot be evaluated in constant functions
...
LL | }
| - value is dropped here

error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
--> $DIR/arbitrary-self-from-method-substs-ice.rs:10:49
|
LL | const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
| ^
|
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
= help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)

error: aborting due to 4 previous errors

Some errors have detailed explanations: E0015, E0493, E0658.
For more information about an error, try `rustc --explain E0015`.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ LL | fn get<R: Deref<Target = Self>>(self: R) -> u32 {
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)

ERROR rustc_hir_typeck::method::confirm Foo was a subtype of &Foo but now is not?
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0658`.

0 comments on commit 9a4e4e0

Please sign in to comment.