Get rid of ToPolyTraitRef

This commit is contained in:
Michael Goulet 2025-01-18 18:47:11 +00:00
parent 8321f00bf4
commit 2a180a93a1
9 changed files with 116 additions and 125 deletions

View file

@ -1,5 +1,5 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::ty::{self, ToPolyTraitRef, TyCtxt};
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::{Ident, Span};
pub use rustc_type_ir::elaborate::*;
@ -125,8 +125,8 @@ pub fn transitive_bounds_that_define_assoc_item<'tcx>(
.iter_identity_copied()
.map(|(clause, _)| clause.instantiate_supertrait(tcx, trait_ref))
.filter_map(|clause| clause.as_trait_clause())
// FIXME: Negative supertraits are elaborated here lol
.map(|trait_pred| trait_pred.to_poly_trait_ref()),
.filter(|clause| clause.polarity() == ty::PredicatePolarity::Positive)
.map(|clause| clause.map_bound(|clause| clause.trait_ref)),
);
return Some(trait_ref);

View file

@ -79,8 +79,7 @@ pub use self::predicate::{
PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef,
PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
PolyTraitRef, PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef, TraitPredicate, TraitRef,
TypeOutlivesPredicate,
RegionOutlivesPredicate, SubtypePredicate, TraitPredicate, TraitRef, TypeOutlivesPredicate,
};
pub use self::region::{
BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region,

View file

@ -476,16 +476,6 @@ impl<'tcx> Clause<'tcx> {
}
}
pub trait ToPolyTraitRef<'tcx> {
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
}
impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> {
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> {
self.map_bound_ref(|trait_pred| trait_pred.trait_ref)
}
}
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PredicateKind<'tcx>> for Predicate<'tcx> {
fn upcast_from(from: PredicateKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
ty::Binder::dummy(from).upcast(tcx)

View file

@ -172,14 +172,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let bound_predicate = predicate.kind();
let mut err = match bound_predicate.skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
let trait_ref = bound_predicate.rebind(data.trait_ref);
debug!(?trait_ref);
let trait_pred = bound_predicate.rebind(data);
debug!(?trait_pred);
if let Err(e) = predicate.error_reported() {
return e;
}
if let Err(guar) = self.tcx.ensure().coherent_trait(trait_ref.def_id()) {
if let Err(guar) = self.tcx.ensure().coherent_trait(trait_pred.def_id()) {
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
// other `Foo` impls are incoherent.
return guar;
@ -200,13 +200,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// avoid inundating the user with unnecessary errors, but we now
// check upstream for type errors and don't add the obligations to
// begin with in those cases.
if self.tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized) {
if self.tcx.is_lang_item(trait_pred.def_id(), LangItem::Sized) {
match self.tainted_by_errors() {
None => {
let err = self.emit_inference_failure_err(
obligation.cause.body_id,
span,
trait_ref.self_ty().skip_binder().into(),
trait_pred.self_ty().skip_binder().into(),
TypeAnnotationNeeded::E0282,
false,
);
@ -251,10 +251,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let mut ambiguities = compute_applicable_impls_for_diagnostics(
self.infcx,
&obligation.with(self.tcx, trait_ref),
&obligation.with(self.tcx, trait_pred),
);
let has_non_region_infer =
trait_ref.skip_binder().args.types().any(|t| !t.is_ty_or_numeric_infer());
let has_non_region_infer = trait_pred
.skip_binder()
.trait_ref
.args
.types()
.any(|t| !t.is_ty_or_numeric_infer());
// It doesn't make sense to talk about applicable impls if there are more than a
// handful of them. If there are a lot of them, but only a few of them have no type
// params, we only show those, as they are more likely to be useful/intended.
@ -294,7 +298,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if impl_candidates.len() < 40 {
self.report_similar_impl_candidates(
impl_candidates.as_slice(),
trait_ref,
trait_pred,
obligation.cause.body_id,
&mut err,
false,
@ -306,7 +310,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if let ObligationCauseCode::WhereClause(def_id, _)
| ObligationCauseCode::WhereClauseInExpr(def_id, ..) = *obligation.cause.code()
{
self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
self.suggest_fully_qualified_path(&mut err, def_id, span, trait_pred.def_id());
}
if let Some(ty::GenericArgKind::Type(_)) = arg.map(|arg| arg.unpack())

View file

@ -23,9 +23,7 @@ use rustc_middle::ty::print::{
FmtPrinter, Print, PrintPolyTraitPredicateExt, PrintTraitPredicateExt as _,
PrintTraitRefExt as _, with_forced_trimmed_paths,
};
use rustc_middle::ty::{
self, ToPolyTraitRef, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast,
};
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast};
use rustc_middle::{bug, span_bug};
use rustc_span::{BytePos, DUMMY_SP, STDLIB_STABLE_CRATES, Span, Symbol, sym};
use tracing::{debug, instrument};
@ -155,12 +153,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
(leaf_trait_predicate, &obligation)
};
let main_trait_ref = main_trait_predicate.to_poly_trait_ref();
let leaf_trait_ref = leaf_trait_predicate.to_poly_trait_ref();
if let Some(guar) = self.emit_specialized_closure_kind_error(
&obligation,
leaf_trait_ref,
leaf_trait_predicate,
) {
return guar;
}
@ -202,14 +197,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
} = self.on_unimplemented_note(main_trait_predicate, main_obligation, &mut long_ty_file);
let have_alt_message = message.is_some() || label.is_some();
let is_try_conversion = self.is_try_conversion(span, main_trait_ref.def_id());
let is_try_conversion = self.is_try_conversion(span, main_trait_predicate.def_id());
let is_unsize =
self.tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Unsize);
self.tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Unsize);
let (message, notes, append_const_msg) = if is_try_conversion {
(
Some(format!(
"`?` couldn't convert the error to `{}`",
main_trait_ref.skip_binder().self_ty(),
main_trait_predicate.skip_binder().self_ty(),
)),
vec![
"the question mark operation (`?`) implicitly performs a \
@ -230,12 +225,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
post_message,
);
let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item(main_trait_ref.def_id(), LangItem::TransmuteTrait)
let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item(main_trait_predicate.def_id(), LangItem::TransmuteTrait)
{
// Recompute the safe transmute reason and use that for the error reporting
match self.get_safe_transmute_error_and_reason(
obligation.clone(),
main_trait_ref,
main_trait_predicate,
span,
) {
GetSafeTransmuteErrorAndReason::Silent => {
@ -266,7 +261,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
let mut suggested = false;
if is_try_conversion {
suggested = self.try_conversion_context(&obligation, main_trait_ref.skip_binder(), &mut err);
suggested = self.try_conversion_context(&obligation, main_trait_predicate, &mut err);
}
if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) {
@ -274,12 +269,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
ret_span,
format!(
"expected `{}` because of this",
main_trait_ref.skip_binder().self_ty()
main_trait_predicate.skip_binder().self_ty()
),
);
}
if tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Tuple) {
if tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Tuple) {
self.add_tuple_trait_message(
obligation.cause.code().peel_derives(),
&mut err,
@ -319,7 +314,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// If it has a custom `#[rustc_on_unimplemented]`
// error message, let's display it as the label!
err.span_label(span, s);
if !matches!(leaf_trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) {
if !matches!(leaf_trait_predicate.skip_binder().self_ty().kind(), ty::Param(_)) {
// When the self type is a type param We don't need to "the trait
// `std::marker::Sized` is not implemented for `T`" as we will point
// at the type param with a label to suggest constraining it.
@ -339,7 +334,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if let ObligationCauseCode::Coercion { source, target } =
*obligation.cause.code().peel_derives()
{
if self.tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Sized) {
if self.tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Sized) {
self.suggest_borrowing_for_object_cast(
&mut err,
root_obligation,
@ -368,7 +363,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
err.span_label(tcx.def_span(body), s);
}
self.suggest_floating_point_literal(&obligation, &mut err, leaf_trait_ref);
self.suggest_floating_point_literal(&obligation, &mut err, leaf_trait_predicate);
self.suggest_dereferencing_index(&obligation, &mut err, leaf_trait_predicate);
suggested |= self.suggest_dereferences(&obligation, &mut err, leaf_trait_predicate);
suggested |= self.suggest_fn_call(&obligation, &mut err, leaf_trait_predicate);
@ -376,7 +371,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
suggested = if let &[cand] = &impl_candidates[..] {
let cand = cand.trait_ref;
if let (ty::FnPtr(..), ty::FnDef(..)) =
(cand.self_ty().kind(), main_trait_ref.self_ty().skip_binder().kind())
(cand.self_ty().kind(), main_trait_predicate.self_ty().skip_binder().kind())
{
// Wrap method receivers and `&`-references in parens
let suggestion = if self.tcx.sess.source_map().span_look_ahead(span, ".", Some(50)).is_some() {
@ -423,11 +418,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
span,
leaf_trait_predicate,
);
self.note_version_mismatch(&mut err, leaf_trait_ref);
self.note_version_mismatch(&mut err, leaf_trait_predicate);
self.suggest_remove_await(&obligation, &mut err);
self.suggest_derive(&obligation, &mut err, leaf_trait_predicate);
if tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Try) {
if tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Try) {
self.suggest_await_before_try(
&mut err,
&obligation,
@ -455,9 +450,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
);
}
let is_fn_trait = tcx.is_fn_trait(leaf_trait_ref.def_id());
let is_fn_trait = tcx.is_fn_trait(leaf_trait_predicate.def_id());
let is_target_feature_fn = if let ty::FnDef(def_id, _) =
*leaf_trait_ref.skip_binder().self_ty().kind()
*leaf_trait_predicate.skip_binder().self_ty().kind()
{
!self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
} else {
@ -509,7 +504,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
self.explain_hrtb_projection(&mut err, leaf_trait_predicate, obligation.param_env, &obligation.cause);
self.suggest_desugaring_async_fn_in_trait(&mut err, main_trait_ref);
self.suggest_desugaring_async_fn_in_trait(&mut err, main_trait_predicate);
// Return early if the trait is Debug or Display and the invocation
// originates within a standard library macro, because the output
@ -527,7 +522,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if in_std_macro
&& matches!(
self.tcx.get_diagnostic_name(leaf_trait_ref.def_id()),
self.tcx.get_diagnostic_name(leaf_trait_predicate.def_id()),
Some(sym::Debug | sym::Display)
)
{
@ -785,21 +780,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
fn emit_specialized_closure_kind_error(
&self,
obligation: &PredicateObligation<'tcx>,
mut trait_ref: ty::PolyTraitRef<'tcx>,
mut trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Option<ErrorGuaranteed> {
// If `AsyncFnKindHelper` is not implemented, that means that the closure kind
// doesn't extend the goal kind. This is worth reporting, but we can only do so
// if we actually know which closure this goal comes from, so look at the cause
// to see if we can extract that information.
if self.tcx.is_lang_item(trait_ref.def_id(), LangItem::AsyncFnKindHelper)
&& let Some(found_kind) = trait_ref.skip_binder().args.type_at(0).to_opt_closure_kind()
if self.tcx.is_lang_item(trait_pred.def_id(), LangItem::AsyncFnKindHelper)
&& let Some(found_kind) =
trait_pred.skip_binder().trait_ref.args.type_at(0).to_opt_closure_kind()
&& let Some(expected_kind) =
trait_ref.skip_binder().args.type_at(1).to_opt_closure_kind()
trait_pred.skip_binder().trait_ref.args.type_at(1).to_opt_closure_kind()
&& !found_kind.extends(expected_kind)
{
if let Some((_, Some(parent))) = obligation.cause.code().parent_with_predicate() {
// If we have a derived obligation, then the parent will be a `AsyncFn*` goal.
trait_ref = parent.to_poly_trait_ref();
trait_pred = parent;
} else if let &ObligationCauseCode::FunctionArg { arg_hir_id, .. } =
obligation.cause.code()
&& let Some(typeck_results) = &self.typeck_results
@ -820,9 +816,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
let self_ty = trait_ref.self_ty().skip_binder();
let self_ty = trait_pred.self_ty().skip_binder();
if let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id()) {
if let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_pred.def_id()) {
let (closure_def_id, found_args, by_ref_captures) = match *self_ty.kind() {
ty::Closure(def_id, args) => {
(def_id, args.as_closure().sig().map_bound(|sig| sig.inputs()[0]), None)
@ -837,7 +833,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
_ => return None,
};
let expected_args = trait_ref.map_bound(|trait_ref| trait_ref.args.type_at(1));
let expected_args =
trait_pred.map_bound(|trait_pred| trait_pred.trait_ref.args.type_at(1));
// Verify that the arguments are compatible. If the signature is
// mismatched, then we have a totally different error to report.
@ -909,7 +906,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
fn try_conversion_context(
&self,
obligation: &PredicateObligation<'tcx>,
trait_ref: ty::TraitRef<'tcx>,
trait_pred: ty::PolyTraitPredicate<'tcx>,
err: &mut Diag<'_>,
) -> bool {
let span = obligation.cause.span;
@ -953,8 +950,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if !self.tcx.is_diagnostic_item(sym::FromResidual, y.def_id()) {
return false;
}
let self_ty = trait_ref.self_ty();
let found_ty = trait_ref.args.get(1).and_then(|a| a.as_type());
let self_ty = trait_pred.skip_binder().self_ty();
let found_ty = trait_pred.skip_binder().trait_ref.args.get(1).and_then(|a| a.as_type());
let mut prev_ty = self.resolve_vars_if_possible(
typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)),
@ -1223,18 +1220,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
goal: ty::TraitPredicate<'tcx>,
assumption: ty::PolyTraitPredicate<'tcx>,
) -> bool {
// Fast path
if goal.polarity != assumption.polarity() {
return false;
}
let trait_goal = goal.trait_ref;
let trait_assumption = self.instantiate_binder_with_fresh_vars(
DUMMY_SP,
infer::BoundRegionConversionTime::HigherRankedType,
assumption.to_poly_trait_ref(),
assumption,
);
self.can_eq(ty::ParamEnv::empty(), trait_goal, trait_assumption)
self.can_eq(ty::ParamEnv::empty(), goal.trait_ref, trait_assumption.trait_ref)
}
fn can_match_projection(
@ -1682,7 +1679,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
pub(super) fn report_similar_impl_candidates(
&self,
impl_candidates: &[ImplCandidate<'tcx>],
trait_ref: ty::PolyTraitRef<'tcx>,
trait_pred: ty::PolyTraitPredicate<'tcx>,
body_def_id: LocalDefId,
err: &mut Diag<'_>,
other: bool,
@ -1727,7 +1724,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// We'll check for the case where the reason for the mismatch is that the trait comes from
// one crate version and the type comes from another crate version, even though they both
// are from the same crate.
let trait_def_id = trait_ref.def_id();
let trait_def_id = trait_pred.def_id();
let trait_name = self.tcx.item_name(trait_def_id);
let crate_name = self.tcx.crate_name(trait_def_id.krate);
if let Some(other_trait_def_id) = self.tcx.all_traits().find(|def_id| {
@ -1739,7 +1736,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// different crate `DefId`. We highlight the traits.
let found_type =
if let ty::Adt(def, _) = trait_ref.self_ty().skip_binder().peel_refs().kind() {
if let ty::Adt(def, _) = trait_pred.self_ty().skip_binder().peel_refs().kind() {
Some(def.did())
} else {
None
@ -1836,7 +1833,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if self.probe(|_| {
let ocx = ObligationCtxt::new(self);
self.enter_forall(trait_ref, |obligation_trait_ref| {
self.enter_forall(trait_pred, |obligation_trait_ref| {
let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id);
let impl_trait_ref = ocx.normalize(
&ObligationCause::dummy(),
@ -1864,7 +1861,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let mut terrs = vec![];
for (obligation_arg, impl_arg) in
std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args)
std::iter::zip(obligation_trait_ref.trait_ref.args, impl_trait_ref.args)
{
if (obligation_arg, impl_arg).references_error() {
return false;
@ -1906,8 +1903,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
let traits = self.cmp_traits(
obligation_trait_ref.def_id,
&obligation_trait_ref.args[1..],
obligation_trait_ref.def_id(),
&obligation_trait_ref.trait_ref.args[1..],
impl_trait_ref.def_id,
&impl_trait_ref.args[1..],
);
@ -1991,7 +1988,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
if let &[cand] = &candidates[..] {
let (desc, mention_castable) =
match (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) {
match (cand.self_ty().kind(), trait_pred.self_ty().skip_binder().kind()) {
(ty::FnPtr(..), ty::FnDef(..)) => {
(" implemented for fn pointer `", ", cast using `as`")
}
@ -2055,7 +2052,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
.filter(|cand| !self.tcx.do_not_recommend_impl(cand.impl_def_id))
.collect::<Vec<_>>();
let def_id = trait_ref.def_id();
let def_id = trait_pred.def_id();
if impl_candidates.is_empty() {
if self.tcx.trait_is_auto(def_id)
|| self.tcx.lang_items().iter().any(|(_, id)| id == def_id)
@ -2132,11 +2129,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
&& !self.tcx.trait_is_auto(def_id)
&& !self.tcx.lang_items().iter().any(|(_, id)| id == def_id)
{
let trait_ref = trait_pred.to_poly_trait_ref();
let impl_candidates = self.find_similar_impl_candidates(trait_pred);
self.report_similar_impl_candidates(
&impl_candidates,
trait_ref,
trait_pred,
body_def_id,
err,
true,
@ -2173,12 +2169,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
/// with the same path as `trait_ref`, a help message about
/// a probable version mismatch is added to `err`
fn note_version_mismatch(&self, err: &mut Diag<'_>, trait_ref: ty::PolyTraitRef<'tcx>) -> bool {
fn note_version_mismatch(
&self,
err: &mut Diag<'_>,
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> bool {
let get_trait_impls = |trait_def_id| {
let mut trait_impls = vec![];
self.tcx.for_each_relevant_impl(
trait_def_id,
trait_ref.skip_binder().self_ty(),
trait_pred.skip_binder().self_ty(),
|impl_def_id| {
trait_impls.push(impl_def_id);
},
@ -2186,11 +2186,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
trait_impls
};
let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
let required_trait_path = self.tcx.def_path_str(trait_pred.def_id());
let traits_with_same_path: UnordSet<_> = self
.tcx
.visible_traits()
.filter(|trait_def_id| *trait_def_id != trait_ref.def_id())
.filter(|trait_def_id| *trait_def_id != trait_pred.def_id())
.map(|trait_def_id| (self.tcx.def_path_str(trait_def_id), trait_def_id))
.filter(|(p, _)| *p == required_trait_path)
.collect();
@ -2374,7 +2374,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
fn get_safe_transmute_error_and_reason(
&self,
obligation: PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
trait_pred: ty::PolyTraitPredicate<'tcx>,
span: Span,
) -> GetSafeTransmuteErrorAndReason {
use rustc_transmute::Answer;
@ -2386,19 +2386,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
// Erase regions because layout code doesn't particularly care about regions.
let trait_ref =
self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_ref));
let trait_pred =
self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_pred));
let src_and_dst = rustc_transmute::Types {
dst: trait_ref.args.type_at(0),
src: trait_ref.args.type_at(1),
dst: trait_pred.trait_ref.args.type_at(0),
src: trait_pred.trait_ref.args.type_at(1),
};
let ocx = ObligationCtxt::new(self);
let Ok(assume) = ocx.structurally_normalize_const(
&obligation.cause,
obligation.param_env,
trait_ref.args.const_at(2),
trait_pred.trait_ref.args.const_at(2),
) else {
self.dcx().span_delayed_bug(
span,
@ -2417,8 +2417,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
return GetSafeTransmuteErrorAndReason::Silent;
};
let dst = trait_ref.args.type_at(0);
let src = trait_ref.args.type_at(1);
let dst = trait_pred.trait_ref.args.type_at(0);
let src = trait_pred.trait_ref.args.type_at(1);
let err_msg = format!("`{src}` cannot be safely transmuted into `{dst}`");
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
@ -2566,12 +2566,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
trait_predicate.skip_binder().polarity,
)
{
self.add_help_message_for_fn_trait(
trait_predicate.to_poly_trait_ref(),
err,
implemented_kind,
params,
);
self.add_help_message_for_fn_trait(trait_predicate, err, implemented_kind, params);
} else if !trait_predicate.has_non_region_infer()
&& self.predicate_can_apply(obligation.param_env, trait_predicate)
{
@ -2606,7 +2601,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
if !self.report_similar_impl_candidates(
&impl_candidates,
trait_predicate.to_poly_trait_ref(),
trait_predicate,
body_def_id,
err,
true,
@ -2623,7 +2618,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
self.suggest_convert_to_slice(
err,
obligation,
trait_predicate.to_poly_trait_ref(),
trait_predicate,
impl_candidates.as_slice(),
span,
);
@ -2634,7 +2629,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
fn add_help_message_for_fn_trait(
&self,
trait_ref: ty::PolyTraitRef<'tcx>,
trait_pred: ty::PolyTraitPredicate<'tcx>,
err: &mut Diag<'_>,
implemented_kind: ty::ClosureKind,
params: ty::Binder<'tcx, Ty<'tcx>>,
@ -2647,12 +2642,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// to implement.
let selected_kind = self
.tcx
.fn_trait_kind_from_def_id(trait_ref.def_id())
.fn_trait_kind_from_def_id(trait_pred.def_id())
.expect("expected to map DefId to ClosureKind");
if !implemented_kind.extends(selected_kind) {
err.note(format!(
"`{}` implements `{}`, but it must implement `{}`, which is more general",
trait_ref.skip_binder().self_ty(),
trait_pred.skip_binder().self_ty(),
implemented_kind,
selected_kind
));
@ -2660,7 +2655,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// Note any argument mismatches
let given_ty = params.skip_binder();
let expected_ty = trait_ref.skip_binder().args.type_at(1);
let expected_ty = trait_pred.skip_binder().trait_ref.args.type_at(1);
if let ty::Tuple(given) = given_ty.kind()
&& let ty::Tuple(expected) = expected_ty.kind()
{

View file

@ -10,7 +10,7 @@ use rustc_hir::{AttrArgs, AttrKind, Attribute};
use rustc_macros::LintDiagnostic;
use rustc_middle::bug;
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::{self, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, TyCtxt};
use rustc_middle::ty::{self, GenericArgsRef, GenericParamDefKind, TyCtxt};
use rustc_parse_format::{ParseMode, Parser, Piece, Position};
use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES;
use rustc_span::{Span, Symbol, kw, sym};
@ -42,18 +42,18 @@ static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
fn impl_similar_to(
&self,
trait_ref: ty::PolyTraitRef<'tcx>,
trait_pred: ty::PolyTraitPredicate<'tcx>,
obligation: &PredicateObligation<'tcx>,
) -> Option<(DefId, GenericArgsRef<'tcx>)> {
let tcx = self.tcx;
let param_env = obligation.param_env;
self.enter_forall(trait_ref, |trait_ref| {
let trait_self_ty = trait_ref.self_ty();
self.enter_forall(trait_pred, |trait_pred| {
let trait_self_ty = trait_pred.self_ty();
let mut self_match_impls = vec![];
let mut fuzzy_match_impls = vec![];
self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
self.tcx.for_each_relevant_impl(trait_pred.def_id(), trait_self_ty, |def_id| {
let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id);
let impl_trait_ref =
tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args);
@ -64,7 +64,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
self_match_impls.push((def_id, impl_args));
if iter::zip(
trait_ref.args.types().skip(1),
trait_pred.trait_ref.args.types().skip(1),
impl_trait_ref.args.types().skip(1),
)
.all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some())
@ -117,7 +117,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
let (def_id, args) = self
.impl_similar_to(trait_pred.to_poly_trait_ref(), obligation)
.impl_similar_to(trait_pred, obligation)
.unwrap_or_else(|| (trait_pred.def_id(), trait_pred.skip_binder().trait_ref.args));
let trait_pred = trait_pred.skip_binder();

View file

@ -32,9 +32,9 @@ use rustc_middle::ty::print::{
with_forced_trimmed_paths, with_no_trimmed_paths,
};
use rustc_middle::ty::{
self, AdtKind, GenericArgs, InferTy, IsSuggestable, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable,
TypeFolder, TypeSuperFoldable, TypeVisitableExt, TypeckResults, Upcast,
suggest_arbitrary_trait_bound, suggest_constraining_type_param,
self, AdtKind, GenericArgs, InferTy, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeFolder,
TypeSuperFoldable, TypeVisitableExt, TypeckResults, Upcast, suggest_arbitrary_trait_bound,
suggest_constraining_type_param,
};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::LocalDefId;
@ -218,15 +218,15 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>(
(_, None) => predicate_constraint(hir_generics, trait_pred.upcast(tcx)),
(None, Some((ident, []))) => (
ident.span.shrink_to_hi(),
format!(": {}", trait_pred.to_poly_trait_ref().print_trait_sugared()),
format!(": {}", trait_pred.print_modifiers_and_trait_path()),
),
(_, Some((_, [.., bounds]))) => (
bounds.span().shrink_to_hi(),
format!(" + {}", trait_pred.to_poly_trait_ref().print_trait_sugared()),
format!(" + {}", trait_pred.print_modifiers_and_trait_path()),
),
(Some(_), Some((_, []))) => (
hir_generics.span.shrink_to_hi(),
format!(": {}", trait_pred.to_poly_trait_ref().print_trait_sugared()),
format!(": {}", trait_pred.print_modifiers_and_trait_path()),
),
};
@ -3729,7 +3729,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>,
trait_ref: ty::PolyTraitRef<'tcx>,
trait_pred: ty::PolyTraitPredicate<'tcx>,
) {
let rhs_span = match obligation.cause.code() {
ObligationCauseCode::BinOp { rhs_span: Some(span), rhs_is_lit, .. } if *rhs_is_lit => {
@ -3737,8 +3737,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
_ => return,
};
if let ty::Float(_) = trait_ref.skip_binder().self_ty().kind()
&& let ty::Infer(InferTy::IntVar(_)) = trait_ref.skip_binder().args.type_at(1).kind()
if let ty::Float(_) = trait_pred.skip_binder().self_ty().kind()
&& let ty::Infer(InferTy::IntVar(_)) =
trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
{
err.span_suggestion_verbose(
rhs_span.shrink_to_hi(),
@ -4448,7 +4449,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
&self,
err: &mut Diag<'_>,
obligation: &PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
trait_pred: ty::PolyTraitPredicate<'tcx>,
candidate_impls: &[ImplCandidate<'tcx>],
span: Span,
) {
@ -4464,7 +4465,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// 1. `[T; _]` (array of T)
// 2. `&[T; _]` (reference to array of T)
// 3. `&mut [T; _]` (mutable reference to array of T)
let (element_ty, mut mutability) = match *trait_ref.skip_binder().self_ty().kind() {
let (element_ty, mut mutability) = match *trait_pred.skip_binder().self_ty().kind() {
ty::Array(element_ty, _) => (element_ty, None),
ty::Ref(_, pointee_ty, mutability) => match *pointee_ty.kind() {
@ -4620,14 +4621,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
pub(super) fn suggest_desugaring_async_fn_in_trait(
&self,
err: &mut Diag<'_>,
trait_ref: ty::PolyTraitRef<'tcx>,
trait_pred: ty::PolyTraitPredicate<'tcx>,
) {
// Don't suggest if RTN is active -- we should prefer a where-clause bound instead.
if self.tcx.features().return_type_notation() {
return;
}
let trait_def_id = trait_ref.def_id();
let trait_def_id = trait_pred.def_id();
// Only suggest specifying auto traits
if !self.tcx.trait_is_auto(trait_def_id) {
@ -4635,7 +4636,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
// Look for an RPITIT
let ty::Alias(ty::Projection, alias_ty) = trait_ref.self_ty().skip_binder().kind() else {
let ty::Alias(ty::Projection, alias_ty) = trait_pred.self_ty().skip_binder().kind() else {
return;
};
let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) =

View file

@ -16,7 +16,7 @@ use rustc_infer::traits::{
Obligation, ObligationCause, PolyTraitObligation, PredicateObligations, SelectionError,
};
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt, TypingMode};
use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode};
use rustc_middle::{bug, span_bug};
use rustc_type_ir::Interner;
use tracing::{debug, instrument, trace};
@ -186,10 +186,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
selcx.infcx.probe(|_| {
// We checked the polarity already
match selcx.match_normalize_trait_ref(
obligation,
placeholder_trait_predicate.trait_ref,
bound.to_poly_trait_ref(),
bound.map_bound(|pred| pred.trait_ref),
) {
Ok(None) => {
candidates.vec.push(ProjectionCandidate(idx));

View file

@ -16,7 +16,7 @@ use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::{DefineOpaqueTypes, HigherRankedType, InferOk};
use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData};
use rustc_middle::ty::{self, GenericArgsRef, ToPolyTraitRef, Ty, TyCtxt, Upcast};
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, Upcast};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::DefId;
use rustc_type_ir::elaborate;
@ -458,8 +458,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ensure_sufficient_stack(|| {
let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
let trait_ref = self.infcx.enter_forall_and_leak_universe(poly_trait_ref);
assert_eq!(obligation.predicate.polarity(), ty::PredicatePolarity::Positive);
let trait_ref =
self.infcx.enter_forall_and_leak_universe(obligation.predicate).trait_ref;
let trait_obligations = self.impl_or_trait_obligations(
&cause,
obligation.recursion_depth + 1,