From 5f59b7f7634ac4b05923b47de00f2a13b213af1f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 9 Mar 2024 22:12:33 +0000 Subject: [PATCH 1/2] Instantiate closure-like bounds with placeholders to deal with binders correctly --- .../src/traits/select/confirmation.rs | 150 ++++++++++-------- .../src/traits/select/mod.rs | 20 +-- .../builtin-closure-like-bounds.rs | 51 ++++++ 3 files changed, 139 insertions(+), 82 deletions(-) create mode 100644 tests/ui/higher-ranked/builtin-closure-like-bounds.rs diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 6f512a1173f5d..47f136cb2b778 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -678,17 +678,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn_host_effect: ty::Const<'tcx>, ) -> Result>, SelectionError<'tcx>> { debug!(?obligation, "confirm_fn_pointer_candidate"); + let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let tcx = self.tcx(); - - let Some(self_ty) = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars()) else { - // FIXME: Ideally we'd support `for<'a> fn(&'a ()): Fn(&'a ())`, - // but we do not currently. Luckily, such a bound is not - // particularly useful, so we don't expect users to write - // them often. - return Err(SelectionError::Unimplemented); - }; - let sig = self_ty.fn_sig(tcx); let trait_ref = closure_trait_ref_and_return_type( tcx, @@ -700,7 +693,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) .map_bound(|(trait_ref, _)| trait_ref); - let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; + let mut nested = self.equate_trait_refs( + &obligation.cause, + obligation.param_env, + placeholder_predicate.trait_ref, + trait_ref, + )?; let cause = obligation.derived_cause(BuiltinDerivedObligation); // Confirm the `type Output: Sized;` bound that is present on `FnOnce` @@ -748,10 +746,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result>, SelectionError<'tcx>> { - // Okay to skip binder because the args on coroutine types never - // touch bound regions, they just capture the in-scope - // type/region parameters. - let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); + let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { bug!("closure candidate for non-closure {:?}", obligation); }; @@ -760,15 +756,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let coroutine_sig = args.as_coroutine().sig(); - // NOTE: The self-type is a coroutine type and hence is - // in fact unparameterized (or at least does not reference any - // regions bound in the obligation). - let self_ty = obligation - .predicate - .self_ty() - .no_bound_vars() - .expect("unboxed closure type should not capture bound vars from the predicate"); - let (trait_ref, _, _) = super::util::coroutine_trait_ref_and_outputs( self.tcx(), obligation.predicate.def_id(), @@ -776,7 +763,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { coroutine_sig, ); - let nested = self.confirm_poly_trait_refs(obligation, ty::Binder::dummy(trait_ref))?; + let nested = self.equate_trait_refs( + &obligation.cause, + obligation.param_env, + placeholder_predicate.trait_ref, + ty::Binder::dummy(trait_ref), + )?; debug!(?trait_ref, ?nested, "coroutine candidate obligations"); Ok(nested) @@ -786,10 +778,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result>, SelectionError<'tcx>> { - // Okay to skip binder because the args on coroutine types never - // touch bound regions, they just capture the in-scope - // type/region parameters. - let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); + let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { bug!("closure candidate for non-closure {:?}", obligation); }; @@ -801,11 +791,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let (trait_ref, _) = super::util::future_trait_ref_and_outputs( self.tcx(), obligation.predicate.def_id(), - obligation.predicate.no_bound_vars().expect("future has no bound vars").self_ty(), + self_ty, coroutine_sig, ); - let nested = self.confirm_poly_trait_refs(obligation, ty::Binder::dummy(trait_ref))?; + let nested = self.equate_trait_refs( + &obligation.cause, + obligation.param_env, + placeholder_predicate.trait_ref, + ty::Binder::dummy(trait_ref), + )?; debug!(?trait_ref, ?nested, "future candidate obligations"); Ok(nested) @@ -815,10 +810,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result>, SelectionError<'tcx>> { - // Okay to skip binder because the args on coroutine types never - // touch bound regions, they just capture the in-scope - // type/region parameters. - let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); + let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { bug!("closure candidate for non-closure {:?}", obligation); }; @@ -830,11 +823,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let (trait_ref, _) = super::util::iterator_trait_ref_and_outputs( self.tcx(), obligation.predicate.def_id(), - obligation.predicate.no_bound_vars().expect("iterator has no bound vars").self_ty(), + self_ty, gen_sig, ); - let nested = self.confirm_poly_trait_refs(obligation, ty::Binder::dummy(trait_ref))?; + let nested = self.equate_trait_refs( + &obligation.cause, + obligation.param_env, + placeholder_predicate.trait_ref, + ty::Binder::dummy(trait_ref), + )?; debug!(?trait_ref, ?nested, "iterator candidate obligations"); Ok(nested) @@ -844,10 +842,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result>, SelectionError<'tcx>> { - // Okay to skip binder because the args on coroutine types never - // touch bound regions, they just capture the in-scope - // type/region parameters. - let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); + let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { bug!("closure candidate for non-closure {:?}", obligation); }; @@ -859,11 +855,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let (trait_ref, _) = super::util::async_iterator_trait_ref_and_outputs( self.tcx(), obligation.predicate.def_id(), - obligation.predicate.no_bound_vars().expect("iterator has no bound vars").self_ty(), + self_ty, gen_sig, ); - let nested = self.confirm_poly_trait_refs(obligation, ty::Binder::dummy(trait_ref))?; + let nested = self.equate_trait_refs( + &obligation.cause, + obligation.param_env, + placeholder_predicate.trait_ref, + ty::Binder::dummy(trait_ref), + )?; debug!(?trait_ref, ?nested, "iterator candidate obligations"); Ok(nested) @@ -874,14 +875,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result>, SelectionError<'tcx>> { - // Okay to skip binder because the args on closure types never - // touch bound regions, they just capture the in-scope - // type/region parameters. - let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); + let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let self_ty: Ty<'_> = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); + let trait_ref = match *self_ty.kind() { - ty::Closure(_, args) => { - self.closure_trait_ref_unnormalized(obligation, args, self.tcx().consts.true_) - } + ty::Closure(..) => self.closure_trait_ref_unnormalized( + self_ty, + obligation.predicate.def_id(), + self.tcx().consts.true_, + ), ty::CoroutineClosure(_, args) => { args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| { ty::TraitRef::new( @@ -896,7 +898,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } }; - self.confirm_poly_trait_refs(obligation, trait_ref) + self.equate_trait_refs( + &obligation.cause, + obligation.param_env, + placeholder_predicate.trait_ref, + trait_ref, + ) } #[instrument(skip(self), level = "debug")] @@ -904,8 +911,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result>, SelectionError<'tcx>> { + let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); + let tcx = self.tcx(); - let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); let mut nested = vec![]; let (trait_ref, kind_ty) = match *self_ty.kind() { @@ -972,7 +981,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => bug!("expected callable type for AsyncFn candidate"), }; - nested.extend(self.confirm_poly_trait_refs(obligation, trait_ref)?); + nested.extend(self.equate_trait_refs( + &obligation.cause, + obligation.param_env, + placeholder_predicate.trait_ref, + trait_ref, + )?); let goal_kind = self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap(); @@ -1025,34 +1039,34 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// selection of the impl. Therefore, if there is a mismatch, we /// report an error to the user. #[instrument(skip(self), level = "trace")] - fn confirm_poly_trait_refs( + fn equate_trait_refs( &mut self, - obligation: &PolyTraitObligation<'tcx>, - self_ty_trait_ref: ty::PolyTraitRef<'tcx>, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + obligation_trait_ref: ty::TraitRef<'tcx>, + found_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result>, SelectionError<'tcx>> { - let obligation_trait_ref = - self.infcx.enter_forall_and_leak_universe(obligation.predicate.to_poly_trait_ref()); - let self_ty_trait_ref = self.infcx.instantiate_binder_with_fresh_vars( - obligation.cause.span, + let found_trait_ref = self.infcx.instantiate_binder_with_fresh_vars( + cause.span, HigherRankedType, - self_ty_trait_ref, + found_trait_ref, ); // Normalize the obligation and expected trait refs together, because why not - let Normalized { obligations: nested, value: (obligation_trait_ref, expected_trait_ref) } = + let Normalized { obligations: nested, value: (obligation_trait_ref, found_trait_ref) } = ensure_sufficient_stack(|| { normalize_with_depth( self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - (obligation_trait_ref, self_ty_trait_ref), + param_env, + cause.clone(), + 0, + (obligation_trait_ref, found_trait_ref), ) }); // needed to define opaque types for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs self.infcx - .at(&obligation.cause, obligation.param_env) - .eq(DefineOpaqueTypes::Yes, obligation_trait_ref, expected_trait_ref) + .at(&cause, param_env) + .eq(DefineOpaqueTypes::Yes, obligation_trait_ref, found_trait_ref) .map(|InferOk { mut obligations, .. }| { obligations.extend(nested); obligations @@ -1060,7 +1074,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map_err(|terr| { SignatureMismatch(Box::new(SignatureMismatchData { expected_trait_ref: ty::Binder::dummy(obligation_trait_ref), - found_trait_ref: ty::Binder::dummy(expected_trait_ref), + found_trait_ref: ty::Binder::dummy(found_trait_ref), terr, })) }) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 1894fbba30270..084f7b1a8c21b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2679,26 +2679,18 @@ impl<'tcx> SelectionContext<'_, 'tcx> { #[instrument(skip(self), level = "debug")] fn closure_trait_ref_unnormalized( &mut self, - obligation: &PolyTraitObligation<'tcx>, - args: GenericArgsRef<'tcx>, + self_ty: Ty<'tcx>, + fn_trait_def_id: DefId, fn_host_effect: ty::Const<'tcx>, ) -> ty::PolyTraitRef<'tcx> { + let ty::Closure(_, args) = *self_ty.kind() else { + bug!("expected closure, found {self_ty}"); + }; let closure_sig = args.as_closure().sig(); - debug!(?closure_sig); - - // NOTE: The self-type is an unboxed closure type and hence is - // in fact unparameterized (or at least does not reference any - // regions bound in the obligation). - let self_ty = obligation - .predicate - .self_ty() - .no_bound_vars() - .expect("unboxed closure type should not capture bound vars from the predicate"); - closure_trait_ref_and_return_type( self.tcx(), - obligation.predicate.def_id(), + fn_trait_def_id, self_ty, closure_sig, util::TupleArgumentsFlag::No, diff --git a/tests/ui/higher-ranked/builtin-closure-like-bounds.rs b/tests/ui/higher-ranked/builtin-closure-like-bounds.rs new file mode 100644 index 0000000000000..c7dfaefbc74b7 --- /dev/null +++ b/tests/ui/higher-ranked/builtin-closure-like-bounds.rs @@ -0,0 +1,51 @@ +//@ edition:2024 +//@ compile-flags: -Zunstable-options +//@ revisions: current next +//@[next] compile-flags: -Znext-solver + +#![feature(unboxed_closures, gen_blocks)] + +trait Dispatch { + fn dispatch(self); +} + +struct Fut(T); +impl Fn<(&'a (),)>> Dispatch for Fut +where + for<'a> >::Output: Future, +{ + fn dispatch(self) { + (self.0)(&()); + } +} + +struct Gen(T); +impl Fn<(&'a (),)>> Dispatch for Gen +where + for<'a> >::Output: Iterator, +{ + fn dispatch(self) { + (self.0)(&()); + } +} + +struct Closure(T); +impl Fn<(&'a (),)>> Dispatch for Closure +where + for<'a> >::Output: Fn<(&'a (),)>, +{ + fn dispatch(self) { + (self.0)(&())(&()); + } +} + +fn main() { + async fn foo(_: &()) {} + Fut(foo).dispatch(); + + gen fn bar(_: &()) {} + Gen(bar).dispatch(); + + fn uwu<'a>(x: &'a ()) -> impl Fn(&'a ()) { |_| {} } + Closure(uwu).dispatch(); +} \ No newline at end of file From 09ea3f93ee6497247172a80ba17493748d08b64c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 10 Mar 2024 05:14:11 +0000 Subject: [PATCH 2/2] Fix obligation param and bless tests --- .../src/traits/select/confirmation.rs | 58 ++++++------------- .../builtin-closure-like-bounds.rs | 9 ++- .../closure-bound-codegen-ice.rs | 33 +++++++++++ .../trait-bounds/fn-ptr.classic.stderr | 19 ------ .../trait-bounds/fn-ptr.current.stderr | 19 ------ tests/ui/higher-ranked/trait-bounds/fn-ptr.rs | 3 +- .../trait-bounds/future.classic.stderr | 6 -- .../trait-bounds/future.current.stderr | 6 -- tests/ui/higher-ranked/trait-bounds/future.rs | 9 +-- tests/ui/lifetimes/issue-105675.rs | 2 +- .../lifetimes/lifetime-errors/issue_74400.rs | 4 +- 11 files changed, 64 insertions(+), 104 deletions(-) create mode 100644 tests/ui/higher-ranked/closure-bound-codegen-ice.rs delete mode 100644 tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr delete mode 100644 tests/ui/higher-ranked/trait-bounds/fn-ptr.current.stderr delete mode 100644 tests/ui/higher-ranked/trait-bounds/future.classic.stderr delete mode 100644 tests/ui/higher-ranked/trait-bounds/future.current.stderr diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 47f136cb2b778..0459246553b0b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -28,7 +28,7 @@ use crate::traits::{ BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource, ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause, PolyTraitObligation, PredicateObligation, Selection, SelectionError, SignatureMismatch, TraitNotObjectSafe, - Unimplemented, + TraitObligation, Unimplemented, }; use super::BuiltinImplConditions; @@ -693,12 +693,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) .map_bound(|(trait_ref, _)| trait_ref); - let mut nested = self.equate_trait_refs( - &obligation.cause, - obligation.param_env, - placeholder_predicate.trait_ref, - trait_ref, - )?; + let mut nested = + self.equate_trait_refs(obligation.with(tcx, placeholder_predicate), trait_ref)?; let cause = obligation.derived_cause(BuiltinDerivedObligation); // Confirm the `type Output: Sized;` bound that is present on `FnOnce` @@ -764,9 +760,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); let nested = self.equate_trait_refs( - &obligation.cause, - obligation.param_env, - placeholder_predicate.trait_ref, + obligation.with(self.tcx(), placeholder_predicate), ty::Binder::dummy(trait_ref), )?; debug!(?trait_ref, ?nested, "coroutine candidate obligations"); @@ -796,9 +790,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); let nested = self.equate_trait_refs( - &obligation.cause, - obligation.param_env, - placeholder_predicate.trait_ref, + obligation.with(self.tcx(), placeholder_predicate), ty::Binder::dummy(trait_ref), )?; debug!(?trait_ref, ?nested, "future candidate obligations"); @@ -828,9 +820,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); let nested = self.equate_trait_refs( - &obligation.cause, - obligation.param_env, - placeholder_predicate.trait_ref, + obligation.with(self.tcx(), placeholder_predicate), ty::Binder::dummy(trait_ref), )?; debug!(?trait_ref, ?nested, "iterator candidate obligations"); @@ -860,9 +850,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); let nested = self.equate_trait_refs( - &obligation.cause, - obligation.param_env, - placeholder_predicate.trait_ref, + obligation.with(self.tcx(), placeholder_predicate), ty::Binder::dummy(trait_ref), )?; debug!(?trait_ref, ?nested, "iterator candidate obligations"); @@ -898,12 +886,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } }; - self.equate_trait_refs( - &obligation.cause, - obligation.param_env, - placeholder_predicate.trait_ref, - trait_ref, - ) + self.equate_trait_refs(obligation.with(self.tcx(), placeholder_predicate), trait_ref) } #[instrument(skip(self), level = "debug")] @@ -981,12 +964,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => bug!("expected callable type for AsyncFn candidate"), }; - nested.extend(self.equate_trait_refs( - &obligation.cause, - obligation.param_env, - placeholder_predicate.trait_ref, - trait_ref, - )?); + nested.extend( + self.equate_trait_refs(obligation.with(tcx, placeholder_predicate), trait_ref)?, + ); let goal_kind = self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap(); @@ -1041,13 +1021,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[instrument(skip(self), level = "trace")] fn equate_trait_refs( &mut self, - cause: &ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - obligation_trait_ref: ty::TraitRef<'tcx>, + obligation: TraitObligation<'tcx>, found_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result>, SelectionError<'tcx>> { let found_trait_ref = self.infcx.instantiate_binder_with_fresh_vars( - cause.span, + obligation.cause.span, HigherRankedType, found_trait_ref, ); @@ -1056,16 +1034,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ensure_sufficient_stack(|| { normalize_with_depth( self, - param_env, - cause.clone(), - 0, - (obligation_trait_ref, found_trait_ref), + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + (obligation.predicate.trait_ref, found_trait_ref), ) }); // needed to define opaque types for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs self.infcx - .at(&cause, param_env) + .at(&obligation.cause, obligation.param_env) .eq(DefineOpaqueTypes::Yes, obligation_trait_ref, found_trait_ref) .map(|InferOk { mut obligations, .. }| { obligations.extend(nested); diff --git a/tests/ui/higher-ranked/builtin-closure-like-bounds.rs b/tests/ui/higher-ranked/builtin-closure-like-bounds.rs index c7dfaefbc74b7..dee290cc4396a 100644 --- a/tests/ui/higher-ranked/builtin-closure-like-bounds.rs +++ b/tests/ui/higher-ranked/builtin-closure-like-bounds.rs @@ -2,6 +2,13 @@ //@ compile-flags: -Zunstable-options //@ revisions: current next //@[next] compile-flags: -Znext-solver +//@ check-pass + +// Makes sure that we support closure/coroutine goals where the signature of +// the item references higher-ranked lifetimes from the *predicate* binder, +// not its own internal signature binder. +// +// This was fixed in . #![feature(unboxed_closures, gen_blocks)] @@ -48,4 +55,4 @@ fn main() { fn uwu<'a>(x: &'a ()) -> impl Fn(&'a ()) { |_| {} } Closure(uwu).dispatch(); -} \ No newline at end of file +} diff --git a/tests/ui/higher-ranked/closure-bound-codegen-ice.rs b/tests/ui/higher-ranked/closure-bound-codegen-ice.rs new file mode 100644 index 0000000000000..4d7ae12d7a742 --- /dev/null +++ b/tests/ui/higher-ranked/closure-bound-codegen-ice.rs @@ -0,0 +1,33 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ build-pass + +// Regression test for incomplete handling of Fn-trait goals, +// fixed in #122267. + +trait Trait { + type Assoc<'a>: FnOnce(&'a ()); +} + +impl Trait for () { + type Assoc<'a> = fn(&'a ()); +} + +trait Indir { + fn break_me() {} +} + +impl Indir for F +where + for<'a> F::Assoc<'a>: FnOnce(&'a ()), +{ + fn break_me() {} +} + +fn foo() { + F::break_me() +} + +fn main() { + foo::<()>(); +} diff --git a/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr b/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr deleted file mode 100644 index b322ea41c436d..0000000000000 --- a/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0277]: expected a `Fn(&'w ())` closure, found `fn(&'w ())` - --> $DIR/fn-ptr.rs:12:5 - | -LL | ice(); - | ^^^^^ expected an `Fn(&'w ())` closure, found `fn(&'w ())` - | - = help: the trait `for<'w> Fn<(&'w (),)>` is not implemented for `fn(&'w ())` -note: required by a bound in `ice` - --> $DIR/fn-ptr.rs:7:25 - | -LL | fn ice() - | --- required by a bound in this function -LL | where -LL | for<'w> fn(&'w ()): Fn(&'w ()), - | ^^^^^^^^^^ required by this bound in `ice` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/fn-ptr.current.stderr b/tests/ui/higher-ranked/trait-bounds/fn-ptr.current.stderr deleted file mode 100644 index f3583cd218b8c..0000000000000 --- a/tests/ui/higher-ranked/trait-bounds/fn-ptr.current.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0277]: expected a `Fn(&'w ())` closure, found `fn(&'w ())` - --> $DIR/fn-ptr.rs:13:5 - | -LL | ice(); - | ^^^^^ expected an `Fn(&'w ())` closure, found `fn(&'w ())` - | - = help: the trait `for<'w> Fn<(&'w (),)>` is not implemented for `fn(&'w ())` -note: required by a bound in `ice` - --> $DIR/fn-ptr.rs:8:25 - | -LL | fn ice() - | --- required by a bound in this function -LL | where -LL | for<'w> fn(&'w ()): Fn(&'w ()), - | ^^^^^^^^^^ required by this bound in `ice` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/fn-ptr.rs b/tests/ui/higher-ranked/trait-bounds/fn-ptr.rs index 9298c10c3417c..7a4c15f4d4b15 100644 --- a/tests/ui/higher-ranked/trait-bounds/fn-ptr.rs +++ b/tests/ui/higher-ranked/trait-bounds/fn-ptr.rs @@ -1,7 +1,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@[next] check-pass +//@ check-pass fn ice() where @@ -11,5 +11,4 @@ where fn main() { ice(); - //[current]~^ ERROR expected a `Fn(&'w ())` closure, found `fn(&'w ())` } diff --git a/tests/ui/higher-ranked/trait-bounds/future.classic.stderr b/tests/ui/higher-ranked/trait-bounds/future.classic.stderr deleted file mode 100644 index ef31b7266c7ef..0000000000000 --- a/tests/ui/higher-ranked/trait-bounds/future.classic.stderr +++ /dev/null @@ -1,6 +0,0 @@ -error: the compiler unexpectedly panicked. this is a bug. - -query stack during panic: -#0 [evaluate_obligation] evaluating trait selection obligation `for<'a> {async fn body@$DIR/future.rs:32:35: 34:2}: core::future::future::Future` -#1 [codegen_select_candidate] computing candidate for `` -end of query stack diff --git a/tests/ui/higher-ranked/trait-bounds/future.current.stderr b/tests/ui/higher-ranked/trait-bounds/future.current.stderr deleted file mode 100644 index 673bc48a424e7..0000000000000 --- a/tests/ui/higher-ranked/trait-bounds/future.current.stderr +++ /dev/null @@ -1,6 +0,0 @@ -error: the compiler unexpectedly panicked. this is a bug. - -query stack during panic: -#0 [evaluate_obligation] evaluating trait selection obligation `for<'a> {async fn body of strlen()}: core::future::future::Future` -#1 [codegen_select_candidate] computing candidate for `` -end of query stack diff --git a/tests/ui/higher-ranked/trait-bounds/future.rs b/tests/ui/higher-ranked/trait-bounds/future.rs index 4b52f04dbe05f..7105015b69012 100644 --- a/tests/ui/higher-ranked/trait-bounds/future.rs +++ b/tests/ui/higher-ranked/trait-bounds/future.rs @@ -3,14 +3,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@[next] check-pass -//@[current] known-bug: #112347 -//@[current] build-fail -//@[current] failure-status: 101 -//@[current] normalize-stderr-test "note: .*\n\n" -> "" -//@[current] normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> "" -//@[current] normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " -//@[current] rustc-env:RUST_BACKTRACE=0 +//@ check-pass #![feature(unboxed_closures)] diff --git a/tests/ui/lifetimes/issue-105675.rs b/tests/ui/lifetimes/issue-105675.rs index 2e2eaca0d335c..0472537e7f34c 100644 --- a/tests/ui/lifetimes/issue-105675.rs +++ b/tests/ui/lifetimes/issue-105675.rs @@ -4,7 +4,7 @@ fn main() { let f = | _ , y: &u32 , z | (); thing(f); //~^ ERROR implementation of `FnOnce` is not general enough - //~^^ ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough let f = | x, y: _ , z: u32 | (); thing(f); //~^ ERROR implementation of `FnOnce` is not general enough diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs index b02e38bec3b3e..72345fa294a43 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs @@ -1,5 +1,5 @@ //! Regression test for #74400: Type mismatch in function arguments E0631, E0271 are falsely -//! recognized as E0308 mismatched types. +//! recognized as "implementation of `FnOnce` is not general enough". use std::convert::identity; @@ -13,6 +13,6 @@ fn g(data: &[T]) { //~^ ERROR the parameter type //~| ERROR the parameter type //~| ERROR the parameter type - //~| ERROR implementation of `FnOnce` is not general + //~| ERROR implementation of `FnOnce` is not general enough //~| ERROR implementation of `Fn` is not general enough }