diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index f7559a3f10ad1..7dae527712060 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1817,7 +1817,7 @@ fn confirm_generator_candidate<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, impl_source: ImplSourceGeneratorData<'tcx, PredicateObligation<'tcx>>, ) -> Progress<'tcx> { - let gen_sig = impl_source.substs.as_generator().poly_sig(); + let gen_sig = impl_source.substs.as_generator().sig(); let Normalized { value: gen_sig, obligations } = normalize_with_depth( selcx, obligation.param_env, @@ -1832,26 +1832,24 @@ fn confirm_generator_candidate<'cx, 'tcx>( let gen_def_id = tcx.require_lang_item(LangItem::Generator, None); - let predicate = super::util::generator_trait_ref_and_outputs( + let (trait_ref, yield_ty, return_ty) = super::util::generator_trait_ref_and_outputs( tcx, gen_def_id, obligation.predicate.self_ty(), gen_sig, - ) - .map_bound(|(trait_ref, yield_ty, return_ty)| { - let name = tcx.associated_item(obligation.predicate.def_id).name; - let ty = if name == sym::Return { - return_ty - } else if name == sym::Yield { - yield_ty - } else { - bug!() - }; + ); - ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs), - term: ty.into(), - } + let name = tcx.associated_item(obligation.predicate.def_id).name; + let ty = if name == sym::Return { + return_ty + } else if name == sym::Yield { + yield_ty + } else { + bug!() + }; + let predicate = ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs), + term: ty.into(), }); confirm_param_env_candidate(selcx, obligation, predicate, false) @@ -1864,7 +1862,7 @@ fn confirm_future_candidate<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, impl_source: ImplSourceFutureData<'tcx, PredicateObligation<'tcx>>, ) -> Progress<'tcx> { - let gen_sig = impl_source.substs.as_generator().poly_sig(); + let gen_sig = impl_source.substs.as_generator().sig(); let Normalized { value: gen_sig, obligations } = normalize_with_depth( selcx, obligation.param_env, @@ -1878,19 +1876,17 @@ fn confirm_future_candidate<'cx, 'tcx>( let tcx = selcx.tcx(); let fut_def_id = tcx.require_lang_item(LangItem::Future, None); - let predicate = super::util::future_trait_ref_and_outputs( + let (trait_ref, return_ty) = super::util::future_trait_ref_and_outputs( tcx, fut_def_id, obligation.predicate.self_ty(), gen_sig, - ) - .map_bound(|(trait_ref, return_ty)| { - debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output); + ); - ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs), - term: return_ty.into(), - } + debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output); + let predicate = ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs), + term: return_ty.into(), }); confirm_param_env_candidate(selcx, obligation, predicate, false) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 21c158fd0fddd..c9e52e49368be 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::{ use rustc_session::config::TraitSolver; use rustc_span::def_id::DefId; -use crate::traits::project::{normalize_with_depth, normalize_with_depth_to}; +use crate::traits::project::normalize_with_depth_to; use crate::traits::util::{self, closure_trait_ref_and_return_type, predicate_for_trait_def}; use crate::traits::vtable::{ count_own_vtable_entries, prepare_vtable_segments, vtable_trait_first_method_offset, @@ -598,13 +598,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { is_const: bool, ) -> Result>, SelectionError<'tcx>> { + let mut nested = vec![]; + let placeholder_trait_pred = + self.infcx.instantiate_binder_with_placeholders(obligation.predicate); + let placeholder_trait_pred = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + placeholder_trait_pred, + &mut nested, + ); + debug!(?obligation, "confirm_fn_pointer_candidate"); let tcx = self.tcx(); - let self_ty = self - .infcx - .shallow_resolve(obligation.self_ty().no_bound_vars()) - .expect("fn pointer should not capture bound vars from predicate"); + + let self_ty = self.infcx.shallow_resolve(placeholder_trait_pred.self_ty()); let sig = self_ty.fn_sig(tcx); let trait_ref = closure_trait_ref_and_return_type( tcx, @@ -615,9 +625,37 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) .map_bound(|(trait_ref, _)| trait_ref); - let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; - let cause = obligation.derived_cause(BuiltinDerivedObligation); + let instantiated_trait_ref = self.infcx.instantiate_binder_with_fresh_vars( + obligation.cause.span, + rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType, + trait_ref, + ); + let instantiated_trait_ref = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + instantiated_trait_ref, + &mut nested, + ); + + nested.extend( + self.infcx + .at(&obligation.cause, obligation.param_env) + // needed for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs + .define_opaque_types(true) + .eq(placeholder_trait_pred.trait_ref, instantiated_trait_ref) + .map_err(|e| { + OutputTypeParameterMismatch( + trait_ref, + obligation.predicate.to_poly_trait_ref(), + e, + ) + })? + .into_obligations(), + ); + let cause = obligation.derived_cause(BuiltinDerivedObligation); if obligation.is_const() && !is_const { // function is a trait method if let ty::FnDef(def_id, substs) = self_ty.kind() && let Some(trait_id) = tcx.trait_of_item(*def_id) { @@ -676,18 +714,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, ) -> Result>, SelectionError<'tcx>> { - // Okay to skip binder because the substs on generator 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 mut nested = vec![]; + let placeholder_trait_pred = + self.infcx.instantiate_binder_with_placeholders(obligation.predicate); + let placeholder_trait_pred = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + placeholder_trait_pred, + &mut nested, + ); + + let self_ty = self.infcx.shallow_resolve(placeholder_trait_pred.self_ty()); let ty::Generator(generator_def_id, substs, _) = *self_ty.kind() else { bug!("closure candidate for non-closure {:?}", obligation); }; debug!(?obligation, ?generator_def_id, ?substs, "confirm_generator_candidate"); - let gen_sig = substs.as_generator().poly_sig(); - + let gen_sig = substs.as_generator().sig(); // NOTE: The self-type is a generator type and hence is // in fact unparameterized (or at least does not reference any // regions bound in the obligation). @@ -697,15 +743,28 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .no_bound_vars() .expect("unboxed closure type should not capture bound vars from the predicate"); - let trait_ref = super::util::generator_trait_ref_and_outputs( + let (trait_ref, _, _) = super::util::generator_trait_ref_and_outputs( self.tcx(), obligation.predicate.def_id(), self_ty, gen_sig, - ) - .map_bound(|(trait_ref, ..)| trait_ref); + ); - let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; + nested.extend( + self.infcx + .at(&obligation.cause, obligation.param_env) + // needed for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs + .define_opaque_types(true) + .eq(placeholder_trait_pred.trait_ref, trait_ref) + .map_err(|e| { + OutputTypeParameterMismatch( + ty::Binder::dummy(trait_ref), + obligation.predicate.to_poly_trait_ref(), + e, + ) + })? + .into_obligations(), + ); debug!(?trait_ref, ?nested, "generator candidate obligations"); Ok(ImplSourceGeneratorData { generator_def_id, substs, nested }) @@ -715,27 +774,53 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, ) -> Result>, SelectionError<'tcx>> { + let mut nested = vec![]; + let placeholder_trait_pred = + self.infcx.instantiate_binder_with_placeholders(obligation.predicate); + let placeholder_trait_pred = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + placeholder_trait_pred, + &mut nested, + ); + // Okay to skip binder because the substs on generator 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 self_ty = self.infcx.shallow_resolve(placeholder_trait_pred.self_ty()); let ty::Generator(generator_def_id, substs, _) = *self_ty.kind() else { bug!("closure candidate for non-closure {:?}", obligation); }; debug!(?obligation, ?generator_def_id, ?substs, "confirm_future_candidate"); - let gen_sig = substs.as_generator().poly_sig(); + let gen_sig = substs.as_generator().sig(); - let trait_ref = super::util::future_trait_ref_and_outputs( + 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(), gen_sig, - ) - .map_bound(|(trait_ref, ..)| trait_ref); + ); + + nested.extend( + self.infcx + .at(&obligation.cause, obligation.param_env) + // needed for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs + .define_opaque_types(true) + .eq(placeholder_trait_pred.trait_ref, trait_ref) + .map_err(|e| { + OutputTypeParameterMismatch( + ty::Binder::dummy(trait_ref), + obligation.predicate.to_poly_trait_ref(), + e, + ) + })? + .into_obligations(), + ); - let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; debug!(?trait_ref, ?nested, "future candidate obligations"); Ok(ImplSourceFutureData { generator_def_id, substs, nested }) @@ -746,23 +831,57 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, ) -> Result>, SelectionError<'tcx>> { + let mut nested = vec![]; + let placeholder_trait_pred = + self.infcx.instantiate_binder_with_placeholders(obligation.predicate); + let placeholder_trait_pred = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + placeholder_trait_pred, + &mut nested, + ); + let kind = self .tcx() - .fn_trait_kind_from_def_id(obligation.predicate.def_id()) + .fn_trait_kind_from_def_id(placeholder_trait_pred.def_id()) .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation)); - // Okay to skip binder because the substs 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 self_ty = self.infcx.shallow_resolve(placeholder_trait_pred.self_ty()); let ty::Closure(closure_def_id, substs) = *self_ty.kind() else { bug!("closure candidate for non-closure {:?}", obligation); }; let trait_ref = self.closure_trait_ref_unnormalized(obligation, substs); - let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; + let instantiated_trait_ref = self.infcx.instantiate_binder_with_fresh_vars( + obligation.cause.span, + rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType, + trait_ref, + ); - debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations"); + nested.extend( + self.infcx + .at(&obligation.cause, obligation.param_env) + // needed for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs + .define_opaque_types(true) + .eq(placeholder_trait_pred.trait_ref, instantiated_trait_ref) + .map_err(|e| { + OutputTypeParameterMismatch( + trait_ref, + obligation.predicate.to_poly_trait_ref(), + e, + ) + })? + .into_obligations(), + ); + + debug!( + ?closure_def_id, + ?instantiated_trait_ref, + ?nested, + "confirm closure candidate obligations" + ); // FIXME: Chalk if self.tcx().sess.opts.unstable_opts.trait_solver != TraitSolver::Chalk { @@ -775,62 +894,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(ImplSourceClosureData { closure_def_id, substs, nested }) } - /// In the case of closure types and fn pointers, - /// we currently treat the input type parameters on the trait as - /// outputs. This means that when we have a match we have only - /// considered the self type, so we have to go back and make sure - /// to relate the argument types too. This is kind of wrong, but - /// since we control the full set of impls, also not that wrong, - /// and it DOES yield better error messages (since we don't report - /// errors as if there is no applicable impl, but rather report - /// errors are about mismatched argument types. - /// - /// Here is an example. Imagine we have a closure expression - /// and we desugared it so that the type of the expression is - /// `Closure`, and `Closure` expects `i32` as argument. Then it - /// is "as if" the compiler generated this impl: - /// ```ignore (illustrative) - /// impl Fn(i32) for Closure { ... } - /// ``` - /// Now imagine our obligation is `Closure: Fn(usize)`. So far - /// we have matched the self type `Closure`. At this point we'll - /// compare the `i32` to `usize` and generate an error. - /// - /// Note that this checking occurs *after* the impl has selected, - /// because these output type parameters should not affect the - /// 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( - &mut self, - obligation: &TraitObligation<'tcx>, - expected_trait_ref: ty::PolyTraitRef<'tcx>, - ) -> Result>, SelectionError<'tcx>> { - let obligation_trait_ref = obligation.predicate.to_poly_trait_ref(); - // Normalize the obligation and expected trait refs together, because why not - let Normalized { obligations: nested, value: (obligation_trait_ref, expected_trait_ref) } = - ensure_sufficient_stack(|| { - normalize_with_depth( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - (obligation_trait_ref, expected_trait_ref), - ) - }); - - self.infcx - .at(&obligation.cause, obligation.param_env) - // needed for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs - .define_opaque_types(true) - .sup(obligation_trait_ref, expected_trait_ref) - .map(|InferOk { mut obligations, .. }| { - obligations.extend(nested); - obligations - }) - .map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e)) - } - fn confirm_trait_upcasting_unsize_candidate( &mut self, obligation: &TraitObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index bcf63d5a6f628..6817d91000fb7 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -302,22 +302,22 @@ pub fn generator_trait_ref_and_outputs<'tcx>( tcx: TyCtxt<'tcx>, fn_trait_def_id: DefId, self_ty: Ty<'tcx>, - sig: ty::PolyGenSig<'tcx>, -) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> { + sig: ty::GenSig<'tcx>, +) -> (ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>) { assert!(!self_ty.has_escaping_bound_vars()); - let trait_ref = tcx.mk_trait_ref(fn_trait_def_id, [self_ty, sig.skip_binder().resume_ty]); - sig.map_bound(|sig| (trait_ref, sig.yield_ty, sig.return_ty)) + let trait_ref = tcx.mk_trait_ref(fn_trait_def_id, [self_ty, sig.resume_ty]); + (trait_ref, sig.yield_ty, sig.return_ty) } pub fn future_trait_ref_and_outputs<'tcx>( tcx: TyCtxt<'tcx>, fn_trait_def_id: DefId, self_ty: Ty<'tcx>, - sig: ty::PolyGenSig<'tcx>, -) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>)> { + sig: ty::GenSig<'tcx>, +) -> (ty::TraitRef<'tcx>, Ty<'tcx>) { assert!(!self_ty.has_escaping_bound_vars()); let trait_ref = tcx.mk_trait_ref(fn_trait_def_id, [self_ty]); - sig.map_bound(|sig| (trait_ref, sig.return_ty)) + (trait_ref, sig.return_ty) } pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool { diff --git a/tests/ui/generator/resume-arg-late-bound.rs b/tests/ui/generator/resume-arg-late-bound.rs index 1c35ba80d2b13..70396c27dbfd0 100644 --- a/tests/ui/generator/resume-arg-late-bound.rs +++ b/tests/ui/generator/resume-arg-late-bound.rs @@ -13,5 +13,5 @@ fn main() { *arg = true; }; test(gen); - //~^ ERROR mismatched types + //~^ ERROR implementation of `Generator` is not general enough } diff --git a/tests/ui/generator/resume-arg-late-bound.stderr b/tests/ui/generator/resume-arg-late-bound.stderr index 34ee4036cc56c..63e5b4f47b4f9 100644 --- a/tests/ui/generator/resume-arg-late-bound.stderr +++ b/tests/ui/generator/resume-arg-late-bound.stderr @@ -1,17 +1,11 @@ -error[E0308]: mismatched types +error: implementation of `Generator` is not general enough --> $DIR/resume-arg-late-bound.rs:15:5 | LL | test(gen); - | ^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^ implementation of `Generator` is not general enough | - = note: expected trait `for<'a> Generator<&'a mut bool>` - found trait `Generator<&mut bool>` -note: the lifetime requirement is introduced here - --> $DIR/resume-arg-late-bound.rs:8:17 - | -LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `[generator@$DIR/resume-arg-late-bound.rs:11:15: 11:31]` must implement `Generator<&'1 mut bool>`, for any lifetime `'1`... + = note: ...but it actually implements `Generator<&'2 mut bool>`, for some specific lifetime `'2` error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/bugs/issue-88382.stderr b/tests/ui/generic-associated-types/bugs/issue-88382.stderr index a9a70bb7130cb..982001c771ce0 100644 --- a/tests/ui/generic-associated-types/bugs/issue-88382.stderr +++ b/tests/ui/generic-associated-types/bugs/issue-88382.stderr @@ -1,22 +1,14 @@ -error[E0631]: type mismatch in function arguments +error[E0282]: type annotations needed --> $DIR/issue-88382.rs:26:40 | LL | do_something(SomeImplementation(), test); - | ------------ ^^^^ expected due to this - | | - | required by a bound introduced by this call -... -LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {} - | ------------------------------------------------- found signature defined here + | ^^^^ cannot infer type of the type parameter `I` declared on the function `test` | - = note: expected function signature `for<'a> fn(&'a mut std::iter::Empty) -> _` - found function signature `for<'a, 'b> fn(&'b mut <_ as Iterable>::Iterator<'a>) -> _` -note: required by a bound in `do_something` - --> $DIR/issue-88382.rs:20:48 +help: consider specifying the generic argument | -LL | fn do_something(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something` +LL | do_something(SomeImplementation(), test::); + | +++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0631`. +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/higher-rank-trait-bounds/fn-ptr.rs b/tests/ui/higher-rank-trait-bounds/fn-ptr.rs new file mode 100644 index 0000000000000..90513353f23cf --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/fn-ptr.rs @@ -0,0 +1,13 @@ +// revisions: classic next +//[next] compile-flags: -Ztrait-solver=next +//check-pass + +fn ice() +where + for<'w> fn(&'w ()): Fn(&'w ()), +{ +} + +fn main() { + ice(); +} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs index 1d90226a3f486..4be99c0d6b615 100644 --- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs @@ -43,9 +43,9 @@ fn main() { } foo(bar, "string", |s| s.len() == 5); - //~^ ERROR mismatched types - //~| ERROR mismatched types + //~^ ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough foo(baz, "string", |s| s.0.len() == 5); - //~^ ERROR mismatched types - //~| ERROR mismatched types + //~^ ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough } diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr index 4ef96cd954106..52b16925bb13f 100644 --- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr @@ -1,79 +1,38 @@ -error[E0308]: mismatched types +error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:45:5 | LL | foo(bar, "string", |s| s.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: expected trait `for<'a, 'b> FnOnce<(&'a &'b str,)>` - found trait `for<'a> FnOnce<(&'a &str,)>` -note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-71955.rs:45:24 - | -LL | foo(bar, "string", |s| s.len() == 5); - | ^^^ -note: the lifetime requirement is introduced here - --> $DIR/issue-71955.rs:25:9 - | -LL | F2: FnOnce(&::Output) -> bool - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` -error[E0308]: mismatched types +error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:45:5 | LL | foo(bar, "string", |s| s.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other - | - = note: expected trait `for<'a, 'b> FnOnce<(&'a &'b str,)>` - found trait `for<'a> FnOnce<(&'a &str,)>` -note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-71955.rs:45:24 - | -LL | foo(bar, "string", |s| s.len() == 5); - | ^^^ -note: the lifetime requirement is introduced here - --> $DIR/issue-71955.rs:25:44 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | -LL | F2: FnOnce(&::Output) -> bool - | ^^^^ + = note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` -error[E0308]: mismatched types +error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:48:5 | LL | foo(baz, "string", |s| s.0.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: expected trait `for<'a, 'b> FnOnce<(&'a Wrapper<'b>,)>` - found trait `for<'a> FnOnce<(&'a Wrapper<'_>,)>` -note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-71955.rs:48:24 - | -LL | foo(baz, "string", |s| s.0.len() == 5); - | ^^^ -note: the lifetime requirement is introduced here - --> $DIR/issue-71955.rs:25:9 - | -LL | F2: FnOnce(&::Output) -> bool - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` -error[E0308]: mismatched types +error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:48:5 | LL | foo(baz, "string", |s| s.0.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other - | - = note: expected trait `for<'a, 'b> FnOnce<(&'a Wrapper<'b>,)>` - found trait `for<'a> FnOnce<(&'a Wrapper<'_>,)>` -note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-71955.rs:48:24 - | -LL | foo(baz, "string", |s| s.0.len() == 5); - | ^^^ -note: the lifetime requirement is introduced here - --> $DIR/issue-71955.rs:25:44 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | -LL | F2: FnOnce(&::Output) -> bool - | ^^^^ + = note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lifetimes/issue-79187-2.rs b/tests/ui/lifetimes/issue-79187-2.rs index fff92c30b3751..9d7f17e7f2382 100644 --- a/tests/ui/lifetimes/issue-79187-2.rs +++ b/tests/ui/lifetimes/issue-79187-2.rs @@ -7,7 +7,7 @@ fn take_foo(_: impl Foo) {} fn main() { take_foo(|a| a); //~^ ERROR implementation of `FnOnce` is not general enough - //~| ERROR mismatched types + //~| ERROR implementation of `Fn` is not general enough take_foo(|a: &i32| a); //~^ ERROR lifetime may not live long enough //~| ERROR mismatched types diff --git a/tests/ui/lifetimes/issue-79187-2.stderr b/tests/ui/lifetimes/issue-79187-2.stderr index c5f654b37bf6f..1ab8d33734315 100644 --- a/tests/ui/lifetimes/issue-79187-2.stderr +++ b/tests/ui/lifetimes/issue-79187-2.stderr @@ -25,24 +25,14 @@ LL | take_foo(|a| a); = note: closure with signature `fn(&'2 i32) -> &i32` must implement `FnOnce<(&'1 i32,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 i32,)>`, for some specific lifetime `'2` -error[E0308]: mismatched types +error: implementation of `Fn` is not general enough --> $DIR/issue-79187-2.rs:8:5 | LL | take_foo(|a| a); - | ^^^^^^^^^^^^^^^ one type is more general than the other - | - = note: expected trait `for<'a> Fn<(&'a i32,)>` - found trait `Fn<(&i32,)>` -note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-79187-2.rs:8:14 - | -LL | take_foo(|a| a); - | ^^^ -note: the lifetime requirement is introduced here - --> $DIR/issue-79187-2.rs:5:21 + | ^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough | -LL | fn take_foo(_: impl Foo) {} - | ^^^ + = note: closure with signature `fn(&'2 i32) -> &i32` must implement `Fn<(&'1 i32,)>`, for any lifetime `'1`... + = note: ...but it actually implements `Fn<(&'2 i32,)>`, for some specific lifetime `'2` error[E0308]: mismatched types --> $DIR/issue-79187-2.rs:11:5 diff --git a/tests/ui/lifetimes/issue-79187.rs b/tests/ui/lifetimes/issue-79187.rs index 8e13045623b3d..a8829bd4e4905 100644 --- a/tests/ui/lifetimes/issue-79187.rs +++ b/tests/ui/lifetimes/issue-79187.rs @@ -3,6 +3,6 @@ fn thing(x: impl FnOnce(&u32)) {} fn main() { let f = |_| (); thing(f); - //~^ ERROR mismatched types - //~^^ ERROR implementation of `FnOnce` is not general enough + //~^ ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough } diff --git a/tests/ui/lifetimes/issue-79187.stderr b/tests/ui/lifetimes/issue-79187.stderr index ee6e7b89d5f0e..988155ec26f56 100644 --- a/tests/ui/lifetimes/issue-79187.stderr +++ b/tests/ui/lifetimes/issue-79187.stderr @@ -1,21 +1,11 @@ -error[E0308]: mismatched types +error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187.rs:5:5 | LL | thing(f); - | ^^^^^^^^ one type is more general than the other - | - = note: expected trait `for<'a> FnOnce<(&'a u32,)>` - found trait `FnOnce<(&u32,)>` -note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-79187.rs:4:13 - | -LL | let f = |_| (); - | ^^^ -note: the lifetime requirement is introduced here - --> $DIR/issue-79187.rs:1:18 + | ^^^^^^^^ implementation of `FnOnce` is not general enough | -LL | fn thing(x: impl FnOnce(&u32)) {} - | ^^^^^^^^^^^^ + = note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187.rs:5:5 @@ -28,4 +18,3 @@ LL | thing(f); error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs index ddb8bacce8f90..86d47d79df5bb 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs @@ -11,6 +11,6 @@ fn f(data: &[T], key: impl Fn(&T) -> S) { fn g(data: &[T]) { f(data, identity) //~^ ERROR the parameter type - //~| ERROR mismatched types + //~| ERROR implementation of `Fn` is not general enough //~| ERROR implementation of `FnOnce` is not general } diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr index 7049f28e2f6eb..7537d4a159dc3 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr @@ -9,19 +9,14 @@ help: consider adding an explicit lifetime bound... LL | fn g(data: &[T]) { | +++++++++ -error[E0308]: mismatched types +error: implementation of `Fn` is not general enough --> $DIR/issue_74400.rs:12:5 | LL | f(data, identity) - | ^^^^^^^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough | - = note: expected trait `for<'a> Fn<(&'a T,)>` - found trait `Fn<(&T,)>` -note: the lifetime requirement is introduced here - --> $DIR/issue_74400.rs:8:34 - | -LL | fn f(data: &[T], key: impl Fn(&T) -> S) { - | ^^^^^^^^^^^ + = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `Fn<(&'1 T,)>`, for any lifetime `'1`... + = note: ...but it actually implements `Fn<(&'2 T,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough --> $DIR/issue_74400.rs:12:5 @@ -34,5 +29,4 @@ LL | f(data, identity) error: aborting due to 3 previous errors -Some errors have detailed explanations: E0308, E0310. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/mismatched_types/closure-mismatch.rs b/tests/ui/mismatched_types/closure-mismatch.rs index b0644e79611fa..36a10a6244d97 100644 --- a/tests/ui/mismatched_types/closure-mismatch.rs +++ b/tests/ui/mismatched_types/closure-mismatch.rs @@ -7,5 +7,5 @@ fn baz(_: T) {} fn main() { baz(|_| ()); //~^ ERROR implementation of `FnOnce` is not general enough - //~| ERROR mismatched types + //~| ERROR implementation of `Fn` is not general enough } diff --git a/tests/ui/mismatched_types/closure-mismatch.stderr b/tests/ui/mismatched_types/closure-mismatch.stderr index a7ef8fa08923f..f0e4420c8f0a6 100644 --- a/tests/ui/mismatched_types/closure-mismatch.stderr +++ b/tests/ui/mismatched_types/closure-mismatch.stderr @@ -7,25 +7,14 @@ LL | baz(|_| ()); = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` -error[E0308]: mismatched types +error: implementation of `Fn` is not general enough --> $DIR/closure-mismatch.rs:8:5 | LL | baz(|_| ()); - | ^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^ implementation of `Fn` is not general enough | - = note: expected trait `for<'a> Fn<(&'a (),)>` - found trait `Fn<(&(),)>` -note: this closure does not fulfill the lifetime requirements - --> $DIR/closure-mismatch.rs:8:9 - | -LL | baz(|_| ()); - | ^^^ -note: the lifetime requirement is introduced here - --> $DIR/closure-mismatch.rs:5:11 - | -LL | fn baz(_: T) {} - | ^^^ + = note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc1623-2.rs b/tests/ui/rfcs/rfc1623-2.rs index c0e13a5f5f031..5d11941414f43 100644 --- a/tests/ui/rfcs/rfc1623-2.rs +++ b/tests/ui/rfcs/rfc1623-2.rs @@ -26,8 +26,8 @@ static SOME_STRUCT: &SomeStruct = &SomeStruct { foo: &Foo { bools: &[false, true] }, bar: &Bar { bools: &[true, true] }, f: &id, - //~^ ERROR mismatched types - //~| ERROR mismatched types + //~^ ERROR implementation of `Fn` is not general enough + //~| ERROR implementation of `Fn` is not general enough //~| ERROR implementation of `FnOnce` is not general enough //~| ERROR implementation of `FnOnce` is not general enough }; diff --git a/tests/ui/rfcs/rfc1623-2.stderr b/tests/ui/rfcs/rfc1623-2.stderr index d183eaaa6236e..5c98a9d4fb4ce 100644 --- a/tests/ui/rfcs/rfc1623-2.stderr +++ b/tests/ui/rfcs/rfc1623-2.stderr @@ -1,20 +1,20 @@ -error[E0308]: mismatched types +error: implementation of `Fn` is not general enough --> $DIR/rfc1623-2.rs:28:8 | LL | f: &id, - | ^^^ one type is more general than the other + | ^^^ implementation of `Fn` is not general enough | - = note: expected trait `for<'a, 'b> Fn<(&'a Foo<'b>,)>` - found trait `Fn<(&Foo<'_>,)>` + = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `Fn<(&'1 Foo<'b>,)>`, for any lifetime `'1`... + = note: ...but it actually implements `Fn<(&'2 Foo<'_>,)>`, for some specific lifetime `'2` -error[E0308]: mismatched types +error: implementation of `Fn` is not general enough --> $DIR/rfc1623-2.rs:28:8 | LL | f: &id, - | ^^^ one type is more general than the other + | ^^^ implementation of `Fn` is not general enough | - = note: expected trait `for<'a, 'b> Fn<(&'a Foo<'b>,)>` - found trait `Fn<(&Foo<'_>,)>` + = note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `Fn<(&'a Foo<'1>,)>`, for any lifetime `'1`... + = note: ...but it actually implements `Fn<(&Foo<'2>,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough --> $DIR/rfc1623-2.rs:28:8 @@ -36,4 +36,3 @@ LL | f: &id, error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`.