Skip to content

Commit

Permalink
Elaborate supertrait obligations when deducing closure signature
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Nov 3, 2022
1 parent 060d439 commit caa701e
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 35 deletions.
18 changes: 11 additions & 7 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{self, Ty};
use rustc_span::source_map::Span;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::error_reporting::ArgKind;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
use std::cmp;
Expand Down Expand Up @@ -226,27 +227,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_vid: ty::TyVid,
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
let mut expected_sig = None;
// 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 mut expected_kind = None;

for obligation in self.obligations_for_self_ty(expected_vid) {
for obligation in traits::elaborate_obligations(
self.tcx,
self.obligations_for_self_ty(expected_vid).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()
{
// Given a Projection predicate, we can potentially infer
// the complete signature.
expected_sig = self.deduce_sig_from_projection(
Some(obligation.cause.span),
bound_predicate.rebind(proj_predicate),
);
}

// 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))
Expand Down
29 changes: 29 additions & 0 deletions src/test/ui/closures/issue-23012-supertrait-signature-inference.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// 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();
});
}
3 changes: 1 addition & 2 deletions src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// check-pass
// Regression test for issue #57611
// Ensures that we don't ICE
// FIXME: This should compile, but it currently doesn't
// known-bug: unknown

#![feature(trait_alias)]
#![feature(type_alias_impl_trait)]
Expand Down
26 changes: 0 additions & 26 deletions src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr

This file was deleted.

0 comments on commit caa701e

Please sign in to comment.