use rustc_infer::traits::specialization_graph::Node;
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
use rustc_middle::ty::trait_def::TraitSpecializationKind;
-use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
use rustc_span::Span;
use rustc_trait_selection::traits::{self, translate_substs, wf};
// Conservatively use an empty `ParamEnv`.
let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty());
- infcx.resolve_regions_and_report_errors(impl1_def_id.to_def_id(), &outlives_env);
+ infcx.resolve_regions_and_report_errors(&outlives_env);
let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
let span = tcx.def_span(impl1_def_id);
tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
span: Span,
) {
let tcx = infcx.tcx;
- let impl1_predicates: Vec<_> = traits::elaborate_predicates(
+ let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
+ let impl1_predicates: Vec<_> = traits::elaborate_predicates_with_span(
tcx,
- tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).predicates.into_iter(),
+ std::iter::zip(
+ instantiated.predicates,
+ // Don't drop predicates (unsound!) because `spans` is too short
+ instantiated.spans.into_iter().chain(std::iter::repeat(span)),
+ ),
)
- .map(|obligation| obligation.predicate)
+ .map(|obligation| (obligation.predicate, obligation.cause.span))
.collect();
let mut impl2_predicates = if impl2_node.is_from_trait() {
// which is sound because we forbid impls like the following
//
// impl<D: Debug> AlwaysApplicable for D { }
- let always_applicable_traits = impl1_predicates.iter().copied().filter(|&predicate| {
+ let always_applicable_traits = impl1_predicates.iter().copied().filter(|&(predicate, _)| {
matches!(
trait_predicate_kind(tcx, predicate),
Some(TraitSpecializationKind::AlwaysApplicable)
}
}
impl2_predicates.extend(
- traits::elaborate_predicates(tcx, always_applicable_traits)
+ traits::elaborate_predicates_with_span(tcx, always_applicable_traits)
.map(|obligation| obligation.predicate),
);
- for predicate in impl1_predicates {
+ for (predicate, span) in impl1_predicates {
if !impl2_predicates.contains(&predicate) {
check_specialization_on(tcx, predicate, span)
}
.emit();
}
}
+ ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
+ tcx.sess
+ .struct_span_err(
+ span,
+ &format!("cannot specialize on associated type `{projection_ty} == {term}`",),
+ )
+ .emit();
+ }
_ => {
tcx.sess
- .struct_span_err(span, &format!("cannot specialize on `{:?}`", predicate))
+ .struct_span_err(span, &format!("cannot specialize on predicate `{}`", predicate))
.emit();
}
}