Change:
} if check_implied_wf == CheckImpliedWfMode::Check && !(impl_sig, trait_sig).references_error() { <del> // We need to check that the impl's args are well-formed given // the hybrid param-env (impl + trait method where-clauses). ocx.register_obligation(traits::Obligation::new( infcx.tcx, ObligationCause::dummy(), param_env, ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed( unnormalized_impl_fty.into(), ))), )); </del> <ins> // See #108544. Annoying, we can end up in cases where, because of winnowing, // we pick param env candidates over a more general impl, leading to more // stricter lifetime requirements than we would otherwise need. This can // trigger the lint. Instead, let's only consider type outlives and // region outlives obligations. // // FIXME(-Ztrait-solver=next): Try removing this hack again once // the new solver is stable. let mut wf_args: smallvec::SmallVec<[_; 4]> = unnormalized_impl_sig.inputs_and_output.iter().map(|ty| ty.into()).collect(); // Annoyingly, asking for the WF predicates of an array (with an unevaluated const (only?)) // will give back the well-formed predicate of the same array. let mut wf_args_seen: FxHashSet<_> = wf_args.iter().copied().collect(); while let Some(arg) = wf_args.pop() { let Some(obligations) = rustc_trait_selection::traits::wf::obligations( infcx, param_env, impl_m_def_id, 0, arg, impl_m_span, ) else { continue; }; for obligation in obligations { match obligation.predicate.kind().skip_binder() { ty::PredicateKind::Clause( ty::ClauseKind::RegionOutlives(..) | ty::ClauseKind::TypeOutlives(..), ) => ocx.register_obligation(obligation), ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { if wf_args_seen.insert(arg) { wf_args.push(arg) } } _ => {} } } } </ins> } // Check that all obligations are satisfied by the implementation's

Discussion:
The lint is triggered by the following code (from , cc : In the environment , the type surprisingly requires for well-formedness (see ), but this constraint is not used in implied bounds, so I believe it can't be exploited for unsoundness. The lint was upgraded to deny-by-default in the current beta (1.68.0-beta.5 2023-02-15 ). So this counts as regression? cc label C-bug T-types T-compiler regression-from-stable-to-beta
:facepalm: I think this is due to us preferring param-env candidates for .
So the issue here is that requires . We try to prove that in the hybrid param-env of the impl's WC + trait method's WC, being after substituting . Due to some frustrating precedence rules around candidate assembly in the trait solver, we try to match against the param-env candidate and get . We also assemble a built-in sized bound, but always prefer the param-env candidate over that. That requires us to prove , which is not known to be true in the hybrid param-env, triggering the lint.
I wonder if we could get away with not checking , but just the implied lifetime bounds or something :thinking:
WG-prioritization assigning priority (). label -I-prioritize +P-medium
Been thinking about this a little bit. One thought I had was to check that the impl method is WF given only the trait method, but I think that would break this example: I wonder if we could get away with not checking WF(return-type), but just the implied lifetime bounds or something This is annoying difficult, because it's not straightforward to get "just the implied lifetime bounds" of a type. I'm playing around with using and filtering outlives bounds, but that can generate more predicates (which, I thought we had somewhere a function that recurses though those). We'll see if this works...