From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- .../normalize-under-binder/issue-62529-1.rs | 88 ++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs (limited to 'src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs') diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs new file mode 100644 index 000000000..c6f29fa59 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs @@ -0,0 +1,88 @@ +// check-pass + +// FamilyType (GAT workaround) +pub trait FamilyLt<'a> { + type Out; +} + +struct RefMutFamily(std::marker::PhantomData, ()); +impl<'a, T: 'a> FamilyLt<'a> for RefMutFamily { + type Out = &'a mut T; +} + +pub trait Execute { + type E: Inject; + fn execute(self, value: <::I as FamilyLt>::Out); +} + +pub trait Inject +where + Self: Sized, +{ + type I: for<'a> FamilyLt<'a>; + fn inject(_: &()) -> ::Out; +} + +impl Inject for RefMutFamily { + type I = Self; + fn inject(_: &()) -> ::Out { + unimplemented!() + } +} + +// This struct is only used to give a hint to the compiler about the type `Q` +struct Annotate(std::marker::PhantomData); +impl Annotate { + fn new() -> Self { + Self(std::marker::PhantomData) + } +} + +// This function annotate a closure so it can have Higher-Rank Lifetime Bounds +// +// See 'annotate' workaround: https://github.com/rust-lang/rust/issues/58052 +fn annotate(_q: Annotate, func: F) -> impl Execute + 'static +where + F: for<'r> FnOnce(<::I as FamilyLt<'r>>::Out) + 'static, + Q: Inject + 'static, +{ + let wrapper: Wrapper = Wrapper(std::marker::PhantomData, func); + wrapper +} + +struct Wrapper(std::marker::PhantomData, F); +impl Execute for Wrapper + where + Q: Inject, + F: for<'r> FnOnce(<::I as FamilyLt<'r>>::Out), +{ + type E = Q; + + fn execute(self, value: <::I as FamilyLt>::Out) { + (self.1)(value) + } +} + +struct Task { + _processor: Box, +} + +// This function consume the closure +fn task

(processor: P) -> Task +where P: Execute + 'static { + Task { + _processor: Box::new(move || { + let q = P::E::inject(&()); + processor.execute(q); + }) + } +} + +fn main() { + task(annotate( + Annotate::>::new(), + |value: &mut usize| { + *value = 2; + } + )); +} -- cgit v1.2.3