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/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_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/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 7186b96b40d04..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 @@ -57,12 +57,21 @@ 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( &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>, @@ -180,49 +189,78 @@ 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); + 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 assigning `{a}` to `{b}`", + ) + } + _ => { + 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); @@ -248,7 +286,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| { @@ -299,7 +337,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_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/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/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-62742.rs b/tests/ui/impl-trait/issues/issue-62742.rs index 041bd0e3855ec..11a75737e5545 100644 --- a/tests/ui/impl-trait/issues/issue-62742.rs +++ b/tests/ui/impl-trait/issues/issue-62742.rs @@ -3,6 +3,7 @@ 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 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..9ec581c231b7b 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:29: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,13 @@ 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:27:35 | LL | pub struct SafeImpl>(PhantomData<(A, T)>); | ^^^^^^ required by this bound in `SafeImpl` 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:7:22 | LL | WrongImpl::<()>::foo(0i32); | ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds @@ -24,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:28: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:12: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:6:5 + --> $DIR/issue-62742.rs:7:5 | LL | WrongImpl::<()>::foo(0i32); | ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>` @@ -45,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:26:35 + --> $DIR/issue-62742.rs:27: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 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/impl-trait/issues/issue-84073.rs b/tests/ui/impl-trait/issues/issue-84073.rs index 49a34ccfa3b4b..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 type annotations needed + 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 d03e458aeb821..ab119a8a4f456 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 assigning `_` to `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..ef6ba8ac87b7b 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 assigning `Box<_>` to `_` x.foo; x.bar(); } diff --git a/tests/ui/infinite/infinite-autoderef.stderr b/tests/ui/infinite/infinite-autoderef.stderr index 51b61e3a66bb4..7d09af9a7d4af 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 assigning `Box<_>` to `_` + --> $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/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/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/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() {} diff --git a/tests/ui/occurs-check-2.rs b/tests/ui/occurs-check-2.rs index f36682a3dd821..1ec460a873527 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 assigning `Box<_>` to `_` } diff --git a/tests/ui/occurs-check-2.stderr b/tests/ui/occurs-check-2.stderr index 7b6fb9fafa202..54307a6c5474f 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 assigning `Box<_>` to `_` --> $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..377a043daf3f6 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 assigning `Clam<_>` to `_` + match c { + Clam::A::(_) => { } + } +} diff --git a/tests/ui/occurs-check-3.stderr b/tests/ui/occurs-check-3.stderr index 675133b6d50bd..77b67ec1a62c6 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 assigning `Clam<_>` to `_` + --> $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..638b9b6d7e4c2 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 assigning `Box<_>` to `_` } diff --git a/tests/ui/occurs-check.stderr b/tests/ui/occurs-check.stderr index 1cb6b32cb2336..30468d68cbd05 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 assigning `Box<_>` to `_` + --> $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`. diff --git a/tests/ui/traits/subtype-recursion-limit.rs b/tests/ui/traits/subtype-recursion-limit.rs index 5804748844e5a..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 evaluating the requirement + //~^ 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 5310f822cc338..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 evaluating the requirement `_ <: *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 056cf947d4b55..770b2222580cf 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 assigning `_` to `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..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 evaluating the requirement `_ <: Option<_>` +error[E0275]: overflow assigning `_` to `Option<_>` --> $DIR/well-formed-recursion-limit.rs:15:33 | LL | let left = move |o_a| match o_a {