diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 2fbc8a3f146a1..f3aece4e1d8aa 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -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 diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 9a353bfe49d0e..c8ab0429ffc70 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -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"); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 430e12ff7b87b..ba7719bbb4e6d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -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 { diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 120e3239d1f1b..02844bcadac6e 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -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?"), + ); } } } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index aea0114167eb9..ceb7480686d90 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -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); diff --git a/tests/ui/self/arbitrary-self-from-method-substs-ice.rs b/tests/ui/self/arbitrary-self-from-method-substs-ice.rs new file mode 100644 index 0000000000000..8bf9f97e0b91d --- /dev/null +++ b/tests/ui/self/arbitrary-self-from-method-substs-ice.rs @@ -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>(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 `::deref` in constant function + } +} + +const FOO: () = { + let foo = Foo(1); + foo.get::<&Foo>(); +}; + +const BAR: [(); { + FOO; + 0 +}] = []; + +fn main() {} diff --git a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr new file mode 100644 index 0000000000000..9e3851f9a6e72 --- /dev/null +++ b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr @@ -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 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 `::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>(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>(self: R) -> u32 { + | ^ + | + = note: see issue #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: Rc`, `self: Arc`, or `self: Pin

` (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`. diff --git a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr index 6fff086a89c2e..4cc69666b8876 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr @@ -9,7 +9,6 @@ LL | fn get>(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: Rc`, `self: Arc`, or `self: Pin

` (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`.