diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 05e5d850bf958..3efdab534384b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -278,9 +278,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, ) -> bool { if let traits::FulfillmentErrorCode::CodeSelectionError( - traits::SelectionError::OutputTypeParameterMismatch(_, expected, _), + traits::SelectionError::OutputTypeParameterMismatch(box traits::SelectionOutputTypeParameterMismatch{ + expected_trait_ref, .. + }), ) = error.code - && let ty::Closure(def_id, _) | ty::Generator(def_id, ..) = expected.skip_binder().self_ty().kind() + && let ty::Closure(def_id, _) | ty::Generator(def_id, ..) = expected_trait_ref.skip_binder().self_ty().kind() && span.overlaps(self.tcx.def_span(*def_id)) { true diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index a2a4362e2f518..dcc323493f479 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -2,6 +2,7 @@ #![feature(let_chains)] #![feature(try_blocks)] #![feature(never_type)] +#![feature(box_patterns)] #![feature(min_specialization)] #![feature(control_flow_enum)] #![feature(drain_filter)] diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 8366567c2c364..449c453555e9e 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -580,11 +580,7 @@ pub enum SelectionError<'tcx> { /// After a closure impl has selected, its "outputs" were evaluated /// (which for closures includes the "input" type params) and they /// didn't resolve. See `confirm_poly_trait_refs` for more. - OutputTypeParameterMismatch( - ty::PolyTraitRef<'tcx>, - ty::PolyTraitRef<'tcx>, - ty::error::TypeError<'tcx>, - ), + OutputTypeParameterMismatch(Box>), /// The trait pointed by `DefId` is not object safe. TraitNotObjectSafe(DefId), /// A given constant couldn't be evaluated. @@ -596,6 +592,13 @@ pub enum SelectionError<'tcx> { ErrorReporting, } +#[derive(Clone, Debug, TypeVisitable, Lift)] +pub struct SelectionOutputTypeParameterMismatch<'tcx> { + pub found_trait_ref: ty::PolyTraitRef<'tcx>, + pub expected_trait_ref: ty::PolyTraitRef<'tcx>, + pub terr: ty::error::TypeError<'tcx>, +} + /// When performing resolution, it is typically the case that there /// can be one of three outcomes: /// diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index c9e2ed092d160..9836522392373 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -28,6 +28,7 @@ use rustc_hir::{GenericParam, Item, Node}; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::{InferOk, TypeTrace}; use rustc_middle::traits::select::OverflowError; +use rustc_middle::traits::SelectionOutputTypeParameterMismatch; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; @@ -1087,17 +1088,21 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } - OutputTypeParameterMismatch( + OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch { found_trait_ref, expected_trait_ref, - terr @ TypeError::CyclicTy(_), - ) => self.report_type_parameter_mismatch_cyclic_type_error( + terr: terr @ TypeError::CyclicTy(_), + }) => self.report_type_parameter_mismatch_cyclic_type_error( &obligation, found_trait_ref, expected_trait_ref, terr, ), - OutputTypeParameterMismatch(found_trait_ref, expected_trait_ref, _) => { + OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch { + found_trait_ref, + expected_trait_ref, + terr: _, + }) => { match self.report_type_parameter_mismatch_error( &obligation, span, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 616187b69dde4..4dc84e0ad10b1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -10,6 +10,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; +use rustc_middle::traits::SelectionOutputTypeParameterMismatch; use rustc_middle::ty::{ self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeVisitableExt, @@ -811,7 +812,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_poly_trait_refs( &mut self, obligation: &TraitObligation<'tcx>, - expected_trait_ref: ty::PolyTraitRef<'tcx>, + self_ty_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result>, SelectionError<'tcx>> { let obligation_trait_ref = obligation.predicate.to_poly_trait_ref(); // Normalize the obligation and expected trait refs together, because why not @@ -822,7 +823,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - (obligation_trait_ref, expected_trait_ref), + (obligation_trait_ref, self_ty_trait_ref), ) }); @@ -834,7 +835,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligations.extend(nested); obligations }) - .map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e)) + .map_err(|terr| { + OutputTypeParameterMismatch(Box::new(SelectionOutputTypeParameterMismatch { + expected_trait_ref: obligation_trait_ref, + found_trait_ref: expected_trait_ref, + terr, + })) + }) } fn confirm_trait_upcasting_unsize_candidate(