提交 f1b85481 编写于 作者: B bors

Auto merge of #109356 - jackh726:issue-108544, r=lcnr

Only check outlives goals on impl compared to trait

Fixes #108544

r? `@compiler-errors`
use super::potentially_plural_count; use super::potentially_plural_count;
use crate::errors::LifetimesOrBoundsMismatchOnTrait; use crate::errors::LifetimesOrBoundsMismatchOnTrait;
use hir::def_id::{DefId, LocalDefId}; use hir::def_id::{DefId, LocalDefId};
use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_errors::{ use rustc_errors::{
pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed, MultiSpan, pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed, MultiSpan,
}; };
...@@ -265,7 +265,6 @@ fn compare_method_predicate_entailment<'tcx>( ...@@ -265,7 +265,6 @@ fn compare_method_predicate_entailment<'tcx>(
infer::HigherRankedType, infer::HigherRankedType,
tcx.fn_sig(impl_m.def_id).instantiate_identity(), tcx.fn_sig(impl_m.def_id).instantiate_identity(),
); );
let unnormalized_impl_fty = Ty::new_fn_ptr(tcx, ty::Binder::dummy(unnormalized_impl_sig));
let norm_cause = ObligationCause::misc(impl_m_span, impl_m_def_id); let norm_cause = ObligationCause::misc(impl_m_span, impl_m_def_id);
let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig); let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig);
...@@ -309,16 +308,44 @@ fn compare_method_predicate_entailment<'tcx>( ...@@ -309,16 +308,44 @@ fn compare_method_predicate_entailment<'tcx>(
} }
if check_implied_wf == CheckImpliedWfMode::Check && !(impl_sig, trait_sig).references_error() { if check_implied_wf == CheckImpliedWfMode::Check && !(impl_sig, trait_sig).references_error() {
// We need to check that the impl's args are well-formed given // See #108544. Annoying, we can end up in cases where, because of winnowing,
// the hybrid param-env (impl + trait method where-clauses). // we pick param env candidates over a more general impl, leading to more
ocx.register_obligation(traits::Obligation::new( // stricter lifetime requirements than we would otherwise need. This can
infcx.tcx, // trigger the lint. Instead, let's only consider type outlives and
ObligationCause::dummy(), // region outlives obligations.
param_env, //
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed( // FIXME(-Ztrait-solver=next): Try removing this hack again once
unnormalized_impl_fty.into(), // 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)
}
}
_ => {}
}
}
}
} }
// Check that all obligations are satisfied by the implementation's // Check that all obligations are satisfied by the implementation's
......
// check-pass
// See issue #109356. We don't want a false positive to the `implied_bounds_entailment` lint.
use std::borrow::Cow;
pub trait Trait {
fn method(self) -> Option<Cow<'static, str>>
where
Self: Sized;
}
impl<'a> Trait for Cow<'a, str> {
// If we're not careful here, we'll check `WF(return-type)` using the trait
// and impl where clauses, requiring that `Cow<'a, str>: Sized`. This is
// obviously true, but if we pick the `Self: Sized` clause from the trait
// over the "inherent impl", we will require `'a == 'static`, which triggers
// the `implied_bounds_entailment` lint.
fn method(self) -> Option<Cow<'static, str>> {
None
}
}
fn main() {}
// check-pass
pub trait Trait<'a, 'b> {
fn method(self, _: &'static &'static ())
where
'a: 'b;
}
impl<'a> Trait<'a, 'static> for () {
// On first glance, this seems like we have the extra implied bound that
// `'a: 'static`, but we know this from the trait method where clause.
fn method(self, _: &'static &'a ()) {}
}
fn main() {}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册