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 986af2f5c9e64..9303e437a968e 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 ad4546c09b546..685b1af931e34 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 505d56cf49179..d40f3f501f58a 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 af722b206262a..896d17478504d 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 0000000000000..ef26a8ff7b863 --- /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 8fc71671b271d..8b5710ee9edc1 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 90f10a0eba9e5..c4c9ddb1ad8e6 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 8b81eac873909..3630b0f439ff4 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 be02452d89fbf..829b0a73a0df5 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 7186b96b40d04..be4c6b4d9d124 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 84e24d1a3f5f9..5bdd3e39806e3 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 4b1b9f20559e8..a2c4dec472439 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 1b3a54923284c..46230d455b270 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 49a34ccfa3b4b..60f98a7c7b53c 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 d03e458aeb821..b9039211db63f 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 d6956e6945707..cf5c9fe5678c2 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 51b61e3a66bb4..24be1a11373cd 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[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 +error: aborting due to 1 previous error -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 8dcdd88c618c7..b4d50bd4ce795 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 960de1be299e1..33d3e48c1aac8 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 f36682a3dd821..6cdb757d65bc6 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 7b6fb9fafa202..acc474319b059 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 9c04204010b77..cdf8dc3bd160b 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 675133b6d50bd..7bc28e61d9f96 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 aec52d839766a..3fae3ff1238e3 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 1cb6b32cb2336..3f61d8fd08d17 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 7920ae0b26cca..13331a016fcfe 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 ff840b781f072..77b01ee08b791 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 | 136 +++++++++--------- .../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, 103 insertions(+), 97 deletions(-) diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 2d5fa1b5c7001..ef9c407acef5c 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::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::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) => { + 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 1146f869fc16d..a4499d438c1b5 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 041bd0e3855ec..a980856f4763e 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 8d969e8e0f3dc..825a48ae919c5 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 91312c9fdd68b..b1c03e82cab9b 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 be4c6b4d9d124..a5411a04d594a 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 fd981130af872..b91698af942e0 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 429e5a5d7a413..15bfffef3cede 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 70fd0b7e50b75..e5f8e33686099 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 d389933fd2dfa..9f715a01d44fa 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 a980856f4763e..11a75737e5545 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 825a48ae919c5..9ec581c231b7b 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 8b8fc46dfc5ba..3dec2c3084f12 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 91cfe89e28a43..cf9ea0db4cbee 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 3aac0d7d1db74..5c8d50341c164 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 ff270f3bf8cc2..c051d11d376c8 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 1cace470627e4..2f00a877142c0 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 1a6259b5cf901..85e8061f173a3 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 b260dedeb0746..dbf5c3743e88a 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 a5411a04d594a..eaae900549e9c 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 60f98a7c7b53c..124b1d0eec848 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 b9039211db63f..2441e523684c1 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 cf5c9fe5678c2..ae854e1d20480 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 24be1a11373cd..94ec00c591e4a 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 6cdb757d65bc6..80ae75632a5de 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 acc474319b059..cf5c95a1c42b5 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 cdf8dc3bd160b..f3d9a28b62d4c 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 7bc28e61d9f96..84197162c3827 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 3fae3ff1238e3..dce0a41bce71d 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 3f61d8fd08d17..0454e6ddda67d 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 5804748844e5a..c652e24644d35 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 5310f822cc338..6544852bbf06a 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 056cf947d4b55..49713be3a798e 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 6f5fda02315c0..690d869b24354 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 eaae900549e9c..2b74b15ec9faa 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 124b1d0eec848..85d9d461fd9ad 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 2441e523684c1..ab119a8a4f456 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 ae854e1d20480..ef6ba8ac87b7b 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 94ec00c591e4a..7d09af9a7d4af 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 80ae75632a5de..1ec460a873527 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 cf5c95a1c42b5..54307a6c5474f 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 f3d9a28b62d4c..377a043daf3f6 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 84197162c3827..77b67ec1a62c6 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 dce0a41bce71d..638b9b6d7e4c2 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 0454e6ddda67d..30468d68cbd05 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 c652e24644d35..e4b08a7ec6774 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 6544852bbf06a..e3587de8613d6 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 49713be3a798e..770b2222580cf 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 690d869b24354..e0270ecabbd8d 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 {