Get rid of ToPolyTraitRef
This commit is contained in:
parent
8321f00bf4
commit
2a180a93a1
9 changed files with 116 additions and 125 deletions
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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 }) =
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue