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

View file

@ -79,8 +79,7 @@ pub use self::predicate::{
PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef, PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef,
PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate, PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
PolyTraitRef, PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate, PolyTraitRef, PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef, TraitPredicate, TraitRef, RegionOutlivesPredicate, SubtypePredicate, TraitPredicate, TraitRef, TypeOutlivesPredicate,
TypeOutlivesPredicate,
}; };
pub use self::region::{ pub use self::region::{
BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, LateParamRegionKind, 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> { impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PredicateKind<'tcx>> for Predicate<'tcx> {
fn upcast_from(from: PredicateKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self { fn upcast_from(from: PredicateKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
ty::Binder::dummy(from).upcast(tcx) ty::Binder::dummy(from).upcast(tcx)

View file

@ -172,14 +172,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let bound_predicate = predicate.kind(); let bound_predicate = predicate.kind();
let mut err = match bound_predicate.skip_binder() { let mut err = match bound_predicate.skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
let trait_ref = bound_predicate.rebind(data.trait_ref); let trait_pred = bound_predicate.rebind(data);
debug!(?trait_ref); debug!(?trait_pred);
if let Err(e) = predicate.error_reported() { if let Err(e) = predicate.error_reported() {
return e; 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 // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
// other `Foo` impls are incoherent. // other `Foo` impls are incoherent.
return guar; return guar;
@ -200,13 +200,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// avoid inundating the user with unnecessary errors, but we now // avoid inundating the user with unnecessary errors, but we now
// check upstream for type errors and don't add the obligations to // check upstream for type errors and don't add the obligations to
// begin with in those cases. // 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() { match self.tainted_by_errors() {
None => { None => {
let err = self.emit_inference_failure_err( let err = self.emit_inference_failure_err(
obligation.cause.body_id, obligation.cause.body_id,
span, span,
trait_ref.self_ty().skip_binder().into(), trait_pred.self_ty().skip_binder().into(),
TypeAnnotationNeeded::E0282, TypeAnnotationNeeded::E0282,
false, false,
); );
@ -251,10 +251,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let mut ambiguities = compute_applicable_impls_for_diagnostics( let mut ambiguities = compute_applicable_impls_for_diagnostics(
self.infcx, self.infcx,
&obligation.with(self.tcx, trait_ref), &obligation.with(self.tcx, trait_pred),
); );
let has_non_region_infer = let has_non_region_infer = trait_pred
trait_ref.skip_binder().args.types().any(|t| !t.is_ty_or_numeric_infer()); .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 // 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 // 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. // 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 { if impl_candidates.len() < 40 {
self.report_similar_impl_candidates( self.report_similar_impl_candidates(
impl_candidates.as_slice(), impl_candidates.as_slice(),
trait_ref, trait_pred,
obligation.cause.body_id, obligation.cause.body_id,
&mut err, &mut err,
false, false,
@ -306,7 +310,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if let ObligationCauseCode::WhereClause(def_id, _) if let ObligationCauseCode::WhereClause(def_id, _)
| ObligationCauseCode::WhereClauseInExpr(def_id, ..) = *obligation.cause.code() | 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()) 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 _, FmtPrinter, Print, PrintPolyTraitPredicateExt, PrintTraitPredicateExt as _,
PrintTraitRefExt as _, with_forced_trimmed_paths, PrintTraitRefExt as _, with_forced_trimmed_paths,
}; };
use rustc_middle::ty::{ use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast};
self, ToPolyTraitRef, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast,
};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::{BytePos, DUMMY_SP, STDLIB_STABLE_CRATES, Span, Symbol, sym}; use rustc_span::{BytePos, DUMMY_SP, STDLIB_STABLE_CRATES, Span, Symbol, sym};
use tracing::{debug, instrument}; use tracing::{debug, instrument};
@ -155,12 +153,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
(leaf_trait_predicate, &obligation) (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( if let Some(guar) = self.emit_specialized_closure_kind_error(
&obligation, &obligation,
leaf_trait_ref, leaf_trait_predicate,
) { ) {
return guar; 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); } = self.on_unimplemented_note(main_trait_predicate, main_obligation, &mut long_ty_file);
let have_alt_message = message.is_some() || label.is_some(); 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 = 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 { let (message, notes, append_const_msg) = if is_try_conversion {
( (
Some(format!( Some(format!(
"`?` couldn't convert the error to `{}`", "`?` couldn't convert the error to `{}`",
main_trait_ref.skip_binder().self_ty(), main_trait_predicate.skip_binder().self_ty(),
)), )),
vec![ vec![
"the question mark operation (`?`) implicitly performs a \ "the question mark operation (`?`) implicitly performs a \
@ -230,12 +225,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
post_message, 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 // Recompute the safe transmute reason and use that for the error reporting
match self.get_safe_transmute_error_and_reason( match self.get_safe_transmute_error_and_reason(
obligation.clone(), obligation.clone(),
main_trait_ref, main_trait_predicate,
span, span,
) { ) {
GetSafeTransmuteErrorAndReason::Silent => { GetSafeTransmuteErrorAndReason::Silent => {
@ -266,7 +261,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
} }
let mut suggested = false; let mut suggested = false;
if is_try_conversion { 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) { 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, ret_span,
format!( format!(
"expected `{}` because of this", "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( self.add_tuple_trait_message(
obligation.cause.code().peel_derives(), obligation.cause.code().peel_derives(),
&mut err, &mut err,
@ -319,7 +314,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// If it has a custom `#[rustc_on_unimplemented]` // If it has a custom `#[rustc_on_unimplemented]`
// error message, let's display it as the label! // error message, let's display it as the label!
err.span_label(span, s); 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 // 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 // `std::marker::Sized` is not implemented for `T`" as we will point
// at the type param with a label to suggest constraining it. // 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 } = if let ObligationCauseCode::Coercion { source, target } =
*obligation.cause.code().peel_derives() *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( self.suggest_borrowing_for_object_cast(
&mut err, &mut err,
root_obligation, root_obligation,
@ -368,7 +363,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
err.span_label(tcx.def_span(body), s); 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); self.suggest_dereferencing_index(&obligation, &mut err, leaf_trait_predicate);
suggested |= self.suggest_dereferences(&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); 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[..] { suggested = if let &[cand] = &impl_candidates[..] {
let cand = cand.trait_ref; let cand = cand.trait_ref;
if let (ty::FnPtr(..), ty::FnDef(..)) = 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 // Wrap method receivers and `&`-references in parens
let suggestion = if self.tcx.sess.source_map().span_look_ahead(span, ".", Some(50)).is_some() { 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, span,
leaf_trait_predicate, 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_remove_await(&obligation, &mut err);
self.suggest_derive(&obligation, &mut err, leaf_trait_predicate); 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( self.suggest_await_before_try(
&mut err, &mut err,
&obligation, &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, _) = 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() !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
} else { } 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.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 // Return early if the trait is Debug or Display and the invocation
// originates within a standard library macro, because the output // originates within a standard library macro, because the output
@ -527,7 +522,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if in_std_macro if in_std_macro
&& matches!( && 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) Some(sym::Debug | sym::Display)
) )
{ {
@ -785,21 +780,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
fn emit_specialized_closure_kind_error( fn emit_specialized_closure_kind_error(
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
mut trait_ref: ty::PolyTraitRef<'tcx>, mut trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Option<ErrorGuaranteed> { ) -> Option<ErrorGuaranteed> {
// If `AsyncFnKindHelper` is not implemented, that means that the closure kind // 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 // 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 // if we actually know which closure this goal comes from, so look at the cause
// to see if we can extract that information. // to see if we can extract that information.
if self.tcx.is_lang_item(trait_ref.def_id(), LangItem::AsyncFnKindHelper) if self.tcx.is_lang_item(trait_pred.def_id(), LangItem::AsyncFnKindHelper)
&& let Some(found_kind) = trait_ref.skip_binder().args.type_at(0).to_opt_closure_kind() && let Some(found_kind) =
trait_pred.skip_binder().trait_ref.args.type_at(0).to_opt_closure_kind()
&& let Some(expected_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) && !found_kind.extends(expected_kind)
{ {
if let Some((_, Some(parent))) = obligation.cause.code().parent_with_predicate() { 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. // 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, .. } = } else if let &ObligationCauseCode::FunctionArg { arg_hir_id, .. } =
obligation.cause.code() obligation.cause.code()
&& let Some(typeck_results) = &self.typeck_results && 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() { let (closure_def_id, found_args, by_ref_captures) = match *self_ty.kind() {
ty::Closure(def_id, args) => { ty::Closure(def_id, args) => {
(def_id, args.as_closure().sig().map_bound(|sig| sig.inputs()[0]), None) (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, _ => 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 // Verify that the arguments are compatible. If the signature is
// mismatched, then we have a totally different error to report. // mismatched, then we have a totally different error to report.
@ -909,7 +906,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
fn try_conversion_context( fn try_conversion_context(
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
trait_ref: ty::TraitRef<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
err: &mut Diag<'_>, err: &mut Diag<'_>,
) -> bool { ) -> bool {
let span = obligation.cause.span; 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()) { if !self.tcx.is_diagnostic_item(sym::FromResidual, y.def_id()) {
return false; return false;
} }
let self_ty = trait_ref.self_ty(); let self_ty = trait_pred.skip_binder().self_ty();
let found_ty = trait_ref.args.get(1).and_then(|a| a.as_type()); 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( let mut prev_ty = self.resolve_vars_if_possible(
typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)), 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>, goal: ty::TraitPredicate<'tcx>,
assumption: ty::PolyTraitPredicate<'tcx>, assumption: ty::PolyTraitPredicate<'tcx>,
) -> bool { ) -> bool {
// Fast path
if goal.polarity != assumption.polarity() { if goal.polarity != assumption.polarity() {
return false; return false;
} }
let trait_goal = goal.trait_ref;
let trait_assumption = self.instantiate_binder_with_fresh_vars( let trait_assumption = self.instantiate_binder_with_fresh_vars(
DUMMY_SP, DUMMY_SP,
infer::BoundRegionConversionTime::HigherRankedType, 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( fn can_match_projection(
@ -1682,7 +1679,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
pub(super) fn report_similar_impl_candidates( pub(super) fn report_similar_impl_candidates(
&self, &self,
impl_candidates: &[ImplCandidate<'tcx>], impl_candidates: &[ImplCandidate<'tcx>],
trait_ref: ty::PolyTraitRef<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
body_def_id: LocalDefId, body_def_id: LocalDefId,
err: &mut Diag<'_>, err: &mut Diag<'_>,
other: bool, 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 // 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 // one crate version and the type comes from another crate version, even though they both
// are from the same crate. // 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 trait_name = self.tcx.item_name(trait_def_id);
let crate_name = self.tcx.crate_name(trait_def_id.krate); 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| { 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. // different crate `DefId`. We highlight the traits.
let found_type = 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()) Some(def.did())
} else { } else {
None None
@ -1836,7 +1833,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if self.probe(|_| { if self.probe(|_| {
let ocx = ObligationCtxt::new(self); 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_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id);
let impl_trait_ref = ocx.normalize( let impl_trait_ref = ocx.normalize(
&ObligationCause::dummy(), &ObligationCause::dummy(),
@ -1864,7 +1861,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let mut terrs = vec![]; let mut terrs = vec![];
for (obligation_arg, impl_arg) in 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() { if (obligation_arg, impl_arg).references_error() {
return false; return false;
@ -1906,8 +1903,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
} }
let traits = self.cmp_traits( let traits = self.cmp_traits(
obligation_trait_ref.def_id, obligation_trait_ref.def_id(),
&obligation_trait_ref.args[1..], &obligation_trait_ref.trait_ref.args[1..],
impl_trait_ref.def_id, impl_trait_ref.def_id,
&impl_trait_ref.args[1..], &impl_trait_ref.args[1..],
); );
@ -1991,7 +1988,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
} }
if let &[cand] = &candidates[..] { if let &[cand] = &candidates[..] {
let (desc, mention_castable) = 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(..)) => { (ty::FnPtr(..), ty::FnDef(..)) => {
(" implemented for fn pointer `", ", cast using `as`") (" 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)) .filter(|cand| !self.tcx.do_not_recommend_impl(cand.impl_def_id))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let def_id = trait_ref.def_id(); let def_id = trait_pred.def_id();
if impl_candidates.is_empty() { if impl_candidates.is_empty() {
if self.tcx.trait_is_auto(def_id) if self.tcx.trait_is_auto(def_id)
|| self.tcx.lang_items().iter().any(|(_, id)| id == 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.trait_is_auto(def_id)
&& !self.tcx.lang_items().iter().any(|(_, id)| id == 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); let impl_candidates = self.find_similar_impl_candidates(trait_pred);
self.report_similar_impl_candidates( self.report_similar_impl_candidates(
&impl_candidates, &impl_candidates,
trait_ref, trait_pred,
body_def_id, body_def_id,
err, err,
true, true,
@ -2173,12 +2169,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
/// with the same path as `trait_ref`, a help message about /// with the same path as `trait_ref`, a help message about
/// a probable version mismatch is added to `err` /// 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 get_trait_impls = |trait_def_id| {
let mut trait_impls = vec![]; let mut trait_impls = vec![];
self.tcx.for_each_relevant_impl( self.tcx.for_each_relevant_impl(
trait_def_id, trait_def_id,
trait_ref.skip_binder().self_ty(), trait_pred.skip_binder().self_ty(),
|impl_def_id| { |impl_def_id| {
trait_impls.push(impl_def_id); trait_impls.push(impl_def_id);
}, },
@ -2186,11 +2186,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
trait_impls 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 let traits_with_same_path: UnordSet<_> = self
.tcx .tcx
.visible_traits() .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)) .map(|trait_def_id| (self.tcx.def_path_str(trait_def_id), trait_def_id))
.filter(|(p, _)| *p == required_trait_path) .filter(|(p, _)| *p == required_trait_path)
.collect(); .collect();
@ -2374,7 +2374,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
fn get_safe_transmute_error_and_reason( fn get_safe_transmute_error_and_reason(
&self, &self,
obligation: PredicateObligation<'tcx>, obligation: PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
span: Span, span: Span,
) -> GetSafeTransmuteErrorAndReason { ) -> GetSafeTransmuteErrorAndReason {
use rustc_transmute::Answer; 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. // Erase regions because layout code doesn't particularly care about regions.
let trait_ref = let trait_pred =
self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_ref)); self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_pred));
let src_and_dst = rustc_transmute::Types { let src_and_dst = rustc_transmute::Types {
dst: trait_ref.args.type_at(0), dst: trait_pred.trait_ref.args.type_at(0),
src: trait_ref.args.type_at(1), src: trait_pred.trait_ref.args.type_at(1),
}; };
let ocx = ObligationCtxt::new(self); let ocx = ObligationCtxt::new(self);
let Ok(assume) = ocx.structurally_normalize_const( let Ok(assume) = ocx.structurally_normalize_const(
&obligation.cause, &obligation.cause,
obligation.param_env, obligation.param_env,
trait_ref.args.const_at(2), trait_pred.trait_ref.args.const_at(2),
) else { ) else {
self.dcx().span_delayed_bug( self.dcx().span_delayed_bug(
span, span,
@ -2417,8 +2417,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
return GetSafeTransmuteErrorAndReason::Silent; return GetSafeTransmuteErrorAndReason::Silent;
}; };
let dst = trait_ref.args.type_at(0); let dst = trait_pred.trait_ref.args.type_at(0);
let src = trait_ref.args.type_at(1); let src = trait_pred.trait_ref.args.type_at(1);
let err_msg = format!("`{src}` cannot be safely transmuted into `{dst}`"); let err_msg = format!("`{src}` cannot be safely transmuted into `{dst}`");
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable( match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
@ -2566,12 +2566,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
trait_predicate.skip_binder().polarity, trait_predicate.skip_binder().polarity,
) )
{ {
self.add_help_message_for_fn_trait( self.add_help_message_for_fn_trait(trait_predicate, err, implemented_kind, params);
trait_predicate.to_poly_trait_ref(),
err,
implemented_kind,
params,
);
} else if !trait_predicate.has_non_region_infer() } else if !trait_predicate.has_non_region_infer()
&& self.predicate_can_apply(obligation.param_env, trait_predicate) && 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); let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
if !self.report_similar_impl_candidates( if !self.report_similar_impl_candidates(
&impl_candidates, &impl_candidates,
trait_predicate.to_poly_trait_ref(), trait_predicate,
body_def_id, body_def_id,
err, err,
true, true,
@ -2623,7 +2618,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
self.suggest_convert_to_slice( self.suggest_convert_to_slice(
err, err,
obligation, obligation,
trait_predicate.to_poly_trait_ref(), trait_predicate,
impl_candidates.as_slice(), impl_candidates.as_slice(),
span, span,
); );
@ -2634,7 +2629,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
fn add_help_message_for_fn_trait( fn add_help_message_for_fn_trait(
&self, &self,
trait_ref: ty::PolyTraitRef<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
err: &mut Diag<'_>, err: &mut Diag<'_>,
implemented_kind: ty::ClosureKind, implemented_kind: ty::ClosureKind,
params: ty::Binder<'tcx, Ty<'tcx>>, params: ty::Binder<'tcx, Ty<'tcx>>,
@ -2647,12 +2642,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// to implement. // to implement.
let selected_kind = self let selected_kind = self
.tcx .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"); .expect("expected to map DefId to ClosureKind");
if !implemented_kind.extends(selected_kind) { if !implemented_kind.extends(selected_kind) {
err.note(format!( err.note(format!(
"`{}` implements `{}`, but it must implement `{}`, which is more general", "`{}` implements `{}`, but it must implement `{}`, which is more general",
trait_ref.skip_binder().self_ty(), trait_pred.skip_binder().self_ty(),
implemented_kind, implemented_kind,
selected_kind selected_kind
)); ));
@ -2660,7 +2655,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// Note any argument mismatches // Note any argument mismatches
let given_ty = params.skip_binder(); 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() if let ty::Tuple(given) = given_ty.kind()
&& let ty::Tuple(expected) = expected_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_macros::LintDiagnostic;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty::print::PrintTraitRefExt as _; 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_parse_format::{ParseMode, Parser, Piece, Position};
use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES; use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES;
use rustc_span::{Span, Symbol, kw, sym}; use rustc_span::{Span, Symbol, kw, sym};
@ -42,18 +42,18 @@ static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[
impl<'tcx> TypeErrCtxt<'_, 'tcx> { impl<'tcx> TypeErrCtxt<'_, 'tcx> {
fn impl_similar_to( fn impl_similar_to(
&self, &self,
trait_ref: ty::PolyTraitRef<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
) -> Option<(DefId, GenericArgsRef<'tcx>)> { ) -> Option<(DefId, GenericArgsRef<'tcx>)> {
let tcx = self.tcx; let tcx = self.tcx;
let param_env = obligation.param_env; let param_env = obligation.param_env;
self.enter_forall(trait_ref, |trait_ref| { self.enter_forall(trait_pred, |trait_pred| {
let trait_self_ty = trait_ref.self_ty(); let trait_self_ty = trait_pred.self_ty();
let mut self_match_impls = vec![]; let mut self_match_impls = vec![];
let mut fuzzy_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_args = self.fresh_args_for_item(obligation.cause.span, def_id);
let impl_trait_ref = let impl_trait_ref =
tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args); 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)); self_match_impls.push((def_id, impl_args));
if iter::zip( if iter::zip(
trait_ref.args.types().skip(1), trait_pred.trait_ref.args.types().skip(1),
impl_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()) .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 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)); .unwrap_or_else(|| (trait_pred.def_id(), trait_pred.skip_binder().trait_ref.args));
let trait_pred = trait_pred.skip_binder(); 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, with_forced_trimmed_paths, with_no_trimmed_paths,
}; };
use rustc_middle::ty::{ use rustc_middle::ty::{
self, AdtKind, GenericArgs, InferTy, IsSuggestable, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable, self, AdtKind, GenericArgs, InferTy, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeFolder,
TypeFolder, TypeSuperFoldable, TypeVisitableExt, TypeckResults, Upcast, TypeSuperFoldable, TypeVisitableExt, TypeckResults, Upcast, suggest_arbitrary_trait_bound,
suggest_arbitrary_trait_bound, suggest_constraining_type_param, suggest_constraining_type_param,
}; };
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::def_id::LocalDefId; 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) => predicate_constraint(hir_generics, trait_pred.upcast(tcx)),
(None, Some((ident, []))) => ( (None, Some((ident, []))) => (
ident.span.shrink_to_hi(), 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]))) => ( (_, Some((_, [.., bounds]))) => (
bounds.span().shrink_to_hi(), 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((_, []))) => ( (Some(_), Some((_, []))) => (
hir_generics.span.shrink_to_hi(), 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, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>, err: &mut Diag<'_>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
) { ) {
let rhs_span = match obligation.cause.code() { let rhs_span = match obligation.cause.code() {
ObligationCauseCode::BinOp { rhs_span: Some(span), rhs_is_lit, .. } if *rhs_is_lit => { ObligationCauseCode::BinOp { rhs_span: Some(span), rhs_is_lit, .. } if *rhs_is_lit => {
@ -3737,8 +3737,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
} }
_ => return, _ => return,
}; };
if let ty::Float(_) = trait_ref.skip_binder().self_ty().kind() if let ty::Float(_) = trait_pred.skip_binder().self_ty().kind()
&& let ty::Infer(InferTy::IntVar(_)) = trait_ref.skip_binder().args.type_at(1).kind() && let ty::Infer(InferTy::IntVar(_)) =
trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
{ {
err.span_suggestion_verbose( err.span_suggestion_verbose(
rhs_span.shrink_to_hi(), rhs_span.shrink_to_hi(),
@ -4448,7 +4449,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
&self, &self,
err: &mut Diag<'_>, err: &mut Diag<'_>,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
candidate_impls: &[ImplCandidate<'tcx>], candidate_impls: &[ImplCandidate<'tcx>],
span: Span, span: Span,
) { ) {
@ -4464,7 +4465,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// 1. `[T; _]` (array of T) // 1. `[T; _]` (array of T)
// 2. `&[T; _]` (reference to array of T) // 2. `&[T; _]` (reference to array of T)
// 3. `&mut [T; _]` (mutable 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::Array(element_ty, _) => (element_ty, None),
ty::Ref(_, pointee_ty, mutability) => match *pointee_ty.kind() { 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( pub(super) fn suggest_desugaring_async_fn_in_trait(
&self, &self,
err: &mut Diag<'_>, 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. // Don't suggest if RTN is active -- we should prefer a where-clause bound instead.
if self.tcx.features().return_type_notation() { if self.tcx.features().return_type_notation() {
return; return;
} }
let trait_def_id = trait_ref.def_id(); let trait_def_id = trait_pred.def_id();
// Only suggest specifying auto traits // Only suggest specifying auto traits
if !self.tcx.trait_is_auto(trait_def_id) { if !self.tcx.trait_is_auto(trait_def_id) {
@ -4635,7 +4636,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
} }
// Look for an RPITIT // 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; return;
}; };
let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) = 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, Obligation, ObligationCause, PolyTraitObligation, PredicateObligations, SelectionError,
}; };
use rustc_middle::ty::fast_reject::DeepRejectCtxt; 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_middle::{bug, span_bug};
use rustc_type_ir::Interner; use rustc_type_ir::Interner;
use tracing::{debug, instrument, trace}; use tracing::{debug, instrument, trace};
@ -186,10 +186,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} }
selcx.infcx.probe(|_| { selcx.infcx.probe(|_| {
// We checked the polarity already
match selcx.match_normalize_trait_ref( match selcx.match_normalize_trait_ref(
obligation, obligation,
placeholder_trait_predicate.trait_ref, placeholder_trait_predicate.trait_ref,
bound.to_poly_trait_ref(), bound.map_bound(|pred| pred.trait_ref),
) { ) {
Ok(None) => { Ok(None) => {
candidates.vec.push(ProjectionCandidate(idx)); 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::infer::{DefineOpaqueTypes, HigherRankedType, InferOk};
use rustc_infer::traits::ObligationCauseCode; use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData}; 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_middle::{bug, span_bug};
use rustc_span::def_id::DefId; use rustc_span::def_id::DefId;
use rustc_type_ir::elaborate; use rustc_type_ir::elaborate;
@ -458,8 +458,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ensure_sufficient_stack(|| { ensure_sufficient_stack(|| {
let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); assert_eq!(obligation.predicate.polarity(), ty::PredicatePolarity::Positive);
let trait_ref = self.infcx.enter_forall_and_leak_universe(poly_trait_ref); let trait_ref =
self.infcx.enter_forall_and_leak_universe(obligation.predicate).trait_ref;
let trait_obligations = self.impl_or_trait_obligations( let trait_obligations = self.impl_or_trait_obligations(
&cause, &cause,
obligation.recursion_depth + 1, obligation.recursion_depth + 1,