From 91535ad0265abbe40733fdd451216efdf28ffd02 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 15 Jan 2024 11:44:56 +0100 Subject: [PATCH 1/5] remove `sub_relations` from infcx, recompute in diagnostics we don't track them when canonicalizing or when freshening, resulting in instable caching in the old solver, and issues when instantiating query responses in the new one. --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 9 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 7 ++ .../src/infer/error_reporting/mod.rs | 3 + .../infer/error_reporting/need_type_info.rs | 43 ++++--- .../infer/error_reporting/sub_relations.rs | 81 +++++++++++++ compiler/rustc_infer/src/infer/mod.rs | 2 +- .../src/infer/relate/generalize.rs | 16 +-- .../rustc_infer/src/infer/type_variable.rs | 106 +----------------- compiler/rustc_infer/src/infer/undo_log.rs | 8 +- .../error_reporting/type_err_ctxt_ext.rs | 4 + .../occurs-check/unused-substs-2.rs | 5 +- .../occurs-check/unused-substs-2.stderr | 6 +- .../occurs-check/unused-substs-5.stderr | 6 +- tests/ui/impl-trait/issues/issue-84073.rs | 2 +- tests/ui/impl-trait/issues/issue-84073.stderr | 13 +-- tests/ui/infinite/infinite-autoderef.rs | 4 +- tests/ui/infinite/infinite-autoderef.stderr | 55 +-------- tests/ui/issues/issue-59494.rs | 2 +- tests/ui/issues/issue-59494.stderr | 19 +--- tests/ui/occurs-check-2.rs | 3 +- tests/ui/occurs-check-2.stderr | 11 +- tests/ui/occurs-check-3.rs | 10 +- tests/ui/occurs-check-3.stderr | 10 +- tests/ui/occurs-check.rs | 5 +- tests/ui/occurs-check.stderr | 13 +-- tests/ui/span/coerce-suggestions.rs | 4 - tests/ui/span/coerce-suggestions.stderr | 13 +-- 27 files changed, 180 insertions(+), 280 deletions(-) create mode 100644 compiler/rustc_infer/src/infer/error_reporting/sub_relations.rs diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 986af2f5c9e6..9303e437a968 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1522,10 +1522,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.next_trait_solver() && let ty::Alias(..) = ty.kind() { - match self + // We need to use a separate variable here as otherwise the temporary for + // `self.fulfillment_cx.borrow_mut()` is alive in the `Err` branch, resulting + // in a reentrant borrow, causing an ICE. + let result = self .at(&self.misc(sp), self.param_env) - .structurally_normalize(ty, &mut **self.fulfillment_cx.borrow_mut()) - { + .structurally_normalize(ty, &mut **self.fulfillment_cx.borrow_mut()); + match result { Ok(normalized_ty) => normalized_ty, Err(errors) => { let guar = self.err_ctxt().report_fulfillment_errors(errors); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index ad4546c09b54..685b1af931e3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -11,6 +11,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer; +use rustc_infer::infer::error_reporting::sub_relations::SubRelations; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; @@ -155,8 +156,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// [`InferCtxt::err_ctxt`]: infer::InferCtxt::err_ctxt pub fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> { + let mut sub_relations = SubRelations::default(); + sub_relations.add_constraints( + self, + self.fulfillment_cx.borrow_mut().pending_obligations().iter().map(|o| o.predicate), + ); TypeErrCtxt { infcx: &self.infcx, + sub_relations: RefCell::new(sub_relations), typeck_results: Some(self.typeck_results.borrow()), fallback_has_occurred: self.fallback_has_occurred.get(), normalize_fn_sig: Box::new(|fn_sig| { diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 505d56cf4917..d40f3f501f58 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -88,6 +88,7 @@ mod note_and_explain; mod suggest; pub(crate) mod need_type_info; +pub mod sub_relations; pub use need_type_info::TypeAnnotationNeeded; pub mod nice_region_error; @@ -123,6 +124,8 @@ fn escape_literal(s: &str) -> String { /// methods which should not be used during the happy path. pub struct TypeErrCtxt<'a, 'tcx> { pub infcx: &'a InferCtxt<'tcx>, + pub sub_relations: std::cell::RefCell, + pub typeck_results: Option>>, pub fallback_has_occurred: bool, diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index af722b206262..896d17478504 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -502,7 +502,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { parent_name, }); - let args = if self.infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) + let args = if self.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(generics_def_id) { "Vec<_>".to_string() @@ -710,7 +710,7 @@ struct InsertableGenericArgs<'tcx> { /// While doing so, the currently best spot is stored in `infer_source`. /// For details on how we rank spots, see [Self::source_cost] struct FindInferSourceVisitor<'a, 'tcx> { - infcx: &'a InferCtxt<'tcx>, + tecx: &'a TypeErrCtxt<'a, 'tcx>, typeck_results: &'a TypeckResults<'tcx>, target: GenericArg<'tcx>, @@ -722,12 +722,12 @@ struct FindInferSourceVisitor<'a, 'tcx> { impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { fn new( - infcx: &'a InferCtxt<'tcx>, + tecx: &'a TypeErrCtxt<'a, 'tcx>, typeck_results: &'a TypeckResults<'tcx>, target: GenericArg<'tcx>, ) -> Self { FindInferSourceVisitor { - infcx, + tecx, typeck_results, target, @@ -778,7 +778,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { } // The sources are listed in order of preference here. - let tcx = self.infcx.tcx; + let tcx = self.tecx.tcx; let ctx = CostCtxt { tcx }; match source.kind { InferSourceKind::LetBinding { ty, .. } => ctx.ty_cost(ty), @@ -829,12 +829,12 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { fn node_args_opt(&self, hir_id: HirId) -> Option> { let args = self.typeck_results.node_args_opt(hir_id); - self.infcx.resolve_vars_if_possible(args) + self.tecx.resolve_vars_if_possible(args) } fn opt_node_type(&self, hir_id: HirId) -> Option> { let ty = self.typeck_results.node_type_opt(hir_id); - self.infcx.resolve_vars_if_possible(ty) + self.tecx.resolve_vars_if_possible(ty) } // Check whether this generic argument is the inference variable we @@ -849,7 +849,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { use ty::{Infer, TyVar}; match (inner_ty.kind(), target_ty.kind()) { (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => { - self.infcx.inner.borrow_mut().type_variables().sub_unified(a_vid, b_vid) + self.tecx.sub_relations.borrow_mut().unified(self.tecx, a_vid, b_vid) } _ => false, } @@ -857,12 +857,9 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { (GenericArgKind::Const(inner_ct), GenericArgKind::Const(target_ct)) => { use ty::InferConst::*; match (inner_ct.kind(), target_ct.kind()) { - (ty::ConstKind::Infer(Var(a_vid)), ty::ConstKind::Infer(Var(b_vid))) => self - .infcx - .inner - .borrow_mut() - .const_unification_table() - .unioned(a_vid, b_vid), + (ty::ConstKind::Infer(Var(a_vid)), ty::ConstKind::Infer(Var(b_vid))) => { + self.tecx.inner.borrow_mut().const_unification_table().unioned(a_vid, b_vid) + } _ => false, } } @@ -917,7 +914,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { &self, expr: &'tcx hir::Expr<'tcx>, ) -> Box> + 'a> { - let tcx = self.infcx.tcx; + let tcx = self.tecx.tcx; match expr.kind { hir::ExprKind::Path(ref path) => { if let Some(args) = self.node_args_opt(expr.hir_id) { @@ -980,7 +977,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { path: &'tcx hir::Path<'tcx>, args: GenericArgsRef<'tcx>, ) -> impl Iterator> + 'a { - let tcx = self.infcx.tcx; + let tcx = self.tecx.tcx; let have_turbofish = path.segments.iter().any(|segment| { segment.args.is_some_and(|args| args.args.iter().any(|arg| arg.is_ty_or_const())) }); @@ -1034,7 +1031,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { args: GenericArgsRef<'tcx>, qpath: &'tcx hir::QPath<'tcx>, ) -> Box> + 'a> { - let tcx = self.infcx.tcx; + let tcx = self.tecx.tcx; match qpath { hir::QPath::Resolved(_self_ty, path) => { Box::new(self.resolved_path_inferred_arg_iter(path, args)) @@ -1107,7 +1104,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; fn nested_visit_map(&mut self) -> Self::Map { - self.infcx.tcx.hir() + self.tecx.tcx.hir() } fn visit_local(&mut self, local: &'tcx Local<'tcx>) { @@ -1163,7 +1160,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { - let tcx = self.infcx.tcx; + let tcx = self.tecx.tcx; match expr.kind { // When encountering `func(arg)` first look into `arg` and then `func`, // as `arg` is "more specific". @@ -1194,7 +1191,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { if generics.parent.is_none() && generics.has_self { argument_index += 1; } - let args = self.infcx.resolve_vars_if_possible(args); + let args = self.tecx.resolve_vars_if_possible(args); let generic_args = &generics.own_args_no_defaults(tcx, args)[generics.own_counts().lifetimes..]; let span = match expr.kind { @@ -1224,7 +1221,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { { let output = args.as_closure().sig().output().skip_binder(); if self.generic_arg_contains_target(output.into()) { - let body = self.infcx.tcx.hir().body(body); + let body = self.tecx.tcx.hir().body(body); let should_wrap_expr = if matches!(body.value.kind, ExprKind::Block(..)) { None } else { @@ -1252,12 +1249,12 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { && let Some(args) = self.node_args_opt(expr.hir_id) && args.iter().any(|arg| self.generic_arg_contains_target(arg)) && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) - && self.infcx.tcx.trait_of_item(def_id).is_some() + && self.tecx.tcx.trait_of_item(def_id).is_some() && !has_impl_trait(def_id) { let successor = method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo())); - let args = self.infcx.resolve_vars_if_possible(args); + let args = self.tecx.resolve_vars_if_possible(args); self.update_infer_source(InferSource { span: path.ident.span, kind: InferSourceKind::FullyQualifiedMethodCall { diff --git a/compiler/rustc_infer/src/infer/error_reporting/sub_relations.rs b/compiler/rustc_infer/src/infer/error_reporting/sub_relations.rs new file mode 100644 index 000000000000..ef26a8ff7b86 --- /dev/null +++ b/compiler/rustc_infer/src/infer/error_reporting/sub_relations.rs @@ -0,0 +1,81 @@ +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::undo_log::NoUndo; +use rustc_data_structures::unify as ut; +use rustc_middle::ty; + +use crate::infer::InferCtxt; + +#[derive(Debug, Copy, Clone, PartialEq)] +struct SubId(u32); +impl ut::UnifyKey for SubId { + type Value = (); + #[inline] + fn index(&self) -> u32 { + self.0 + } + #[inline] + fn from_index(i: u32) -> SubId { + SubId(i) + } + fn tag() -> &'static str { + "SubId" + } +} + +/// When reporting ambiguity errors, we sometimes want to +/// treat all inference vars which are subtypes of each +/// others as if they are equal. For this case we compute +/// the transitive closure of our subtype obligations here. +/// +/// E.g. when encountering ambiguity errors, we want to suggest +/// specifying some method argument or to add a type annotation +/// to a local variable. Because subtyping cannot change the +/// shape of a type, it's fine if the cause of the ambiguity error +/// is only related to the suggested variable via subtyping. +/// +/// Even for something like `let x = returns_arg(); x.method();` the +/// type of `x` is only a supertype of the argument of `returns_arg`. We +/// still want to suggest specifying the type of the argument. +#[derive(Default)] +pub struct SubRelations { + map: FxHashMap, + table: ut::UnificationTableStorage, +} + +impl SubRelations { + fn get_id<'tcx>(&mut self, infcx: &InferCtxt<'tcx>, vid: ty::TyVid) -> SubId { + let root_vid = infcx.root_var(vid); + *self.map.entry(root_vid).or_insert_with(|| self.table.with_log(&mut NoUndo).new_key(())) + } + + pub fn add_constraints<'tcx>( + &mut self, + infcx: &InferCtxt<'tcx>, + obls: impl IntoIterator>, + ) { + for p in obls { + let (a, b) = match p.kind().skip_binder() { + ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => { + (a, b) + } + ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => (a, b), + _ => continue, + }; + + match (a.kind(), b.kind()) { + (&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => { + let a = self.get_id(infcx, a_vid); + let b = self.get_id(infcx, b_vid); + self.table.with_log(&mut NoUndo).unify_var_var(a, b).unwrap(); + } + _ => continue, + } + } + } + + pub fn unified<'tcx>(&mut self, infcx: &InferCtxt<'tcx>, a: ty::TyVid, b: ty::TyVid) -> bool { + let a = self.get_id(infcx, a); + let b = self.get_id(infcx, b); + self.table.with_log(&mut NoUndo).unioned(a, b) + } +} diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 8fc71671b271..8b5710ee9edc 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -762,6 +762,7 @@ impl<'tcx> InferCtxt<'tcx> { pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> { TypeErrCtxt { infcx: self, + sub_relations: Default::default(), typeck_results: None, fallback_has_occurred: false, normalize_fn_sig: Box::new(|fn_sig| fn_sig), @@ -1029,7 +1030,6 @@ impl<'tcx> InferCtxt<'tcx> { let r_b = self.shallow_resolve(predicate.skip_binder().b); match (r_a.kind(), r_b.kind()) { (&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => { - self.inner.borrow_mut().type_variables().sub(a_vid, b_vid); return Err((a_vid, b_vid)); } _ => {} diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 90f10a0eba9e..c4c9ddb1ad8e 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -217,10 +217,9 @@ impl<'tcx> InferCtxt<'tcx> { ) -> RelateResult<'tcx, Generalization> { assert!(!source_term.has_escaping_bound_vars()); let (for_universe, root_vid) = match target_vid.into() { - ty::TermVid::Ty(ty_vid) => ( - self.probe_ty_var(ty_vid).unwrap_err(), - ty::TermVid::Ty(self.inner.borrow_mut().type_variables().sub_root_var(ty_vid)), - ), + ty::TermVid::Ty(ty_vid) => { + (self.probe_ty_var(ty_vid).unwrap_err(), ty::TermVid::Ty(self.root_var(ty_vid))) + } ty::TermVid::Const(ct_vid) => ( self.probe_const_var(ct_vid).unwrap_err(), ty::TermVid::Const( @@ -424,9 +423,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> { ty::Infer(ty::TyVar(vid)) => { let mut inner = self.infcx.inner.borrow_mut(); let vid = inner.type_variables().root_var(vid); - let sub_vid = inner.type_variables().sub_root_var(vid); - - if ty::TermVid::Ty(sub_vid) == self.root_vid { + if ty::TermVid::Ty(vid) == self.root_vid { // If sub-roots are equal, then `root_vid` and // `vid` are related via subtyping. Err(self.cyclic_term_error()) @@ -461,11 +458,6 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> { let new_var_id = inner.type_variables().new_var(self.for_universe, origin); let u = Ty::new_var(self.tcx(), new_var_id); - - // Record that we replaced `vid` with `new_var_id` as part of a generalization - // operation. This is needed to detect cyclic types. To see why, see the - // docs in the `type_variables` module. - inner.type_variables().sub(vid, new_var_id); debug!("replacing original vid={:?} with new={:?}", vid, u); Ok(u) } diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index 8b81eac87390..3630b0f439ff 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -1,3 +1,4 @@ +use rustc_data_structures::undo_log::Rollback; use rustc_hir::def_id::DefId; use rustc_index::IndexVec; use rustc_middle::ty::{self, Ty, TyVid}; @@ -12,35 +13,9 @@ use std::cmp; use std::marker::PhantomData; use std::ops::Range; -use rustc_data_structures::undo_log::Rollback; - -/// Represents a single undo-able action that affects a type inference variable. -#[derive(Clone)] -pub(crate) enum UndoLog<'tcx> { - EqRelation(sv::UndoLog>>), - SubRelation(sv::UndoLog>), -} - -/// Convert from a specific kind of undo to the more general UndoLog -impl<'tcx> From>>> for UndoLog<'tcx> { - fn from(l: sv::UndoLog>>) -> Self { - UndoLog::EqRelation(l) - } -} - -/// Convert from a specific kind of undo to the more general UndoLog -impl<'tcx> From>> for UndoLog<'tcx> { - fn from(l: sv::UndoLog>) -> Self { - UndoLog::SubRelation(l) - } -} - -impl<'tcx> Rollback> for TypeVariableStorage<'tcx> { - fn reverse(&mut self, undo: UndoLog<'tcx>) { - match undo { - UndoLog::EqRelation(undo) => self.eq_relations.reverse(undo), - UndoLog::SubRelation(undo) => self.sub_relations.reverse(undo), - } +impl<'tcx> Rollback>>> for TypeVariableStorage<'tcx> { + fn reverse(&mut self, undo: sv::UndoLog>>) { + self.eq_relations.reverse(undo) } } @@ -52,41 +27,6 @@ pub struct TypeVariableStorage<'tcx> { /// constraint `?X == ?Y`. This table also stores, for each key, /// the known value. eq_relations: ut::UnificationTableStorage>, - - /// Two variables are unified in `sub_relations` when we have a - /// constraint `?X <: ?Y` *or* a constraint `?Y <: ?X`. This second - /// table exists only to help with the occurs check. In particular, - /// we want to report constraints like these as an occurs check - /// violation: - /// ``` text - /// ?1 <: ?3 - /// Box <: ?1 - /// ``` - /// Without this second table, what would happen in a case like - /// this is that we would instantiate `?1` with a generalized - /// type like `Box`. We would then relate `Box <: Box` - /// and infer that `?3 <: ?6`. Next, since `?1` was instantiated, - /// we would process `?1 <: ?3`, generalize `?1 = Box` to `Box`, - /// and instantiate `?3` with `Box`. Finally, we would relate - /// `?6 <: ?9`. But now that we instantiated `?3`, we can process - /// `?3 <: ?6`, which gives us `Box <: ?6`... and the cycle - /// continues. (This is `occurs-check-2.rs`.) - /// - /// What prevents this cycle is that when we generalize - /// `Box` to `Box`, we also sub-unify `?3` and `?6` - /// (in the generalizer). When we then process `Box <: ?3`, - /// the occurs check then fails because `?6` and `?3` are sub-unified, - /// and hence generalization fails. - /// - /// This is reasonable because, in Rust, subtypes have the same - /// "skeleton" and hence there is no possible type such that - /// (e.g.) `Box <: ?3` for any `?3`. - /// - /// In practice, we sometimes sub-unify variables in other spots, such - /// as when processing subtype predicates. This is not necessary but is - /// done to aid diagnostics, as it allows us to be more effective when - /// we guide the user towards where they should insert type hints. - sub_relations: ut::UnificationTableStorage, } pub struct TypeVariableTable<'a, 'tcx> { @@ -158,7 +98,6 @@ impl<'tcx> TypeVariableStorage<'tcx> { TypeVariableStorage { values: Default::default(), eq_relations: ut::UnificationTableStorage::new(), - sub_relations: ut::UnificationTableStorage::new(), } } @@ -197,16 +136,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { debug_assert!(self.probe(a).is_unknown()); debug_assert!(self.probe(b).is_unknown()); self.eq_relations().union(a, b); - self.sub_relations().union(a, b); - } - - /// Records that `a <: b`, depending on `dir`. - /// - /// Precondition: neither `a` nor `b` are known. - pub fn sub(&mut self, a: ty::TyVid, b: ty::TyVid) { - debug_assert!(self.probe(a).is_unknown()); - debug_assert!(self.probe(b).is_unknown()); - self.sub_relations().union(a, b); } /// Instantiates `vid` with the type `ty`. @@ -240,10 +169,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { origin: TypeVariableOrigin, ) -> ty::TyVid { let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe }); - - let sub_key = self.sub_relations().new_key(()); - debug_assert_eq!(eq_key.vid, sub_key); - let index = self.storage.values.push(TypeVariableData { origin }); debug_assert_eq!(eq_key.vid, index); @@ -266,24 +191,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { self.eq_relations().find(vid).vid } - /// Returns the "root" variable of `vid` in the `sub_relations` - /// equivalence table. All type variables that have been are - /// related via equality or subtyping will yield the same root - /// variable (per the union-find algorithm), so `sub_root_var(a) - /// == sub_root_var(b)` implies that: - /// ```text - /// exists X. (a <: X || X <: a) && (b <: X || X <: b) - /// ``` - pub fn sub_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid { - self.sub_relations().find(vid) - } - - /// Returns `true` if `a` and `b` have same "sub-root" (i.e., exists some - /// type X such that `forall i in {a, b}. (i <: X || X <: i)`. - pub fn sub_unified(&mut self, a: ty::TyVid, b: ty::TyVid) -> bool { - self.sub_root_var(a) == self.sub_root_var(b) - } - /// Retrieves the type to which `vid` has been instantiated, if /// any. pub fn probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> { @@ -314,11 +221,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { self.storage.eq_relations.with_log(self.undo_log) } - #[inline] - fn sub_relations(&mut self) -> super::UnificationTable<'_, 'tcx, ty::TyVid> { - self.storage.sub_relations.with_log(self.undo_log) - } - /// Returns a range of the type variables created during the snapshot. pub fn vars_since_snapshot( &mut self, diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs index be02452d89fb..829b0a73a0df 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -20,7 +20,7 @@ pub struct Snapshot<'tcx> { #[derive(Clone)] pub(crate) enum UndoLog<'tcx> { OpaqueTypes(OpaqueTypeKey<'tcx>, Option>), - TypeVariables(type_variable::UndoLog<'tcx>), + TypeVariables(sv::UndoLog>>), ConstUnificationTable(sv::UndoLog>>), IntUnificationTable(sv::UndoLog>), FloatUnificationTable(sv::UndoLog>), @@ -46,17 +46,13 @@ macro_rules! impl_from { // Upcast from a single kind of "undoable action" to the general enum impl_from! { RegionConstraintCollector(region_constraints::UndoLog<'tcx>), - TypeVariables(type_variable::UndoLog<'tcx>), TypeVariables(sv::UndoLog>>), - TypeVariables(sv::UndoLog>), - IntUnificationTable(sv::UndoLog>), - FloatUnificationTable(sv::UndoLog>), - EffectUnificationTable(sv::UndoLog>>), ConstUnificationTable(sv::UndoLog>>), + EffectUnificationTable(sv::UndoLog>>), RegionUnificationTable(sv::UndoLog>>), ProjectionCache(traits::UndoLog<'tcx>), diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 7186b96b40d0..be4c6b4d9d12 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -63,6 +63,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &self, mut errors: Vec>, ) -> ErrorGuaranteed { + self.sub_relations + .borrow_mut() + .add_constraints(self, errors.iter().map(|e| e.obligation.predicate)); + #[derive(Debug)] struct ErrorDescriptor<'tcx> { predicate: ty::Predicate<'tcx>, diff --git a/tests/ui/const-generics/occurs-check/unused-substs-2.rs b/tests/ui/const-generics/occurs-check/unused-substs-2.rs index 84e24d1a3f5f..5bdd3e39806e 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-2.rs +++ b/tests/ui/const-generics/occurs-check/unused-substs-2.rs @@ -20,9 +20,10 @@ impl Bind for Foo<{ 6 + 1 }> { fn main() { let (mut t, foo) = Foo::bind(); + //~^ ERROR mismatched types + //~| NOTE cyclic type + // `t` is `ty::Infer(TyVar(?1t))` // `foo` contains `ty::Infer(TyVar(?1t))` in its substs t = foo; - //~^ ERROR mismatched types - //~| NOTE cyclic type } diff --git a/tests/ui/const-generics/occurs-check/unused-substs-2.stderr b/tests/ui/const-generics/occurs-check/unused-substs-2.stderr index 4b1b9f20559e..a2c4dec47243 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-2.stderr +++ b/tests/ui/const-generics/occurs-check/unused-substs-2.stderr @@ -1,8 +1,8 @@ error[E0308]: mismatched types - --> $DIR/unused-substs-2.rs:25:9 + --> $DIR/unused-substs-2.rs:22:24 | -LL | t = foo; - | ^^^ cyclic type of infinite size +LL | let (mut t, foo) = Foo::bind(); + | ^^^^^^^^^^^ cyclic type of infinite size error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/occurs-check/unused-substs-5.stderr b/tests/ui/const-generics/occurs-check/unused-substs-5.stderr index 1b3a54923284..46230d455b27 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-5.stderr +++ b/tests/ui/const-generics/occurs-check/unused-substs-5.stderr @@ -1,10 +1,8 @@ error[E0308]: mismatched types - --> $DIR/unused-substs-5.rs:15:9 + --> $DIR/unused-substs-5.rs:15:19 | LL | x = q::<_, N>(x); - | ^^^^^^^^^^^^- help: try using a conversion method: `.to_vec()` - | | - | cyclic type of infinite size + | ^ cyclic type of infinite size error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-84073.rs b/tests/ui/impl-trait/issues/issue-84073.rs index 49a34ccfa3b4..60f98a7c7b53 100644 --- a/tests/ui/impl-trait/issues/issue-84073.rs +++ b/tests/ui/impl-trait/issues/issue-84073.rs @@ -29,5 +29,5 @@ where } fn main() { - Race::new(|race| race.when()); //~ ERROR type annotations needed + Race::new(|race| race.when()); //~ ERROR overflow evaluating the requirement `_ <: Option<_>` } diff --git a/tests/ui/impl-trait/issues/issue-84073.stderr b/tests/ui/impl-trait/issues/issue-84073.stderr index d03e458aeb82..b9039211db63 100644 --- a/tests/ui/impl-trait/issues/issue-84073.stderr +++ b/tests/ui/impl-trait/issues/issue-84073.stderr @@ -1,14 +1,9 @@ -error[E0282]: type annotations needed for `RaceBuilder>` - --> $DIR/issue-84073.rs:32:16 +error[E0275]: overflow evaluating the requirement `_ <: Option<_>` + --> $DIR/issue-84073.rs:32:22 | LL | Race::new(|race| race.when()); - | ^^^^ ---- type must be known at this point - | -help: consider giving this closure parameter an explicit type, where the type for type parameter `T` is specified - | -LL | Race::new(|race: RaceBuilder>| race.when()); - | ++++++++++++++++++++++++++ + | ^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/infinite/infinite-autoderef.rs b/tests/ui/infinite/infinite-autoderef.rs index d6956e694570..cf5c9fe5678c 100644 --- a/tests/ui/infinite/infinite-autoderef.rs +++ b/tests/ui/infinite/infinite-autoderef.rs @@ -1,6 +1,3 @@ -//@ error-pattern: reached the recursion limit while auto-dereferencing -//@ compile-flags: -Zdeduplicate-diagnostics=yes - use std::ops::Deref; struct Foo; @@ -17,6 +14,7 @@ pub fn main() { let mut x; loop { x = Box::new(x); + //~^ ERROR overflow evaluating the requirement `Box<_> <: _` x.foo; x.bar(); } diff --git a/tests/ui/infinite/infinite-autoderef.stderr b/tests/ui/infinite/infinite-autoderef.stderr index 51b61e3a66bb..24be1a11373c 100644 --- a/tests/ui/infinite/infinite-autoderef.stderr +++ b/tests/ui/infinite/infinite-autoderef.stderr @@ -1,54 +1,9 @@ -error[E0308]: mismatched types - --> $DIR/infinite-autoderef.rs:19:13 +error[E0275]: overflow evaluating the requirement `Box<_> <: _` + --> $DIR/infinite-autoderef.rs:16:13 | LL | x = Box::new(x); - | ^^^^^^^^^^^ cyclic type of infinite size - | -help: consider unboxing the value - | -LL | x = *Box::new(x); - | + + | ^^^^^^^^^^^ -error[E0055]: reached the recursion limit while auto-dereferencing `Foo` - --> $DIR/infinite-autoderef.rs:24:5 - | -LL | Foo.foo; - | ^^^^^^^ deref recursion limit reached - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`) +error: aborting due to 1 previous error -error[E0055]: reached the recursion limit while auto-dereferencing `Foo` - --> $DIR/infinite-autoderef.rs:24:9 - | -LL | Foo.foo; - | ^^^ deref recursion limit reached - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`) - -error[E0609]: no field `foo` on type `Foo` - --> $DIR/infinite-autoderef.rs:24:9 - | -LL | Foo.foo; - | ^^^ unknown field - -error[E0055]: reached the recursion limit while auto-dereferencing `Foo` - --> $DIR/infinite-autoderef.rs:25:9 - | -LL | Foo.bar(); - | ^^^ deref recursion limit reached - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`) - -error[E0599]: no method named `bar` found for struct `Foo` in the current scope - --> $DIR/infinite-autoderef.rs:25:9 - | -LL | struct Foo; - | ---------- method `bar` not found for this struct -... -LL | Foo.bar(); - | ^^^ method not found in `Foo` - -error: aborting due to 6 previous errors - -Some errors have detailed explanations: E0055, E0308, E0599, E0609. -For more information about an error, try `rustc --explain E0055`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/issues/issue-59494.rs b/tests/ui/issues/issue-59494.rs index 8dcdd88c618c..b4d50bd4ce79 100644 --- a/tests/ui/issues/issue-59494.rs +++ b/tests/ui/issues/issue-59494.rs @@ -18,6 +18,6 @@ fn main() { let f = |(_, _)| {}; let g = |(a, _)| a; let t7 = |env| |a| |b| t7p(f, g)(((env, a), b)); + //~^ ERROR mismatched types let t8 = t8n(t7, t7p(f, g)); - //~^ ERROR: expected a `Fn(_)` closure, found `impl Fn(((_, _), _))` [E0277] } diff --git a/tests/ui/issues/issue-59494.stderr b/tests/ui/issues/issue-59494.stderr index 960de1be299e..33d3e48c1aac 100644 --- a/tests/ui/issues/issue-59494.stderr +++ b/tests/ui/issues/issue-59494.stderr @@ -1,18 +1,9 @@ -error[E0277]: expected a `Fn(_)` closure, found `impl Fn(((_, _), _))` - --> $DIR/issue-59494.rs:21:22 +error[E0308]: mismatched types + --> $DIR/issue-59494.rs:20:40 | -LL | let t8 = t8n(t7, t7p(f, g)); - | --- ^^^^^^^^^ expected an `Fn(_)` closure, found `impl Fn(((_, _), _))` - | | - | required by a bound introduced by this call - | - = help: the trait `Fn<(_,)>` is not implemented for `impl Fn(((_, _), _))` -note: required by a bound in `t8n` - --> $DIR/issue-59494.rs:5:45 - | -LL | fn t8n(f: impl Fn(A) -> B, g: impl Fn(A) -> C) -> impl Fn(A) -> (B, C) - | ^^^^^^^^^^ required by this bound in `t8n` +LL | let t7 = |env| |a| |b| t7p(f, g)(((env, a), b)); + | ^^^ cyclic type of infinite size error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/occurs-check-2.rs b/tests/ui/occurs-check-2.rs index f36682a3dd82..6cdb757d65bc 100644 --- a/tests/ui/occurs-check-2.rs +++ b/tests/ui/occurs-check-2.rs @@ -5,6 +5,5 @@ fn main() { g = f; f = Box::new(g); - //~^ ERROR mismatched types - //~| cyclic type of infinite size + //~^ ERROR overflow evaluating the requirement `Box<_> <: _` } diff --git a/tests/ui/occurs-check-2.stderr b/tests/ui/occurs-check-2.stderr index 7b6fb9fafa20..acc474319b05 100644 --- a/tests/ui/occurs-check-2.stderr +++ b/tests/ui/occurs-check-2.stderr @@ -1,14 +1,9 @@ -error[E0308]: mismatched types +error[E0275]: overflow evaluating the requirement `Box<_> <: _` --> $DIR/occurs-check-2.rs:7:9 | LL | f = Box::new(g); - | ^^^^^^^^^^^ cyclic type of infinite size - | -help: consider unboxing the value - | -LL | f = *Box::new(g); - | + + | ^^^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/occurs-check-3.rs b/tests/ui/occurs-check-3.rs index 9c04204010b7..cdf8dc3bd160 100644 --- a/tests/ui/occurs-check-3.rs +++ b/tests/ui/occurs-check-3.rs @@ -1,5 +1,11 @@ // From Issue #778 enum Clam { A(T) } -fn main() { let c; c = Clam::A(c); match c { Clam::A::(_) => { } } } -//~^ ERROR mismatched types +fn main() { + let c; + c = Clam::A(c); + //~^ ERROR overflow evaluating the requirement `Clam<_> <: _` + match c { + Clam::A::(_) => { } + } +} diff --git a/tests/ui/occurs-check-3.stderr b/tests/ui/occurs-check-3.stderr index 675133b6d50b..7bc28e61d9f9 100644 --- a/tests/ui/occurs-check-3.stderr +++ b/tests/ui/occurs-check-3.stderr @@ -1,9 +1,9 @@ -error[E0308]: mismatched types - --> $DIR/occurs-check-3.rs:4:24 +error[E0275]: overflow evaluating the requirement `Clam<_> <: _` + --> $DIR/occurs-check-3.rs:6:9 | -LL | fn main() { let c; c = Clam::A(c); match c { Clam::A::(_) => { } } } - | ^^^^^^^^^^ cyclic type of infinite size +LL | c = Clam::A(c); + | ^^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/occurs-check.rs b/tests/ui/occurs-check.rs index aec52d839766..3fae3ff1238e 100644 --- a/tests/ui/occurs-check.rs +++ b/tests/ui/occurs-check.rs @@ -1,8 +1,5 @@ fn main() { - let f; - f = Box::new(f); - //~^ ERROR mismatched types - //~| cyclic type of infinite size + //~^ ERROR overflow evaluating the requirement `Box<_> <: _` } diff --git a/tests/ui/occurs-check.stderr b/tests/ui/occurs-check.stderr index 1cb6b32cb233..3f61d8fd08d1 100644 --- a/tests/ui/occurs-check.stderr +++ b/tests/ui/occurs-check.stderr @@ -1,14 +1,9 @@ -error[E0308]: mismatched types - --> $DIR/occurs-check.rs:5:9 +error[E0275]: overflow evaluating the requirement `Box<_> <: _` + --> $DIR/occurs-check.rs:3:9 | LL | f = Box::new(f); - | ^^^^^^^^^^^ cyclic type of infinite size - | -help: consider unboxing the value - | -LL | f = *Box::new(f); - | + + | ^^^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/span/coerce-suggestions.rs b/tests/ui/span/coerce-suggestions.rs index 7920ae0b26cc..13331a016fcf 100644 --- a/tests/ui/span/coerce-suggestions.rs +++ b/tests/ui/span/coerce-suggestions.rs @@ -13,10 +13,6 @@ fn main() { //~^ ERROR E0308 test2(&y); //~^ ERROR E0308 - let f; - f = Box::new(f); - //~^ ERROR E0308 - let s = &mut String::new(); s = format!("foo"); //~^ ERROR E0308 diff --git a/tests/ui/span/coerce-suggestions.stderr b/tests/ui/span/coerce-suggestions.stderr index ff840b781f07..77b01ee08b79 100644 --- a/tests/ui/span/coerce-suggestions.stderr +++ b/tests/ui/span/coerce-suggestions.stderr @@ -54,22 +54,11 @@ LL | fn test2(_x: &mut i32) {} error[E0308]: mismatched types --> $DIR/coerce-suggestions.rs:17:9 | -LL | f = Box::new(f); - | ^^^^^^^^^^^ cyclic type of infinite size - | -help: consider unboxing the value - | -LL | f = *Box::new(f); - | + - -error[E0308]: mismatched types - --> $DIR/coerce-suggestions.rs:21:9 - | LL | s = format!("foo"); | ^^^^^^^^^^^^^^ expected `&mut String`, found `String` | = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0308`. From f392a870e9dffc629587c2e53b0e0b0e90410d84 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 15 Jan 2024 11:47:53 +0100 Subject: [PATCH 2/5] freshen: resolve root vars Without doing so we use the same candidate cache entry for `?0: Trait` and `?0: Trait`. These goals are different and we must not use the same entry for them. --- compiler/rustc_infer/src/infer/freshen.rs | 134 +++++++++--------- .../src/traits/select/mod.rs | 25 +--- tests/ui/impl-trait/issues/issue-62742.rs | 2 + tests/ui/impl-trait/issues/issue-62742.stderr | 37 ++++- 4 files changed, 102 insertions(+), 96 deletions(-) diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 2d5fa1b5c700..ef9c407acef5 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -56,49 +56,46 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { } } - fn freshen_ty(&mut self, opt_ty: Option>, key: ty::InferTy, mk_fresh: F) -> Ty<'tcx> + fn freshen_ty(&mut self, input: Result, ty::InferTy>, mk_fresh: F) -> Ty<'tcx> where F: FnOnce(u32) -> Ty<'tcx>, { - if let Some(ty) = opt_ty { - return ty.fold_with(self); - } - - match self.ty_freshen_map.entry(key) { - Entry::Occupied(entry) => *entry.get(), - Entry::Vacant(entry) => { - let index = self.ty_freshen_count; - self.ty_freshen_count += 1; - let t = mk_fresh(index); - entry.insert(t); - t - } + match input { + Ok(ty) => ty.fold_with(self), + Err(key) => match self.ty_freshen_map.entry(key) { + Entry::Occupied(entry) => *entry.get(), + Entry::Vacant(entry) => { + let index = self.ty_freshen_count; + self.ty_freshen_count += 1; + let t = mk_fresh(index); + entry.insert(t); + t + } + }, } } fn freshen_const( &mut self, - opt_ct: Option>, - key: ty::InferConst, + input: Result, ty::InferConst>, freshener: F, ty: Ty<'tcx>, ) -> ty::Const<'tcx> where F: FnOnce(u32) -> ty::InferConst, { - if let Some(ct) = opt_ct { - return ct.fold_with(self); - } - - match self.const_freshen_map.entry(key) { - Entry::Occupied(entry) => *entry.get(), - Entry::Vacant(entry) => { - let index = self.const_freshen_count; - self.const_freshen_count += 1; - let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index), ty); - entry.insert(ct); - ct - } + match input { + Ok(ct) => ct.fold_with(self), + Err(key) => match self.const_freshen_map.entry(key) { + Entry::Occupied(entry) => *entry.get(), + Entry::Vacant(entry) => { + let index = self.const_freshen_count; + self.const_freshen_count += 1; + let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index), ty); + entry.insert(ct); + ct + } + }, } } } @@ -146,19 +143,22 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { match ct.kind() { ty::ConstKind::Infer(ty::InferConst::Var(v)) => { - let opt_ct = - self.infcx.inner.borrow_mut().const_unification_table().probe_value(v).known(); - self.freshen_const(opt_ct, ty::InferConst::Var(v), ty::InferConst::Fresh, ct.ty()) + let mut inner = self.infcx.inner.borrow_mut(); + let input = + inner.const_unification_table().probe_value(v).known().ok_or_else(|| { + ty::InferConst::Var(inner.const_unification_table().find(v).vid) + }); + drop(inner); + self.freshen_const(input, ty::InferConst::Fresh, ct.ty()) } ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => { - let opt_ct = - self.infcx.inner.borrow_mut().effect_unification_table().probe_value(v).known(); - self.freshen_const( - opt_ct, - ty::InferConst::EffectVar(v), - ty::InferConst::Fresh, - ct.ty(), - ) + let mut inner = self.infcx.inner.borrow_mut(); + let input = + inner.effect_unification_table().probe_value(v).known().ok_or_else(|| { + ty::InferConst::EffectVar(inner.effect_unification_table().find(v).vid) + }); + drop(inner); + self.freshen_const(input, ty::InferConst::Fresh, ct.ty()) } ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => { if i >= self.const_freshen_count { @@ -191,35 +191,37 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { fn fold_infer_ty(&mut self, v: ty::InferTy) -> Option> { match v { ty::TyVar(v) => { - let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known(); - Some(self.freshen_ty(opt_ty, ty::TyVar(v), |n| Ty::new_fresh(self.infcx.tcx, n))) + let mut inner = self.infcx.inner.borrow_mut(); + let input = inner + .type_variables() + .probe(v) + .known() + .ok_or_else(|| ty::TyVar(inner.type_variables().root_var(v))); + drop(inner); + Some(self.freshen_ty(input, |n| Ty::new_fresh(self.infcx.tcx, n))) } - ty::IntVar(v) => Some( - self.freshen_ty( - self.infcx - .inner - .borrow_mut() - .int_unification_table() - .probe_value(v) - .map(|v| v.to_type(self.infcx.tcx)), - ty::IntVar(v), - |n| Ty::new_fresh_int(self.infcx.tcx, n), - ), - ), + ty::IntVar(v) => { + let mut inner = self.infcx.inner.borrow_mut(); + let input = inner + .int_unification_table() + .probe_value(v) + .map(|v| v.to_type(self.infcx.tcx)) + .ok_or_else(|| ty::IntVar(inner.int_unification_table().find(v))); + drop(inner); + Some(self.freshen_ty(input, |n| Ty::new_fresh_int(self.infcx.tcx, n))) + } - ty::FloatVar(v) => Some( - self.freshen_ty( - self.infcx - .inner - .borrow_mut() - .float_unification_table() - .probe_value(v) - .map(|v| v.to_type(self.infcx.tcx)), - ty::FloatVar(v), - |n| Ty::new_fresh_float(self.infcx.tcx, n), - ), - ), + ty::FloatVar(v) => { + let mut inner = self.infcx.inner.borrow_mut(); + let input = inner + .float_unification_table() + .probe_value(v) + .map(|v| v.to_type(self.infcx.tcx)) + .ok_or_else(|| ty::FloatVar(inner.float_unification_table().find(v))); + drop(inner); + Some(self.freshen_ty(input, |n| Ty::new_fresh_float(self.infcx.tcx, n))) + } ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct) => { if ct >= self.ty_freshen_count { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 1146f869fc16..a4499d438c1b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -40,7 +40,6 @@ use rustc_middle::dep_graph::DepNodeIndex; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::_match::MatchAgainstFreshVars; use rustc_middle::ty::abstract_const::NotConstEvaluatable; -use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; @@ -2435,28 +2434,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { match self.match_impl(impl_def_id, impl_trait_header, obligation) { Ok(args) => args, Err(()) => { - // FIXME: A rematch may fail when a candidate cache hit occurs - // on the freshened form of the trait predicate, but the match - // fails for some reason that is not captured in the freshened - // cache key. For example, equating an impl trait ref against - // the placeholder trait ref may fail due the Generalizer relation - // raising a CyclicalTy error due to a sub_root_var relation - // for a variable being generalized... - let guar = self.infcx.dcx().span_delayed_bug( - obligation.cause.span, - format!( - "Impl {impl_def_id:?} was matchable against {obligation:?} but now is not" - ), - ); - let value = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id); - let err = Ty::new_error(self.tcx(), guar); - let value = value.fold_with(&mut BottomUpFolder { - tcx: self.tcx(), - ty_op: |_| err, - lt_op: |l| l, - ct_op: |c| c, - }); - Normalized { value, obligations: vec![] } + let predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); + bug!("impl {impl_def_id:?} was matchable against {predicate:?} but now is not") } } } diff --git a/tests/ui/impl-trait/issues/issue-62742.rs b/tests/ui/impl-trait/issues/issue-62742.rs index 041bd0e3855e..a980856f4763 100644 --- a/tests/ui/impl-trait/issues/issue-62742.rs +++ b/tests/ui/impl-trait/issues/issue-62742.rs @@ -3,6 +3,8 @@ use std::marker::PhantomData; fn _alias_check() { WrongImpl::foo(0i32); //~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied + //~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied + //~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied WrongImpl::<()>::foo(0i32); //~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied //~| ERROR trait bounds were not satisfied diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr index 8d969e8e0f3d..825a48ae919c 100644 --- a/tests/ui/impl-trait/issues/issue-62742.stderr +++ b/tests/ui/impl-trait/issues/issue-62742.stderr @@ -1,3 +1,18 @@ +error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied + --> $DIR/issue-62742.rs:4:5 + | +LL | WrongImpl::foo(0i32); + | ^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` + | + = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>` +note: required by a bound in `SafeImpl::::foo` + --> $DIR/issue-62742.rs:30:20 + | +LL | impl> SafeImpl { + | ^^^^^^ required by this bound in `SafeImpl::::foo` +LL | pub fn foo(value: A::Value) {} + | --- required by a bound in this associated function + error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied --> $DIR/issue-62742.rs:4:5 | @@ -6,13 +21,21 @@ LL | WrongImpl::foo(0i32); | = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>` note: required by a bound in `SafeImpl` - --> $DIR/issue-62742.rs:26:35 + --> $DIR/issue-62742.rs:28:35 | LL | pub struct SafeImpl>(PhantomData<(A, T)>); | ^^^^^^ required by this bound in `SafeImpl` +error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied + --> $DIR/issue-62742.rs:4:5 + | +LL | WrongImpl::foo(0i32); + | ^^^^^^^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` + | + = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>` + error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied - --> $DIR/issue-62742.rs:6:22 + --> $DIR/issue-62742.rs:8:22 | LL | WrongImpl::<()>::foo(0i32); | ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds @@ -24,20 +47,20 @@ LL | pub struct SafeImpl>(PhantomData<(A, T)>); | ----------------------------------------- function or associated item `foo` not found for this struct | note: trait bound `RawImpl<()>: Raw<()>` was not satisfied - --> $DIR/issue-62742.rs:28:20 + --> $DIR/issue-62742.rs:30:20 | LL | impl> SafeImpl { | ^^^^^^ -------------- | | | unsatisfied trait bound introduced here note: the trait `Raw` must be implemented - --> $DIR/issue-62742.rs:12:1 + --> $DIR/issue-62742.rs:14:1 | LL | pub trait Raw { | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied - --> $DIR/issue-62742.rs:6:5 + --> $DIR/issue-62742.rs:8:5 | LL | WrongImpl::<()>::foo(0i32); | ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>` @@ -45,12 +68,12 @@ LL | WrongImpl::<()>::foo(0i32); = help: the trait `Raw<[()]>` is implemented for `RawImpl<()>` = help: for that trait implementation, expected `[()]`, found `()` note: required by a bound in `SafeImpl` - --> $DIR/issue-62742.rs:26:35 + --> $DIR/issue-62742.rs:28:35 | LL | pub struct SafeImpl>(PhantomData<(A, T)>); | ^^^^^^ required by this bound in `SafeImpl` -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0277, E0599. For more information about an error, try `rustc --explain E0277`. From f7cdff825c9a8087406ce56792e07d19f2d04e17 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 15 Jan 2024 15:06:25 +0100 Subject: [PATCH 3/5] overflow errors: change source to a concrete enum --- .../src/solve/normalize.rs | 10 ++- .../error_reporting/type_err_ctxt_ext.rs | 89 ++++++++++++------- .../src/traits/fulfill.rs | 7 +- .../src/traits/normalize.rs | 14 +-- .../src/traits/query/normalize.rs | 7 +- compiler/rustc_type_ir/src/ty_kind.rs | 11 +++ tests/ui/impl-trait/issues/issue-62742.rs | 1 - tests/ui/impl-trait/issues/issue-62742.stderr | 26 ++---- ...type-alias-mutual-recursion.feature.stderr | 6 +- .../infinite-type-alias-mutual-recursion.rs | 6 +- ...infinite-vec-type-recursion.feature.stderr | 2 +- .../infinite/infinite-vec-type-recursion.rs | 2 +- .../inherent-impls-overflow.classic.stderr | 16 ++-- .../inherent-impls-overflow.next.stderr | 6 +- .../inherent-impls-overflow.rs | 14 +-- 15 files changed, 126 insertions(+), 91 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 91312c9fdd68..b1c03e82cab9 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -1,4 +1,4 @@ -use crate::traits::error_reporting::TypeErrCtxtExt; +use crate::traits::error_reporting::{OverflowCause, TypeErrCtxtExt}; use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::{BoundVarReplacer, PlaceholderReplacer}; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -60,8 +60,12 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> { let tcx = infcx.tcx; let recursion_limit = tcx.recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { + let ty::Alias(_, data) = *alias_ty.kind() else { + unreachable!(); + }; + self.at.infcx.err_ctxt().report_overflow_error( - &alias_ty, + OverflowCause::DeeplyNormalize(data), self.at.cause.span, true, |_| {}, @@ -109,7 +113,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> { let recursion_limit = tcx.recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { self.at.infcx.err_ctxt().report_overflow_error( - &ty::Const::new_unevaluated(tcx, uv, ty), + OverflowCause::DeeplyNormalize(ty::AliasTy::new(tcx, uv.def, uv.args)), self.at.cause.span, true, |_| {}, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index be4c6b4d9d12..a5411a04d594 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -57,6 +57,11 @@ use super::{ pub use rustc_infer::traits::error_reporting::*; +pub enum OverflowCause<'tcx> { + DeeplyNormalize(ty::AliasTy<'tcx>), + TraitSolver(ty::Predicate<'tcx>), +} + #[extension(pub trait TypeErrCtxtExt<'tcx>)] impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn report_fulfillment_errors( @@ -184,49 +189,65 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { /// whose result could not be truly determined and thus we can't say /// if the program type checks or not -- and they are unusual /// occurrences in any case. - fn report_overflow_error( + fn report_overflow_error( &self, - predicate: &T, + cause: OverflowCause<'tcx>, span: Span, suggest_increasing_limit: bool, mutate: impl FnOnce(&mut DiagnosticBuilder<'_>), - ) -> ! - where - T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, - { - let mut err = self.build_overflow_error(predicate, span, suggest_increasing_limit); + ) -> ! { + let mut err = self.build_overflow_error(cause, span, suggest_increasing_limit); mutate(&mut err); err.emit(); FatalError.raise(); } - fn build_overflow_error( + fn build_overflow_error( &self, - predicate: &T, + cause: OverflowCause<'tcx>, span: Span, suggest_increasing_limit: bool, - ) -> DiagnosticBuilder<'tcx> - where - T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, - { - let predicate = self.resolve_vars_if_possible(predicate.clone()); - let mut pred_str = predicate.to_string(); - - if pred_str.len() > 50 { - // We don't need to save the type to a file, we will be talking about this type already - // in a separate note when we explain the obligation, so it will be available that way. - let mut cx: FmtPrinter<'_, '_> = - FmtPrinter::new_with_limit(self.tcx, Namespace::TypeNS, rustc_session::Limit(6)); - predicate.print(&mut cx).unwrap(); - pred_str = cx.into_buffer(); + ) -> DiagnosticBuilder<'tcx> { + fn with_short_path<'tcx, T>(tcx: TyCtxt<'tcx>, value: T) -> String + where + T: fmt::Display + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, + { + let s = value.to_string(); + if s.len() > 50 { + // We don't need to save the type to a file, we will be talking about this type already + // in a separate note when we explain the obligation, so it will be available that way. + let mut cx: FmtPrinter<'_, '_> = + FmtPrinter::new_with_limit(tcx, Namespace::TypeNS, rustc_session::Limit(6)); + value.print(&mut cx).unwrap(); + cx.into_buffer() + } else { + s + } } - let mut err = struct_span_code_err!( - self.dcx(), - span, - E0275, - "overflow evaluating the requirement `{}`", - pred_str, - ); + + let mut err = match cause { + OverflowCause::DeeplyNormalize(alias_ty) => { + let alias_ty = self.resolve_vars_if_possible(alias_ty); + let kind = alias_ty.opt_kind(self.tcx).map_or("alias", |k| k.descr()); + let alias_str = with_short_path(self.tcx, alias_ty); + struct_span_code_err!( + self.dcx(), + span, + E0275, + "overflow normalizing the {kind} `{alias_str}`", + ) + } + OverflowCause::TraitSolver(predicate) => { + let predicate = self.resolve_vars_if_possible(predicate); + let pred_str = with_short_path(self.tcx, predicate); + struct_span_code_err!( + self.dcx(), + span, + E0275, + "overflow evaluating the requirement `{pred_str}`", + ) + } + }; if suggest_increasing_limit { self.suggest_new_overflow_limit(&mut err); @@ -252,7 +273,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let predicate = obligation.predicate.clone().to_predicate(self.tcx); let predicate = self.resolve_vars_if_possible(predicate); self.report_overflow_error( - &predicate, + OverflowCause::TraitSolver(predicate), obligation.cause.span, suggest_increasing_limit, |err| { @@ -303,7 +324,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed { let obligation = self.resolve_vars_if_possible(obligation); - let mut err = self.build_overflow_error(&obligation.predicate, obligation.cause.span, true); + let mut err = self.build_overflow_error( + OverflowCause::TraitSolver(obligation.predicate), + obligation.cause.span, + true, + ); self.note_obligation_cause(&mut err, &obligation); self.point_at_returns_when_relevant(&mut err, &obligation); err.emit() diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index fd981130af87..b91698af942e 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -450,12 +450,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { .recursion_limit() .value_within_limit(obligation.recursion_depth) => { - self.selcx.infcx.err_ctxt().report_overflow_error( - &obligation.predicate, - obligation.cause.span, - false, - |_| {}, - ); + self.selcx.infcx.err_ctxt().report_overflow_obligation(&obligation, false); } ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 429e5a5d7a41..15bfffef3ced 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -1,4 +1,8 @@ //! Deeply normalize types using the old trait solver. +use super::error_reporting::OverflowCause; +use super::error_reporting::TypeErrCtxtExt; +use super::SelectionContext; +use super::{project, with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::infer::at::At; use rustc_infer::infer::InferOk; @@ -8,10 +12,6 @@ use rustc_middle::traits::{ObligationCause, ObligationCauseCode, Reveal}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFolder}; use rustc_middle::ty::{TypeFoldable, TypeSuperFoldable, TypeVisitable, TypeVisitableExt}; -use super::error_reporting::TypeErrCtxtExt; -use super::SelectionContext; -use super::{project, with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer}; - #[extension(pub trait NormalizeExt<'tcx>)] impl<'tcx> At<'_, 'tcx> { /// Normalize a value using the `AssocTypeNormalizer`. @@ -173,7 +173,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx } let (kind, data) = match *ty.kind() { - ty::Alias(kind, alias_ty) => (kind, alias_ty), + ty::Alias(kind, data) => (kind, data), _ => return ty.super_fold_with(self), }; @@ -210,7 +210,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx let recursion_limit = self.interner().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { self.selcx.infcx.err_ctxt().report_overflow_error( - &ty, + OverflowCause::DeeplyNormalize(data), self.cause.span, true, |_| {}, @@ -306,7 +306,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx let recursion_limit = self.interner().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { self.selcx.infcx.err_ctxt().report_overflow_error( - &ty, + OverflowCause::DeeplyNormalize(data), self.cause.span, false, |diag| { diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 70fd0b7e50b7..e5f8e3368609 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -5,6 +5,7 @@ use crate::infer::at::At; use crate::infer::canonical::OriginalQueryValues; use crate::infer::{InferCtxt, InferOk}; +use crate::traits::error_reporting::OverflowCause; use crate::traits::error_reporting::TypeErrCtxtExt; use crate::traits::normalize::needs_normalization; use crate::traits::{BoundVarReplacer, PlaceholderReplacer}; @@ -228,7 +229,11 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> let guar = self .infcx .err_ctxt() - .build_overflow_error(&ty, self.cause.span, true) + .build_overflow_error( + OverflowCause::DeeplyNormalize(data), + self.cause.span, + true, + ) .delay_as_bug(); return Ok(Ty::new_error(self.interner(), guar)); } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index d389933fd2df..9f715a01d44f 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -105,6 +105,17 @@ pub enum AliasKind { Weak, } +impl AliasKind { + pub fn descr(self) -> &'static str { + match self { + AliasKind::Projection => "associated type", + AliasKind::Inherent => "inherent associated type", + AliasKind::Opaque => "opaque type", + AliasKind::Weak => "type alias", + } + } +} + /// Defines the kinds of types used by the type system. /// /// Types written by the user start out as `hir::TyKind` and get diff --git a/tests/ui/impl-trait/issues/issue-62742.rs b/tests/ui/impl-trait/issues/issue-62742.rs index a980856f4763..11a75737e554 100644 --- a/tests/ui/impl-trait/issues/issue-62742.rs +++ b/tests/ui/impl-trait/issues/issue-62742.rs @@ -4,7 +4,6 @@ fn _alias_check() { WrongImpl::foo(0i32); //~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied //~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied - //~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied WrongImpl::<()>::foo(0i32); //~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied //~| ERROR trait bounds were not satisfied diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr index 825a48ae919c..9ec581c231b7 100644 --- a/tests/ui/impl-trait/issues/issue-62742.stderr +++ b/tests/ui/impl-trait/issues/issue-62742.stderr @@ -2,11 +2,11 @@ error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied --> $DIR/issue-62742.rs:4:5 | LL | WrongImpl::foo(0i32); - | ^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` | = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>` note: required by a bound in `SafeImpl::::foo` - --> $DIR/issue-62742.rs:30:20 + --> $DIR/issue-62742.rs:29:20 | LL | impl> SafeImpl { | ^^^^^^ required by this bound in `SafeImpl::::foo` @@ -21,21 +21,13 @@ LL | WrongImpl::foo(0i32); | = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>` note: required by a bound in `SafeImpl` - --> $DIR/issue-62742.rs:28:35 + --> $DIR/issue-62742.rs:27:35 | LL | pub struct SafeImpl>(PhantomData<(A, T)>); | ^^^^^^ required by this bound in `SafeImpl` -error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied - --> $DIR/issue-62742.rs:4:5 - | -LL | WrongImpl::foo(0i32); - | ^^^^^^^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` - | - = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>` - error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied - --> $DIR/issue-62742.rs:8:22 + --> $DIR/issue-62742.rs:7:22 | LL | WrongImpl::<()>::foo(0i32); | ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds @@ -47,20 +39,20 @@ LL | pub struct SafeImpl>(PhantomData<(A, T)>); | ----------------------------------------- function or associated item `foo` not found for this struct | note: trait bound `RawImpl<()>: Raw<()>` was not satisfied - --> $DIR/issue-62742.rs:30:20 + --> $DIR/issue-62742.rs:29:20 | LL | impl> SafeImpl { | ^^^^^^ -------------- | | | unsatisfied trait bound introduced here note: the trait `Raw` must be implemented - --> $DIR/issue-62742.rs:14:1 + --> $DIR/issue-62742.rs:13:1 | LL | pub trait Raw { | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied - --> $DIR/issue-62742.rs:8:5 + --> $DIR/issue-62742.rs:7:5 | LL | WrongImpl::<()>::foo(0i32); | ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>` @@ -68,12 +60,12 @@ LL | WrongImpl::<()>::foo(0i32); = help: the trait `Raw<[()]>` is implemented for `RawImpl<()>` = help: for that trait implementation, expected `[()]`, found `()` note: required by a bound in `SafeImpl` - --> $DIR/issue-62742.rs:28:35 + --> $DIR/issue-62742.rs:27:35 | LL | pub struct SafeImpl>(PhantomData<(A, T)>); | ^^^^^^ required by this bound in `SafeImpl` -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0599. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/infinite/infinite-type-alias-mutual-recursion.feature.stderr b/tests/ui/infinite/infinite-type-alias-mutual-recursion.feature.stderr index 8b8fc46dfc5b..3dec2c3084f1 100644 --- a/tests/ui/infinite/infinite-type-alias-mutual-recursion.feature.stderr +++ b/tests/ui/infinite/infinite-type-alias-mutual-recursion.feature.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `X2` +error[E0275]: overflow normalizing the type alias `X2` --> $DIR/infinite-type-alias-mutual-recursion.rs:6:11 | LL | type X1 = X2; @@ -6,7 +6,7 @@ LL | type X1 = X2; | = note: in case this is a recursive type alias, consider using a struct, enum, or union instead -error[E0275]: overflow evaluating the requirement `X3` +error[E0275]: overflow normalizing the type alias `X3` --> $DIR/infinite-type-alias-mutual-recursion.rs:9:11 | LL | type X2 = X3; @@ -14,7 +14,7 @@ LL | type X2 = X3; | = note: in case this is a recursive type alias, consider using a struct, enum, or union instead -error[E0275]: overflow evaluating the requirement `X1` +error[E0275]: overflow normalizing the type alias `X1` --> $DIR/infinite-type-alias-mutual-recursion.rs:11:11 | LL | type X3 = X1; diff --git a/tests/ui/infinite/infinite-type-alias-mutual-recursion.rs b/tests/ui/infinite/infinite-type-alias-mutual-recursion.rs index 91cfe89e28a4..cf9ea0db4cbe 100644 --- a/tests/ui/infinite/infinite-type-alias-mutual-recursion.rs +++ b/tests/ui/infinite/infinite-type-alias-mutual-recursion.rs @@ -5,10 +5,10 @@ type X1 = X2; //[gated]~^ ERROR cycle detected when expanding type alias `X1` -//[feature]~^^ ERROR: overflow evaluating the requirement `X2` +//[feature]~^^ ERROR: overflow normalizing the type alias `X2` type X2 = X3; -//[feature]~^ ERROR: overflow evaluating the requirement `X3` +//[feature]~^ ERROR: overflow normalizing the type alias `X3` type X3 = X1; -//[feature]~^ ERROR: overflow evaluating the requirement `X1` +//[feature]~^ ERROR: overflow normalizing the type alias `X1` fn main() {} diff --git a/tests/ui/infinite/infinite-vec-type-recursion.feature.stderr b/tests/ui/infinite/infinite-vec-type-recursion.feature.stderr index 3aac0d7d1db7..5c8d50341c16 100644 --- a/tests/ui/infinite/infinite-vec-type-recursion.feature.stderr +++ b/tests/ui/infinite/infinite-vec-type-recursion.feature.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `X` +error[E0275]: overflow normalizing the type alias `X` --> $DIR/infinite-vec-type-recursion.rs:6:10 | LL | type X = Vec; diff --git a/tests/ui/infinite/infinite-vec-type-recursion.rs b/tests/ui/infinite/infinite-vec-type-recursion.rs index ff270f3bf8cc..c051d11d376c 100644 --- a/tests/ui/infinite/infinite-vec-type-recursion.rs +++ b/tests/ui/infinite/infinite-vec-type-recursion.rs @@ -5,7 +5,7 @@ type X = Vec; //[gated]~^ ERROR cycle detected -//[feature]~^^ ERROR: overflow evaluating the requirement `X` +//[feature]~^^ ERROR: overflow normalizing the type alias `X` #[rustfmt::skip] fn main() { let b: X = Vec::new(); } diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.classic.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.classic.stderr index 1cace470627e..2f00a877142c 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.classic.stderr +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.classic.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `Loop` +error[E0275]: overflow normalizing the type alias `Loop` --> $DIR/inherent-impls-overflow.rs:7:13 | LL | type Loop = Loop; @@ -6,7 +6,7 @@ LL | type Loop = Loop; | = note: in case this is a recursive type alias, consider using a struct, enum, or union instead -error[E0275]: overflow evaluating the requirement `Loop` +error[E0275]: overflow normalizing the type alias `Loop` --> $DIR/inherent-impls-overflow.rs:9:1 | LL | impl Loop {} @@ -14,24 +14,24 @@ LL | impl Loop {} | = note: in case this is a recursive type alias, consider using a struct, enum, or union instead -error[E0275]: overflow evaluating the requirement `Poly0<((((((...,),),),),),)>` - --> $DIR/inherent-impls-overflow.rs:11:17 +error[E0275]: overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>` + --> $DIR/inherent-impls-overflow.rs:13:17 | LL | type Poly0 = Poly1<(T,)>; | ^^^^^^^^^^^ | = note: in case this is a recursive type alias, consider using a struct, enum, or union instead -error[E0275]: overflow evaluating the requirement `Poly1<((((((...,),),),),),)>` - --> $DIR/inherent-impls-overflow.rs:14:17 +error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` + --> $DIR/inherent-impls-overflow.rs:16:17 | LL | type Poly1 = Poly0<(T,)>; | ^^^^^^^^^^^ | = note: in case this is a recursive type alias, consider using a struct, enum, or union instead -error[E0275]: overflow evaluating the requirement `Poly1<((((((...,),),),),),)>` - --> $DIR/inherent-impls-overflow.rs:18:1 +error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` + --> $DIR/inherent-impls-overflow.rs:20:1 | LL | impl Poly0<()> {} | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr index 1a6259b5cf90..85e8061f173a 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr @@ -7,7 +7,7 @@ LL | impl Loop {} = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_impls_overflow`) error[E0392]: type parameter `T` is never used - --> $DIR/inherent-impls-overflow.rs:11:12 + --> $DIR/inherent-impls-overflow.rs:13:12 | LL | type Poly0 = Poly1<(T,)>; | ^ unused type parameter @@ -16,7 +16,7 @@ LL | type Poly0 = Poly1<(T,)>; = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error[E0392]: type parameter `T` is never used - --> $DIR/inherent-impls-overflow.rs:14:12 + --> $DIR/inherent-impls-overflow.rs:16:12 | LL | type Poly1 = Poly0<(T,)>; | ^ unused type parameter @@ -25,7 +25,7 @@ LL | type Poly1 = Poly0<(T,)>; = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error[E0275]: overflow evaluating the requirement `Poly0<()> == _` - --> $DIR/inherent-impls-overflow.rs:18:6 + --> $DIR/inherent-impls-overflow.rs:20:6 | LL | impl Poly0<()> {} | ^^^^^^^^^ diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs index b260dedeb074..dbf5c3743e88 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs @@ -4,17 +4,21 @@ #![feature(lazy_type_alias)] #![allow(incomplete_features)] -type Loop = Loop; //[classic]~ ERROR overflow evaluating the requirement +type Loop = Loop; //[classic]~ ERROR overflow normalizing the type alias `Loop` -impl Loop {} //~ ERROR overflow evaluating the requirement +impl Loop {} +//[classic]~^ ERROR overflow normalizing the type alias `Loop` +//[next]~^^ ERROR overflow evaluating the requirement `Loop == _` type Poly0 = Poly1<(T,)>; -//[classic]~^ ERROR overflow evaluating the requirement +//[classic]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>` //[next]~^^ ERROR type parameter `T` is never used type Poly1 = Poly0<(T,)>; -//[classic]~^ ERROR overflow evaluating the requirement +//[classic]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` //[next]~^^ ERROR type parameter `T` is never used -impl Poly0<()> {} //~ ERROR overflow evaluating the requirement +impl Poly0<()> {} +//[classic]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` +//[next]~^^ ERROR overflow evaluating the requirement `Poly0<()> == _` fn main() {} From 49dc0f22f43e54f6ddac568f3773d8cae63aeaac Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 15 Jan 2024 15:31:30 +0100 Subject: [PATCH 4/5] do not use <: in subtyping overflow msg --- .../error_reporting/type_err_ctxt_ext.rs | 27 ++++++++++++++----- tests/ui/impl-trait/issues/issue-84073.rs | 2 +- tests/ui/impl-trait/issues/issue-84073.stderr | 2 +- tests/ui/infinite/infinite-autoderef.rs | 2 +- tests/ui/infinite/infinite-autoderef.stderr | 2 +- tests/ui/occurs-check-2.rs | 2 +- tests/ui/occurs-check-2.stderr | 2 +- tests/ui/occurs-check-3.rs | 2 +- tests/ui/occurs-check-3.stderr | 2 +- tests/ui/occurs-check.rs | 2 +- tests/ui/occurs-check.stderr | 2 +- tests/ui/traits/subtype-recursion-limit.rs | 2 +- .../ui/traits/subtype-recursion-limit.stderr | 2 +- .../ui/traits/well-formed-recursion-limit.rs | 4 +-- .../traits/well-formed-recursion-limit.stderr | 2 +- 15 files changed, 35 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index a5411a04d594..eaae900549e9 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -239,13 +239,26 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } OverflowCause::TraitSolver(predicate) => { let predicate = self.resolve_vars_if_possible(predicate); - let pred_str = with_short_path(self.tcx, predicate); - struct_span_code_err!( - self.dcx(), - span, - E0275, - "overflow evaluating the requirement `{pred_str}`", - ) + match predicate.kind().skip_binder() { + ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ }) + | ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => { + struct_span_code_err!( + self.dcx(), + span, + E0275, + "overflow setting `{a}` to a subtype of `{b}`", + ) + } + _ => { + let pred_str = with_short_path(self.tcx, predicate); + struct_span_code_err!( + self.dcx(), + span, + E0275, + "overflow evaluating the requirement `{pred_str}`", + ) + } + } } }; diff --git a/tests/ui/impl-trait/issues/issue-84073.rs b/tests/ui/impl-trait/issues/issue-84073.rs index 60f98a7c7b53..124b1d0eec84 100644 --- a/tests/ui/impl-trait/issues/issue-84073.rs +++ b/tests/ui/impl-trait/issues/issue-84073.rs @@ -29,5 +29,5 @@ where } fn main() { - Race::new(|race| race.when()); //~ ERROR overflow evaluating the requirement `_ <: Option<_>` + Race::new(|race| race.when()); //~ ERROR overflow setting `_` to a subtype of `Option<_>` } diff --git a/tests/ui/impl-trait/issues/issue-84073.stderr b/tests/ui/impl-trait/issues/issue-84073.stderr index b9039211db63..2441e523684c 100644 --- a/tests/ui/impl-trait/issues/issue-84073.stderr +++ b/tests/ui/impl-trait/issues/issue-84073.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `_ <: Option<_>` +error[E0275]: overflow setting `_` to a subtype of `Option<_>` --> $DIR/issue-84073.rs:32:22 | LL | Race::new(|race| race.when()); diff --git a/tests/ui/infinite/infinite-autoderef.rs b/tests/ui/infinite/infinite-autoderef.rs index cf5c9fe5678c..ae854e1d2048 100644 --- a/tests/ui/infinite/infinite-autoderef.rs +++ b/tests/ui/infinite/infinite-autoderef.rs @@ -14,7 +14,7 @@ pub fn main() { let mut x; loop { x = Box::new(x); - //~^ ERROR overflow evaluating the requirement `Box<_> <: _` + //~^ ERROR overflow setting `Box<_>` to a subtype of `_` x.foo; x.bar(); } diff --git a/tests/ui/infinite/infinite-autoderef.stderr b/tests/ui/infinite/infinite-autoderef.stderr index 24be1a11373c..94ec00c591e4 100644 --- a/tests/ui/infinite/infinite-autoderef.stderr +++ b/tests/ui/infinite/infinite-autoderef.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `Box<_> <: _` +error[E0275]: overflow setting `Box<_>` to a subtype of `_` --> $DIR/infinite-autoderef.rs:16:13 | LL | x = Box::new(x); diff --git a/tests/ui/occurs-check-2.rs b/tests/ui/occurs-check-2.rs index 6cdb757d65bc..80ae75632a5d 100644 --- a/tests/ui/occurs-check-2.rs +++ b/tests/ui/occurs-check-2.rs @@ -5,5 +5,5 @@ fn main() { g = f; f = Box::new(g); - //~^ ERROR overflow evaluating the requirement `Box<_> <: _` + //~^ ERROR overflow setting `Box<_>` to a subtype of `_` } diff --git a/tests/ui/occurs-check-2.stderr b/tests/ui/occurs-check-2.stderr index acc474319b05..cf5c95a1c42b 100644 --- a/tests/ui/occurs-check-2.stderr +++ b/tests/ui/occurs-check-2.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `Box<_> <: _` +error[E0275]: overflow setting `Box<_>` to a subtype of `_` --> $DIR/occurs-check-2.rs:7:9 | LL | f = Box::new(g); diff --git a/tests/ui/occurs-check-3.rs b/tests/ui/occurs-check-3.rs index cdf8dc3bd160..f3d9a28b62d4 100644 --- a/tests/ui/occurs-check-3.rs +++ b/tests/ui/occurs-check-3.rs @@ -4,7 +4,7 @@ enum Clam { A(T) } fn main() { let c; c = Clam::A(c); - //~^ ERROR overflow evaluating the requirement `Clam<_> <: _` + //~^ ERROR overflow setting `Clam<_>` to a subtype of `_` match c { Clam::A::(_) => { } } diff --git a/tests/ui/occurs-check-3.stderr b/tests/ui/occurs-check-3.stderr index 7bc28e61d9f9..84197162c382 100644 --- a/tests/ui/occurs-check-3.stderr +++ b/tests/ui/occurs-check-3.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `Clam<_> <: _` +error[E0275]: overflow setting `Clam<_>` to a subtype of `_` --> $DIR/occurs-check-3.rs:6:9 | LL | c = Clam::A(c); diff --git a/tests/ui/occurs-check.rs b/tests/ui/occurs-check.rs index 3fae3ff1238e..dce0a41bce71 100644 --- a/tests/ui/occurs-check.rs +++ b/tests/ui/occurs-check.rs @@ -1,5 +1,5 @@ fn main() { let f; f = Box::new(f); - //~^ ERROR overflow evaluating the requirement `Box<_> <: _` + //~^ ERROR overflow setting `Box<_>` to a subtype of `_` } diff --git a/tests/ui/occurs-check.stderr b/tests/ui/occurs-check.stderr index 3f61d8fd08d1..0454e6ddda67 100644 --- a/tests/ui/occurs-check.stderr +++ b/tests/ui/occurs-check.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `Box<_> <: _` +error[E0275]: overflow setting `Box<_>` to a subtype of `_` --> $DIR/occurs-check.rs:3:9 | LL | f = Box::new(f); diff --git a/tests/ui/traits/subtype-recursion-limit.rs b/tests/ui/traits/subtype-recursion-limit.rs index 5804748844e5..c652e24644d3 100644 --- a/tests/ui/traits/subtype-recursion-limit.rs +++ b/tests/ui/traits/subtype-recursion-limit.rs @@ -10,7 +10,7 @@ fn main() { let x = return; let y = return; let mut w = (x, y); - //~^ ERROR overflow evaluating the requirement + //~^ ERROR overflow setting `_` to a subtype of `*const _` // Avoid creating lifetimes, `Sized` bounds or function calls. let a = (ptr::addr_of!(y), ptr::addr_of!(x)); w = a; diff --git a/tests/ui/traits/subtype-recursion-limit.stderr b/tests/ui/traits/subtype-recursion-limit.stderr index 5310f822cc33..6544852bbf06 100644 --- a/tests/ui/traits/subtype-recursion-limit.stderr +++ b/tests/ui/traits/subtype-recursion-limit.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `_ <: *const _` +error[E0275]: overflow setting `_` to a subtype of `*const _` --> $DIR/subtype-recursion-limit.rs:12:17 | LL | let mut w = (x, y); diff --git a/tests/ui/traits/well-formed-recursion-limit.rs b/tests/ui/traits/well-formed-recursion-limit.rs index 056cf947d4b5..49713be3a798 100644 --- a/tests/ui/traits/well-formed-recursion-limit.rs +++ b/tests/ui/traits/well-formed-recursion-limit.rs @@ -13,8 +13,8 @@ pub fn iso_un_option(i: ISO, Option>) -> IS //~^ ERROR no field `ab` on type //~| ERROR no field `ba` on type let left = move |o_a| match o_a { - //~^ ERROR overflow evaluating the requirement - None => panic!("absured"), + //~^ ERROR overflow setting `_` to a subtype of `Option<_>` + None => panic!("absurd"), Some(a) => a, }; let right = move |o_b| match o_b { diff --git a/tests/ui/traits/well-formed-recursion-limit.stderr b/tests/ui/traits/well-formed-recursion-limit.stderr index 6f5fda02315c..690d869b2435 100644 --- a/tests/ui/traits/well-formed-recursion-limit.stderr +++ b/tests/ui/traits/well-formed-recursion-limit.stderr @@ -10,7 +10,7 @@ error[E0609]: no field `ba` on type `(Box<(dyn Fn(Option) -> Option + 'sta LL | let (ab, ba) = (i.ab, i.ba); | ^^ unknown field -error[E0275]: overflow evaluating the requirement `_ <: Option<_>` +error[E0275]: overflow setting `_` to a subtype of `Option<_>` --> $DIR/well-formed-recursion-limit.rs:15:33 | LL | let left = move |o_a| match o_a { From c71484eefd38d6d60a54981376f3b157789cc570 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 22 Feb 2024 18:18:33 +0100 Subject: [PATCH 5/5] change error messages to be incorrect, but more helpful --- .../src/traits/error_reporting/type_err_ctxt_ext.rs | 2 +- tests/ui/impl-trait/issues/issue-84073.rs | 2 +- tests/ui/impl-trait/issues/issue-84073.stderr | 2 +- tests/ui/infinite/infinite-autoderef.rs | 2 +- tests/ui/infinite/infinite-autoderef.stderr | 2 +- tests/ui/occurs-check-2.rs | 2 +- tests/ui/occurs-check-2.stderr | 2 +- tests/ui/occurs-check-3.rs | 2 +- tests/ui/occurs-check-3.stderr | 2 +- tests/ui/occurs-check.rs | 2 +- tests/ui/occurs-check.stderr | 2 +- tests/ui/traits/subtype-recursion-limit.rs | 2 +- tests/ui/traits/subtype-recursion-limit.stderr | 2 +- tests/ui/traits/well-formed-recursion-limit.rs | 2 +- tests/ui/traits/well-formed-recursion-limit.stderr | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index eaae900549e9..2b74b15ec9fa 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -246,7 +246,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.dcx(), span, E0275, - "overflow setting `{a}` to a subtype of `{b}`", + "overflow assigning `{a}` to `{b}`", ) } _ => { diff --git a/tests/ui/impl-trait/issues/issue-84073.rs b/tests/ui/impl-trait/issues/issue-84073.rs index 124b1d0eec84..85d9d461fd9a 100644 --- a/tests/ui/impl-trait/issues/issue-84073.rs +++ b/tests/ui/impl-trait/issues/issue-84073.rs @@ -29,5 +29,5 @@ where } fn main() { - Race::new(|race| race.when()); //~ ERROR overflow setting `_` to a subtype of `Option<_>` + Race::new(|race| race.when()); //~ ERROR overflow assigning `_` to `Option<_>` } diff --git a/tests/ui/impl-trait/issues/issue-84073.stderr b/tests/ui/impl-trait/issues/issue-84073.stderr index 2441e523684c..ab119a8a4f45 100644 --- a/tests/ui/impl-trait/issues/issue-84073.stderr +++ b/tests/ui/impl-trait/issues/issue-84073.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow setting `_` to a subtype of `Option<_>` +error[E0275]: overflow assigning `_` to `Option<_>` --> $DIR/issue-84073.rs:32:22 | LL | Race::new(|race| race.when()); diff --git a/tests/ui/infinite/infinite-autoderef.rs b/tests/ui/infinite/infinite-autoderef.rs index ae854e1d2048..ef6ba8ac87b7 100644 --- a/tests/ui/infinite/infinite-autoderef.rs +++ b/tests/ui/infinite/infinite-autoderef.rs @@ -14,7 +14,7 @@ pub fn main() { let mut x; loop { x = Box::new(x); - //~^ ERROR overflow setting `Box<_>` to a subtype of `_` + //~^ ERROR overflow assigning `Box<_>` to `_` x.foo; x.bar(); } diff --git a/tests/ui/infinite/infinite-autoderef.stderr b/tests/ui/infinite/infinite-autoderef.stderr index 94ec00c591e4..7d09af9a7d4a 100644 --- a/tests/ui/infinite/infinite-autoderef.stderr +++ b/tests/ui/infinite/infinite-autoderef.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow setting `Box<_>` to a subtype of `_` +error[E0275]: overflow assigning `Box<_>` to `_` --> $DIR/infinite-autoderef.rs:16:13 | LL | x = Box::new(x); diff --git a/tests/ui/occurs-check-2.rs b/tests/ui/occurs-check-2.rs index 80ae75632a5d..1ec460a87352 100644 --- a/tests/ui/occurs-check-2.rs +++ b/tests/ui/occurs-check-2.rs @@ -5,5 +5,5 @@ fn main() { g = f; f = Box::new(g); - //~^ ERROR overflow setting `Box<_>` to a subtype of `_` + //~^ ERROR overflow assigning `Box<_>` to `_` } diff --git a/tests/ui/occurs-check-2.stderr b/tests/ui/occurs-check-2.stderr index cf5c95a1c42b..54307a6c5474 100644 --- a/tests/ui/occurs-check-2.stderr +++ b/tests/ui/occurs-check-2.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow setting `Box<_>` to a subtype of `_` +error[E0275]: overflow assigning `Box<_>` to `_` --> $DIR/occurs-check-2.rs:7:9 | LL | f = Box::new(g); diff --git a/tests/ui/occurs-check-3.rs b/tests/ui/occurs-check-3.rs index f3d9a28b62d4..377a043daf3f 100644 --- a/tests/ui/occurs-check-3.rs +++ b/tests/ui/occurs-check-3.rs @@ -4,7 +4,7 @@ enum Clam { A(T) } fn main() { let c; c = Clam::A(c); - //~^ ERROR overflow setting `Clam<_>` to a subtype of `_` + //~^ ERROR overflow assigning `Clam<_>` to `_` match c { Clam::A::(_) => { } } diff --git a/tests/ui/occurs-check-3.stderr b/tests/ui/occurs-check-3.stderr index 84197162c382..77b67ec1a62c 100644 --- a/tests/ui/occurs-check-3.stderr +++ b/tests/ui/occurs-check-3.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow setting `Clam<_>` to a subtype of `_` +error[E0275]: overflow assigning `Clam<_>` to `_` --> $DIR/occurs-check-3.rs:6:9 | LL | c = Clam::A(c); diff --git a/tests/ui/occurs-check.rs b/tests/ui/occurs-check.rs index dce0a41bce71..638b9b6d7e4c 100644 --- a/tests/ui/occurs-check.rs +++ b/tests/ui/occurs-check.rs @@ -1,5 +1,5 @@ fn main() { let f; f = Box::new(f); - //~^ ERROR overflow setting `Box<_>` to a subtype of `_` + //~^ ERROR overflow assigning `Box<_>` to `_` } diff --git a/tests/ui/occurs-check.stderr b/tests/ui/occurs-check.stderr index 0454e6ddda67..30468d68cbd0 100644 --- a/tests/ui/occurs-check.stderr +++ b/tests/ui/occurs-check.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow setting `Box<_>` to a subtype of `_` +error[E0275]: overflow assigning `Box<_>` to `_` --> $DIR/occurs-check.rs:3:9 | LL | f = Box::new(f); diff --git a/tests/ui/traits/subtype-recursion-limit.rs b/tests/ui/traits/subtype-recursion-limit.rs index c652e24644d3..e4b08a7ec677 100644 --- a/tests/ui/traits/subtype-recursion-limit.rs +++ b/tests/ui/traits/subtype-recursion-limit.rs @@ -10,7 +10,7 @@ fn main() { let x = return; let y = return; let mut w = (x, y); - //~^ ERROR overflow setting `_` to a subtype of `*const _` + //~^ ERROR overflow assigning `_` to `*const _` // Avoid creating lifetimes, `Sized` bounds or function calls. let a = (ptr::addr_of!(y), ptr::addr_of!(x)); w = a; diff --git a/tests/ui/traits/subtype-recursion-limit.stderr b/tests/ui/traits/subtype-recursion-limit.stderr index 6544852bbf06..e3587de8613d 100644 --- a/tests/ui/traits/subtype-recursion-limit.stderr +++ b/tests/ui/traits/subtype-recursion-limit.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow setting `_` to a subtype of `*const _` +error[E0275]: overflow assigning `_` to `*const _` --> $DIR/subtype-recursion-limit.rs:12:17 | LL | let mut w = (x, y); diff --git a/tests/ui/traits/well-formed-recursion-limit.rs b/tests/ui/traits/well-formed-recursion-limit.rs index 49713be3a798..770b2222580c 100644 --- a/tests/ui/traits/well-formed-recursion-limit.rs +++ b/tests/ui/traits/well-formed-recursion-limit.rs @@ -13,7 +13,7 @@ pub fn iso_un_option(i: ISO, Option>) -> IS //~^ ERROR no field `ab` on type //~| ERROR no field `ba` on type let left = move |o_a| match o_a { - //~^ ERROR overflow setting `_` to a subtype of `Option<_>` + //~^ ERROR overflow assigning `_` to `Option<_>` None => panic!("absurd"), Some(a) => a, }; diff --git a/tests/ui/traits/well-formed-recursion-limit.stderr b/tests/ui/traits/well-formed-recursion-limit.stderr index 690d869b2435..e0270ecabbd8 100644 --- a/tests/ui/traits/well-formed-recursion-limit.stderr +++ b/tests/ui/traits/well-formed-recursion-limit.stderr @@ -10,7 +10,7 @@ error[E0609]: no field `ba` on type `(Box<(dyn Fn(Option) -> Option + 'sta LL | let (ab, ba) = (i.ab, i.ba); | ^^ unknown field -error[E0275]: overflow setting `_` to a subtype of `Option<_>` +error[E0275]: overflow assigning `_` to `Option<_>` --> $DIR/well-formed-recursion-limit.rs:15:33 | LL | let left = move |o_a| match o_a {