From e5776c690328a373ec812471f7a257e6c0920881 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 27 Sep 2022 20:00:24 +0000 Subject: [PATCH] Use already resolved self_ty in confirm_fn_pointer_candidate --- .../src/traits/select/confirmation.rs | 3 +- src/test/ui/function-pointer/issue-102289.rs | 54 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/function-pointer/issue-102289.rs diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 27fbfb6dd21fb..dd49dcecf77e3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -626,7 +626,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // the signature, as evidenced by how we treat it during projection. // The safe thing to do here is to liberate it, though, which should // have no worse effect than skipping the binder here. - let liberated_fn_ty = self.infcx.replace_bound_vars_with_placeholders(obligation.self_ty()); + let liberated_fn_ty = + self.infcx.replace_bound_vars_with_placeholders(obligation.predicate.rebind(self_ty)); let output_ty = self .infcx .replace_bound_vars_with_placeholders(liberated_fn_ty.fn_sig(self.tcx()).output()); diff --git a/src/test/ui/function-pointer/issue-102289.rs b/src/test/ui/function-pointer/issue-102289.rs new file mode 100644 index 0000000000000..de394ca9ad6d4 --- /dev/null +++ b/src/test/ui/function-pointer/issue-102289.rs @@ -0,0 +1,54 @@ +// check-pass + +pub(crate) trait Parser: Sized { + type Output; + fn parse(&mut self, _input: &str) -> Result<(), ()> { + loop {} + } + fn map(self, _f: F) -> Map + where + F: FnMut(Self::Output) -> B, + { + todo!() + } +} + +pub(crate) struct Chainl1(P, Op); +impl Parser for Chainl1 +where + P: Parser, + Op: Parser, + Op::Output: FnOnce(P::Output, P::Output) -> P::Output, +{ + type Output = P::Output; +} +pub(crate) fn chainl1(_parser: P, _op: Op) -> Chainl1 +where + P: Parser, + Op: Parser, + Op::Output: FnOnce(P::Output, P::Output) -> P::Output, +{ + loop {} +} + +pub(crate) struct Map(P, F); +impl Parser for Map +where + P: Parser, + F: FnMut(A) -> B, +{ + type Output = B; +} + +impl Parser for u32 { + type Output = (); +} + +pub fn chainl1_error_consume() { + fn first(t: T, _: U) -> T { + t + } + let _ = chainl1(1, 1.map(|_| first)).parse(""); +} + +fn main() {}