From caa701e3c190c4d77634c9075548746e4917e56d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Sep 2022 00:35:23 +0000 Subject: [PATCH] Elaborate supertrait obligations when deducing closure signature --- compiler/rustc_hir_typeck/src/closure.rs | 18 +++++++----- ...ue-23012-supertrait-signature-inference.rs | 29 +++++++++++++++++++ .../issue-57611-trait-alias.rs | 3 +- .../issue-57611-trait-alias.stderr | 26 ----------------- 4 files changed, 41 insertions(+), 35 deletions(-) create mode 100644 src/test/ui/closures/issue-23012-supertrait-signature-inference.rs delete mode 100644 src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index cc1191d32458f..4f8ac45d5a630 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -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; @@ -226,27 +227,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_vid: ty::TyVid, ) -> (Option>, Option) { 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`. 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`. 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)) diff --git a/src/test/ui/closures/issue-23012-supertrait-signature-inference.rs b/src/test/ui/closures/issue-23012-supertrait-signature-inference.rs new file mode 100644 index 0000000000000..5899b703e7c13 --- /dev/null +++ b/src/test/ui/closures/issue-23012-supertrait-signature-inference.rs @@ -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: FnOnce(Result) { + fn receive(self, res: Result); +} + +impl)> Receive for F { + fn receive(self, res: Result) { + self(res) + } +} + +pub trait Async { + fn receive>(self, f: F); +} + +impl Async for Result { + fn receive>(self, f: F) { + f(self) + } +} + +pub fn main() { + Ok::(123).receive(|res| { + res.unwrap(); + }); +} diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index 067ed7ea1e585..cad3e0f66774d 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -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)] diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr deleted file mode 100644 index 6344f114a9131..0000000000000 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ /dev/null @@ -1,26 +0,0 @@ -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`.