Change:
This is related to and ; but is not the same issue: is already resolved and is dealing with a more complex case where inference is lacking. Also perhaps related to I'm filing an ICE because that's what I'm hitting as I try to reduce it, however I have a related bug where the workaround from doesn't actually work. I wonder if fixing the ICE will make this code compile or if it will hit code that needs to be worked around (My unreduced code is at , ) <details<summaryCode </summary<!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: </details <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</detailscc
Probably related to
I've looked into this: The problem here is that we try to the normalized (coming from and being normalized ) with the unnormalized closure type from the . The normalized input ty in this example corresponds to a closure with substs: and the unnormalized input ty from the mir is a closure with substs: . This fails since the output types cannot be equalized. We can make this compile by normalizing  (note that we cannot normalize the for the closure during typecheck since this leads to other type relation problems), but I feel that this misses the actual problem. I would expect that we would get problems when actually building this if some associated type in the mir is not normalized. Can you give me an example including a main function that uses upcast? I had problems fulfilling the bound when supplying an argument to .
Wait I'm a bit the hack that I literally right there not work?
Yes, that fails to normalize it.
Ah, I see, it's that is unnormalized. Can we just repeat the hack to normalize ? As you stated (and I found previously), this does miss the problem, but it's a difficult problem to solve.
trying to write the upcast displays the related bug that I was trying to reduce in the first place: which throws As mentioned before, this is along the same vein as and : The trait bound is satisfied by the type, rustc just can't figure it out.
No 'b' is unnormalized, the problem seems to be that an empty is passed to . I can open a PR for that. One question though, when we normalize we add region constraints by using , can we ignore these constraints here?
Ah I see; I was reading it as the first arg. So, In , the first fails, so we try to normalize . Now, specifically, we need to normalize to . The question is why. We shouldn't need the here. The problem might be related to the fact that the impl is implemented for the lifetime whereas this looks like some inference region var (but that should just come out as region constraints which we maybe should ignore). We should be able to, yes.
You're right about the second projection, but the normalization of actually fails because cannot be normalized and we need the for that.
Oh are we only able to normalize "all or nothing"? I'm not worried about that because it also appears in
yeah its not important for the eq relation here, but returns an error because isn't provable if we don't supply the correct param_env.
The ICE is now fixed, but the underlying bug I was trying to reduce still exists, going to file another issue.

Discussion:
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and //! contain revealed `impl Trait` values). <ins> use crate::type_check::constraint_conversion::ConstraintConversion; </ins> use rustc_index::vec::Idx; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::mir::*; <del> use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, Ty}; </del> <ins> use rustc_middle::ty::Ty; </ins> use rustc_span::Span; <del> use rustc_trait_selection::traits::query::normalize::AtExt; </del> <ins> use rustc_span::DUMMY_SP; use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use rustc_trait_selection::traits::query::Fallible; use type_op::TypeOpOutput; </ins> use crate::universal_regions::UniversalRegions;

let (&normalized_output_ty, normalized_input_tys) = normalized_inputs_and_output.split_last().unwrap(); <ins> debug!(?normalized_output_ty); debug!(?normalized_input_tys); </ins> let mir_def_id = body.source.def_id().expect_local(); // If the user explicitly annotated the input types, extract

.delay_span_bug(body.span, "found more normalized_input_ty than local_decls"); break; } // In MIR, argument N is stored in local N+1. let local = Local::new(argument_index + 1); let mir_input_ty = body.local_decls[local].ty; let mir_input_span = body.local_decls[local].source_info.span; self.equate_normalized_input_or_output( normalized_input_ty,

// If the user explicitly annotated the input types, enforce those. let user_provided_input_ty = self.normalize(user_provided_input_ty, Locations::All(mir_input_span)); self.equate_normalized_input_or_output( user_provided_input_ty, mir_input_ty,

// `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd // like to normalize *before* inserting into `local_decls`, but // doing so ends up causing some other trouble. <del> let b = match self .infcx .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) .normalize(b) { Ok(n) => { debug!("equate_inputs_and_outputs: {:?}", n); if n.obligations.iter().all(|o| { matches!( o.predicate.kind().skip_binder(), ty::PredicateKind::RegionOutlives(_) | ty::PredicateKind::TypeOutlives(_) ) }) { n.value } else { b } } </del> <ins> let b = match self.normalize_and_add_constraints(b) { Ok(n) => n, </ins> Err(_) => { debug!("equate_inputs_and_outputs: NoSolution"); b } }; // Note: if we have to introduce new placeholders during normalization above, then we won't have // added those universes to the universe info, which we would want in `relate_tys`. if let Err(terr) =

} } } <ins> pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible<Ty<'tcx>> { let TypeOpOutput { output: norm_ty, constraints, .. } = self.param_env.and(type_op::normalize::Normalize::new(t)).fully_perform(self.infcx)?; debug!("{:?} normalized to {:?}", t, norm_ty); for data in constraints.into_iter().collect::<Vec<_>>() { ConstraintConversion::new( self.infcx, &self.borrowck_context.universal_regions, &self.region_bound_pairs, Some(self.implicit_region_bound), self.param_env, Locations::All(DUMMY_SP), ConstraintCategory::Internal, &mut self.borrowck_context.constraints, ) .convert_all(&*data); } Ok(norm_ty) } </ins> }

} struct BorrowCheckContext<'a, 'tcx> { <del> universal_regions: &'a UniversalRegions<'tcx>, </del> <ins> pub(crate) universal_regions: &'a UniversalRegions<'tcx>, </ins> location_table: &'a LocationTable, all_facts: &'a mut Option<AllFacts>, borrow_set: &'a BorrowSet<'tcx>, <del> constraints: &'a mut MirTypeckRegionConstraints<'tcx>, </del> <ins> pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>, </ins> upvars: &'a [Upvar<'tcx>], }

self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category) } <ins> #[instrument(skip(self, category), level = "debug")] </ins> fn eq_types( &mut self, expected: Ty<'tcx>,

<ins> // check-pass #![feature(generic_associated_types)] use std::marker::PhantomData; trait Family: Sized { type Item<'a>; fn apply_all<F>(&self, f: F) where F: FamilyItemFn<Self> { } } struct Array<T>(PhantomData<T>); impl<T: 'static> Family for Array<T> { type Item<'a> = &'a T; } trait FamilyItemFn<T: Family> { fn apply(&self, item: T::Item<'_>); } impl<T, F> FamilyItemFn<T> for F where T: Family, for<'a> F: Fn(T::Item<'a>) { fn apply(&self, item: T::Item<'_>) { (*self)(item); } } fn process<T: 'static>(array: Array<T>) { // Works array.apply_all(|x: &T| { }); // ICE: NoSolution array.apply_all(|x: <Array<T> as Family>::Item<'_>| { }); } fn main() {} </ins>

<ins> //check-pass #![feature(generic_associated_types)] trait Yokeable<'a>: 'static { type Output: 'a; } trait IsCovariant<'a> {} struct Yoke<Y: for<'a> Yokeable<'a>> { data: Y, } impl<Y: for<'a> Yokeable<'a>> Yoke<Y> { fn project<Y2: for<'a> Yokeable<'a>>(&self, _f: for<'a> fn(<Y as Yokeable<'a>>::Output, &'a ()) -> <Y2 as Yokeable<'a>>::Output) -> Yoke<Y2> { unimplemented!() } } fn _upcast<Y>(x: Yoke<Y>) -> Yoke<Box<dyn IsCovariant<'static> + 'static>> where Y: for<'a> Yokeable<'a>, for<'a> <Y as Yokeable<'a>>::Output: IsCovariant<'a> { x.project(|data, _| { Box::new(data) }) } impl<'a> Yokeable<'a> for Box<dyn IsCovariant<'static> + 'static> { type Output = Box<dyn IsCovariant<'a> + 'a>; } fn main() {} </ins>