Change:
Repro: Output:
cc
What's causing this is that we currently inspect the obligations in scope for obligations, but in this case the obligation is (which implies a obligation as a supertrait). This is expected but unfortunate, yes. We could probably fix this particular case in a relatively straightforward way by trying to upcast each pending obligation to a obligation.
I imagine that atm this could be worked around by changing: to
Today, this gives a completely different error about not implementing ...
Updated code to not give the unrelated error (by removing bounds everywhere), still gives the type must be known error.
This comes up for me fairly regularly. It would be really nice to fix it. (e.g., it came up recently in )
We discussed this in the types team 'backlog bonanza' meeting today. Our conclusion was that this is a "nice to have" and that directly fixing this issue felt like a types team FCP, because it's a tweak to the inference rules. TL;DR right now we say If there is some trait obligation , then we take the args from it seems reasonable to say If there is some trait obligation that implies (through the "invariants", in terms) , then we take the args from that would fix this example (types team FCP would be required). However, I believe that beyond this specific example, most people who wind up here are trying to do something a bit more sophisticated, such as having an argument that might be a closure but might not, or have extended varieties of closures (). It is possible that just making the above change would fix those problems, but it's likely that further changes would be required. Those scope feels like a lang-team initiative. Still may be worth making this change just to screen out the easy cases, mind you!

Discussion:
use rustc_middle::ty::{self, Ty}; use rustc_span::source_map::Span; use rustc_target::spec::abi::Abi; <ins> use rustc_trait_selection::traits; </ins> use rustc_trait_selection::traits::error_reporting::ArgKind; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use std::cmp;

&self, expected_vid: ty::TyVid, ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) { <del> let expected_sig = self.obligations_for_self_ty(expected_vid).find_map(|(_, obligation)| { debug!(?obligation.predicate); let bound_predicate = obligation.predicate.kind(); if let ty::PredicateKind::Projection(proj_predicate) = obligation.predicate.kind().skip_binder() { // Given a Projection predicate, we can potentially infer // the complete signature. self.deduce_sig_from_projection( Some(obligation.cause.span), bound_predicate.rebind(proj_predicate), ) } else { None } }); </del> <ins> let mut expected_sig = None; let mut expected_kind = None; for obligation in traits::elaborate_obligations( self.tcx, // Reverse the obligations here, since `elaborate_*` uses a stack, // and we want to keep inference generally in the same order of // the registered obligations. self.obligations_for_self_ty(expected_vid).rev().collect(), ) { debug!(?obligation.predicate); let bound_predicate = obligation.predicate.kind(); // Given a Projection predicate, we can potentially infer // the complete signature. if expected_sig.is_none() && let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() { expected_sig = self.deduce_sig_from_projection( Some(obligation.cause.span), bound_predicate.rebind(proj_predicate), ); } </ins> <del> // Even if we can't infer the full signature, we may be able to // infer the kind. This can occur when we elaborate a predicate // like `F : Fn<A>`. Note that due to subtyping we could encounter // many viable options, so pick the most restrictive. let expected_kind = self .obligations_for_self_ty(expected_vid) .filter_map(|(tr, _)| self.tcx.fn_trait_kind_from_lang_item(tr.def_id())) .fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur)))); </del> <ins> // Even if we can't infer the full signature, we may be able to // infer the kind. This can occur when we elaborate a predicate // like `F : Fn<A>`. Note that due to subtyping we could encounter // many viable options, so pick the most restrictive. let trait_def_id = match bound_predicate.skip_binder() { ty::PredicateKind::Projection(data) => { Some(data.projection_ty.trait_def_id(self.tcx)) } ty::PredicateKind::Trait(data) => Some(data.def_id()), _ => None, }; if let Some(closure_kind) = trait_def_id.and_then(|def_id| self.tcx.fn_trait_kind_from_lang_item(def_id)) { expected_kind = Some( expected_kind .map_or_else(|| closure_kind, |current| cmp::min(current, closure_kind)), ); } } </ins> (expected_sig, expected_kind) }

let output_ty = match *ret_ty.kind() { ty::Infer(ty::TyVar(ret_vid)) => { <del> self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| { </del> <ins> self.obligations_for_self_ty(ret_vid).find_map(|obligation| { </ins> get_future_output(obligation.predicate, obligation.cause.span) })? }

use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{ <del> self, AdtKind, CanonicalUserType, DefIdTree, EarlyBinder, GenericParamDefKind, ToPolyTraitRef, ToPredicate, Ty, UserType, </del> <ins> self, AdtKind, CanonicalUserType, DefIdTree, EarlyBinder, GenericParamDefKind, ToPredicate, Ty, UserType, </ins> }; use rustc_middle::ty::{GenericArgKind, InternalSubsts, SubstsRef, UserSelfTy, UserSubsts}; use rustc_session::lint;

} #[instrument(skip(self), level = "debug")] <del> fn self_type_matches_expected_vid( &self, trait_ref: ty::PolyTraitRef<'tcx>, expected_vid: ty::TyVid, ) -> bool { let self_ty = self.shallow_resolve(trait_ref.skip_binder().self_ty()); </del> <ins> fn self_type_matches_expected_vid(&self, self_ty: Ty<'tcx>, expected_vid: ty::TyVid) -> bool { let self_ty = self.shallow_resolve(self_ty); </ins> debug!(?self_ty); match *self_ty.kind() {

pub(in super::super) fn obligations_for_self_ty<'b>( &'b self, self_ty: ty::TyVid, <del> ) -> impl Iterator<Item = (ty::PolyTraitRef<'tcx>, traits::PredicateObligation<'tcx>)> + Captures<'tcx> + 'b { </del> <ins> ) -> impl DoubleEndedIterator<Item = traits::PredicateObligation<'tcx>> + Captures<'tcx> + 'b { </ins> // FIXME: consider using `sub_root_var` here so we // can see through subtyping. let ty_var_root = self.root_var(self_ty); trace!("pending_obligations = {:#?}", self.fulfillment_cx.borrow().pending_obligations()); <del> self.fulfillment_cx .borrow() .pending_obligations() .into_iter() .filter_map(move |obligation| { let bound_predicate = obligation.predicate.kind(); match bound_predicate.skip_binder() { ty::PredicateKind::Projection(data) => Some(( bound_predicate.rebind(data).required_poly_trait_ref(self.tcx), obligation, )), ty::PredicateKind::Trait(data) => { Some((bound_predicate.rebind(data).to_poly_trait_ref(), obligation)) } ty::PredicateKind::Subtype(..) => None, ty::PredicateKind::Coerce(..) => None, ty::PredicateKind::RegionOutlives(..) => None, ty::PredicateKind::TypeOutlives(..) => None, ty::PredicateKind::WellFormed(..) => None, ty::PredicateKind::ObjectSafe(..) => None, ty::PredicateKind::ConstEvaluatable(..) => None, ty::PredicateKind::ConstEquate(..) => None, // N.B., this predicate is created by breaking down a // `ClosureType: FnFoo()` predicate, where // `ClosureType` represents some `Closure`. It can't // possibly be referring to the current closure, // because we haven't produced the `Closure` for // this closure yet; this is exactly why the other // code is looking for a self type of an unresolved // inference variable. ty::PredicateKind::ClosureKind(..) => None, ty::PredicateKind::TypeWellFormedFromEnv(..) => None, </del> <ins> self.fulfillment_cx.borrow().pending_obligations().into_iter().filter_map( move |obligation| match &obligation.predicate.kind().skip_binder() { ty::PredicateKind::Projection(data) if self.self_type_matches_expected_vid( data.projection_ty.self_ty(), ty_var_root, ) => { Some(obligation) </ins> } <del> }) .filter(move |(tr, _)| self.self_type_matches_expected_vid(*tr, ty_var_root)) </del> <ins> ty::PredicateKind::Trait(data) if self.self_type_matches_expected_vid(data.self_ty(), ty_var_root) => { Some(obligation) } ty::PredicateKind::Trait(..) | ty::PredicateKind::Projection(..) | ty::PredicateKind::Subtype(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::RegionOutlives(..) | ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::WellFormed(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) // N.B., this predicate is created by breaking down a // `ClosureType: FnFoo()` predicate, where // `ClosureType` represents some `Closure`. It can't // possibly be referring to the current closure, // because we haven't produced the `Closure` for // this closure yet; this is exactly why the other // code is looking for a self type of an unresolved // inference variable. | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, }, ) </ins> } pub(in super::super) fn type_var_is_sized(&self, self_ty: ty::TyVid) -> bool { <del> self.obligations_for_self_ty(self_ty) .any(|(tr, _)| Some(tr.def_id()) == self.tcx.lang_items().sized_trait()) </del> <ins> let sized_did = self.tcx.lang_items().sized_trait(); self.obligations_for_self_ty(self_ty).any(|obligation| { match obligation.predicate.kind().skip_binder() { ty::PredicateKind::Trait(data) => Some(data.def_id()) == sized_did, _ => false, } }) </ins> } pub(in super::super) fn err_args(&self, len: usize) -> Vec<Ty<'tcx>> {

<ins> // check-pass // Checks that we can infer a closure signature even if the `FnOnce` bound is // a supertrait of the obligations we have currently registered for the Ty var. pub trait Receive<T, E>: FnOnce(Result<T, E>) { fn receive(self, res: Result<T, E>); } impl<T, E, F: FnOnce(Result<T, E>)> Receive<T, E> for F { fn receive(self, res: Result<T, E>) { self(res) } } pub trait Async<T, E> { fn receive<F: Receive<T, E>>(self, f: F); } impl<T, E> Async<T, E> for Result<T, E> { fn receive<F: Receive<T, E>>(self, f: F) { f(self) } } pub fn main() { Ok::<u32, ()>(123).receive(|res| { res.unwrap(); }); } </ins>

<ins> // check-pass </ins> // Regression test for issue #57611 // Ensures that we don't ICE <del> // FIXME: This should compile, but it currently doesn't // known-bug: unknown </del> #![feature(trait_alias)] #![feature(type_alias_impl_trait)]

<del> error[E0308]: mismatched types --> $DIR/issue-57611-trait-alias.rs:21:9 | LL |         |x| x |         ^^^^^ one type is more general than the other | = note: expected trait `for<'a> Fn<(&'a X,)>` found trait `Fn<(&X,)>` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-57611-trait-alias.rs:21:9 | LL |         |x| x |         ^^^ error: implementation of `FnOnce` is not general enough --> $DIR/issue-57611-trait-alias.rs:21:9 | LL |         |x| x |         ^^^^^ implementation of `FnOnce` is not general enough | = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. </del>