Auto merge of #93298 - lcnr:issue-92113, r=cjgillot
make `find_similar_impl_candidates` even fuzzier continues the good work of `@BGR360` in #92223. I might have overshot a bit and we're now slightly too fuzzy 😅 with this we can now also simplify `simplify_type`, which is nice :3
This commit is contained in:
commit
52dd59ed21
35 changed files with 211 additions and 152 deletions
|
@ -26,7 +26,7 @@ use rustc_middle::mir::interpret;
|
||||||
use rustc_middle::thir;
|
use rustc_middle::thir;
|
||||||
use rustc_middle::traits::specialization_graph;
|
use rustc_middle::traits::specialization_graph;
|
||||||
use rustc_middle::ty::codec::TyEncoder;
|
use rustc_middle::ty::codec::TyEncoder;
|
||||||
use rustc_middle::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences};
|
use rustc_middle::ty::fast_reject::{self, SimplifiedType, SimplifyParams};
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
|
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
|
||||||
use rustc_serialize::{opaque, Encodable, Encoder};
|
use rustc_serialize::{opaque, Encodable, Encoder};
|
||||||
|
@ -2066,7 +2066,6 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplsVisitor<'tcx> {
|
||||||
self.tcx,
|
self.tcx,
|
||||||
trait_ref.self_ty(),
|
trait_ref.self_ty(),
|
||||||
SimplifyParams::No,
|
SimplifyParams::No,
|
||||||
StripReferences::No,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
self.impls
|
self.impls
|
||||||
|
|
|
@ -54,12 +54,6 @@ pub enum SimplifyParams {
|
||||||
No,
|
No,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
|
|
||||||
pub enum StripReferences {
|
|
||||||
Yes,
|
|
||||||
No,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
|
/// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
|
||||||
///
|
///
|
||||||
/// The idea is to get something simple that we can use to quickly decide if two types could unify,
|
/// The idea is to get something simple that we can use to quickly decide if two types could unify,
|
||||||
|
@ -73,8 +67,6 @@ pub enum StripReferences {
|
||||||
/// When using `SimplifyParams::Yes`, we still return a simplified type for params and projections²,
|
/// When using `SimplifyParams::Yes`, we still return a simplified type for params and projections²,
|
||||||
/// the reasoning for this can be seen at the places doing this.
|
/// the reasoning for this can be seen at the places doing this.
|
||||||
///
|
///
|
||||||
/// For diagnostics we strip references with `StripReferences::Yes`. This is currently the best
|
|
||||||
/// way to skip some unhelpful suggestions.
|
|
||||||
///
|
///
|
||||||
/// ¹ meaning that if two outermost layers are different, then the whole types are also different.
|
/// ¹ meaning that if two outermost layers are different, then the whole types are also different.
|
||||||
/// ² FIXME(@lcnr): this seems like it can actually end up being unsound with the way it's used during
|
/// ² FIXME(@lcnr): this seems like it can actually end up being unsound with the way it's used during
|
||||||
|
@ -87,7 +79,6 @@ pub fn simplify_type(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
ty: Ty<'_>,
|
ty: Ty<'_>,
|
||||||
can_simplify_params: SimplifyParams,
|
can_simplify_params: SimplifyParams,
|
||||||
strip_references: StripReferences,
|
|
||||||
) -> Option<SimplifiedType> {
|
) -> Option<SimplifiedType> {
|
||||||
match *ty.kind() {
|
match *ty.kind() {
|
||||||
ty::Bool => Some(BoolSimplifiedType),
|
ty::Bool => Some(BoolSimplifiedType),
|
||||||
|
@ -106,16 +97,7 @@ pub fn simplify_type(
|
||||||
}
|
}
|
||||||
_ => Some(MarkerTraitObjectSimplifiedType),
|
_ => Some(MarkerTraitObjectSimplifiedType),
|
||||||
},
|
},
|
||||||
ty::Ref(_, ty, mutbl) => {
|
ty::Ref(_, _, mutbl) => Some(RefSimplifiedType(mutbl)),
|
||||||
if strip_references == StripReferences::Yes {
|
|
||||||
// For diagnostics, when recommending similar impls we want to
|
|
||||||
// recommend impls even when there is a reference mismatch,
|
|
||||||
// so we treat &T and T equivalently in that case.
|
|
||||||
simplify_type(tcx, ty, can_simplify_params, strip_references)
|
|
||||||
} else {
|
|
||||||
Some(RefSimplifiedType(mutbl))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)),
|
ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)),
|
||||||
ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)),
|
ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)),
|
||||||
ty::GeneratorWitness(ref tys) => {
|
ty::GeneratorWitness(ref tys) => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::traits::specialization_graph;
|
use crate::traits::specialization_graph;
|
||||||
use crate::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences};
|
use crate::ty::fast_reject::{self, SimplifiedType, SimplifyParams};
|
||||||
use crate::ty::fold::TypeFoldable;
|
use crate::ty::fold::TypeFoldable;
|
||||||
use crate::ty::{Ident, Ty, TyCtxt};
|
use crate::ty::{Ident, Ty, TyCtxt};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -150,9 +150,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
) -> impl Iterator<Item = DefId> + 'tcx {
|
) -> impl Iterator<Item = DefId> + 'tcx {
|
||||||
let impls = self.trait_impls_of(def_id);
|
let impls = self.trait_impls_of(def_id);
|
||||||
if let Some(simp) =
|
if let Some(simp) = fast_reject::simplify_type(self, self_ty, SimplifyParams::No) {
|
||||||
fast_reject::simplify_type(self, self_ty, SimplifyParams::No, StripReferences::No)
|
|
||||||
{
|
|
||||||
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
|
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
|
||||||
return impls.iter().copied();
|
return impls.iter().copied();
|
||||||
}
|
}
|
||||||
|
@ -189,9 +187,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
// whose outer level is not a parameter or projection. Especially for things like
|
// whose outer level is not a parameter or projection. Especially for things like
|
||||||
// `T: Clone` this is incredibly useful as we would otherwise look at all the impls
|
// `T: Clone` this is incredibly useful as we would otherwise look at all the impls
|
||||||
// of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on.
|
// of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on.
|
||||||
if let Some(simp) =
|
if let Some(simp) = fast_reject::simplify_type(self, self_ty, SimplifyParams::Yes) {
|
||||||
fast_reject::simplify_type(self, self_ty, SimplifyParams::Yes, StripReferences::No)
|
|
||||||
{
|
|
||||||
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
|
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
|
||||||
for &impl_def_id in impls {
|
for &impl_def_id in impls {
|
||||||
if let result @ Some(_) = f(impl_def_id) {
|
if let result @ Some(_) = f(impl_def_id) {
|
||||||
|
@ -251,7 +247,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(simplified_self_ty) =
|
if let Some(simplified_self_ty) =
|
||||||
fast_reject::simplify_type(tcx, impl_self_ty, SimplifyParams::No, StripReferences::No)
|
fast_reject::simplify_type(tcx, impl_self_ty, SimplifyParams::No)
|
||||||
{
|
{
|
||||||
impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id);
|
impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::traits::{
|
||||||
};
|
};
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
use rustc_middle::traits::specialization_graph::OverlapMode;
|
use rustc_middle::traits::specialization_graph::OverlapMode;
|
||||||
use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
|
use rustc_middle::ty::fast_reject::{self, SimplifyParams};
|
||||||
use rustc_middle::ty::fold::TypeFoldable;
|
use rustc_middle::ty::fold::TypeFoldable;
|
||||||
use rustc_middle::ty::subst::Subst;
|
use rustc_middle::ty::subst::Subst;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
|
@ -82,8 +82,8 @@ where
|
||||||
impl2_ref.iter().flat_map(|tref| tref.substs.types()),
|
impl2_ref.iter().flat_map(|tref| tref.substs.types()),
|
||||||
)
|
)
|
||||||
.any(|(ty1, ty2)| {
|
.any(|(ty1, ty2)| {
|
||||||
let t1 = fast_reject::simplify_type(tcx, ty1, SimplifyParams::No, StripReferences::No);
|
let t1 = fast_reject::simplify_type(tcx, ty1, SimplifyParams::No);
|
||||||
let t2 = fast_reject::simplify_type(tcx, ty2, SimplifyParams::No, StripReferences::No);
|
let t2 = fast_reject::simplify_type(tcx, ty2, SimplifyParams::No);
|
||||||
|
|
||||||
if let (Some(t1), Some(t2)) = (t1, t2) {
|
if let (Some(t1), Some(t2)) = (t1, t2) {
|
||||||
// Simplified successfully
|
// Simplified successfully
|
||||||
|
|
|
@ -21,10 +21,9 @@ use rustc_hir::Item;
|
||||||
use rustc_hir::Node;
|
use rustc_hir::Node;
|
||||||
use rustc_middle::thir::abstract_const::NotConstEvaluatable;
|
use rustc_middle::thir::abstract_const::NotConstEvaluatable;
|
||||||
use rustc_middle::ty::error::ExpectedFound;
|
use rustc_middle::ty::error::ExpectedFound;
|
||||||
use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
|
|
||||||
use rustc_middle::ty::fold::TypeFolder;
|
use rustc_middle::ty::fold::TypeFolder;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable,
|
self, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable,
|
||||||
};
|
};
|
||||||
use rustc_session::DiagnosticMessageId;
|
use rustc_session::DiagnosticMessageId;
|
||||||
use rustc_span::symbol::{kw, sym};
|
use rustc_span::symbol::{kw, sym};
|
||||||
|
@ -40,6 +39,22 @@ use suggestions::InferCtxtExt as _;
|
||||||
|
|
||||||
pub use rustc_infer::traits::error_reporting::*;
|
pub use rustc_infer::traits::error_reporting::*;
|
||||||
|
|
||||||
|
// When outputting impl candidates, prefer showing those that are more similar.
|
||||||
|
//
|
||||||
|
// We also compare candidates after skipping lifetimes, which has a lower
|
||||||
|
// priority than exact matches.
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub enum CandidateSimilarity {
|
||||||
|
Exact { ignoring_lifetimes: bool },
|
||||||
|
Fuzzy { ignoring_lifetimes: bool },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct ImplCandidate<'tcx> {
|
||||||
|
pub trait_ref: ty::TraitRef<'tcx>,
|
||||||
|
pub similarity: CandidateSimilarity,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait InferCtxtExt<'tcx> {
|
pub trait InferCtxtExt<'tcx> {
|
||||||
fn report_fulfillment_errors(
|
fn report_fulfillment_errors(
|
||||||
&self,
|
&self,
|
||||||
|
@ -1143,18 +1158,23 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
|
||||||
error: &MismatchedProjectionTypes<'tcx>,
|
error: &MismatchedProjectionTypes<'tcx>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool;
|
fn fuzzy_match_tys(
|
||||||
|
&self,
|
||||||
|
a: Ty<'tcx>,
|
||||||
|
b: Ty<'tcx>,
|
||||||
|
ignoring_lifetimes: bool,
|
||||||
|
) -> Option<CandidateSimilarity>;
|
||||||
|
|
||||||
fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str>;
|
fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str>;
|
||||||
|
|
||||||
fn find_similar_impl_candidates(
|
fn find_similar_impl_candidates(
|
||||||
&self,
|
&self,
|
||||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
) -> Vec<ty::TraitRef<'tcx>>;
|
) -> Vec<ImplCandidate<'tcx>>;
|
||||||
|
|
||||||
fn report_similar_impl_candidates(
|
fn report_similar_impl_candidates(
|
||||||
&self,
|
&self,
|
||||||
impl_candidates: Vec<ty::TraitRef<'tcx>>,
|
impl_candidates: Vec<ImplCandidate<'tcx>>,
|
||||||
err: &mut DiagnosticBuilder<'_>,
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1446,45 +1466,80 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
|
fn fuzzy_match_tys(
|
||||||
|
&self,
|
||||||
|
mut a: Ty<'tcx>,
|
||||||
|
mut b: Ty<'tcx>,
|
||||||
|
ignoring_lifetimes: bool,
|
||||||
|
) -> Option<CandidateSimilarity> {
|
||||||
/// returns the fuzzy category of a given type, or None
|
/// returns the fuzzy category of a given type, or None
|
||||||
/// if the type can be equated to any type.
|
/// if the type can be equated to any type.
|
||||||
fn type_category(t: Ty<'_>) -> Option<u32> {
|
fn type_category(tcx: TyCtxt<'_>, t: Ty<'_>) -> Option<u32> {
|
||||||
match t.kind() {
|
match t.kind() {
|
||||||
ty::Bool => Some(0),
|
ty::Bool => Some(0),
|
||||||
ty::Char => Some(1),
|
ty::Char => Some(1),
|
||||||
ty::Str => Some(2),
|
ty::Str => Some(2),
|
||||||
ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
|
ty::Adt(def, _) if tcx.is_diagnostic_item(sym::String, def.did) => Some(2),
|
||||||
ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
|
ty::Int(..)
|
||||||
|
| ty::Uint(..)
|
||||||
|
| ty::Float(..)
|
||||||
|
| ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) => Some(4),
|
||||||
ty::Ref(..) | ty::RawPtr(..) => Some(5),
|
ty::Ref(..) | ty::RawPtr(..) => Some(5),
|
||||||
ty::Array(..) | ty::Slice(..) => Some(6),
|
ty::Array(..) | ty::Slice(..) => Some(6),
|
||||||
ty::FnDef(..) | ty::FnPtr(..) => Some(7),
|
ty::FnDef(..) | ty::FnPtr(..) => Some(7),
|
||||||
ty::Dynamic(..) => Some(8),
|
ty::Dynamic(..) => Some(8),
|
||||||
ty::Closure(..) => Some(9),
|
ty::Closure(..) => Some(9),
|
||||||
ty::Tuple(..) => Some(10),
|
ty::Tuple(..) => Some(10),
|
||||||
ty::Projection(..) => Some(11),
|
ty::Param(..) => Some(11),
|
||||||
ty::Param(..) => Some(12),
|
ty::Projection(..) => Some(12),
|
||||||
ty::Opaque(..) => Some(13),
|
ty::Opaque(..) => Some(13),
|
||||||
ty::Never => Some(14),
|
ty::Never => Some(14),
|
||||||
ty::Adt(adt, ..) => match adt.adt_kind() {
|
ty::Adt(..) => Some(15),
|
||||||
AdtKind::Struct => Some(15),
|
ty::Generator(..) => Some(16),
|
||||||
AdtKind::Union => Some(16),
|
ty::Foreign(..) => Some(17),
|
||||||
AdtKind::Enum => Some(17),
|
ty::GeneratorWitness(..) => Some(18),
|
||||||
},
|
|
||||||
ty::Generator(..) => Some(18),
|
|
||||||
ty::Foreign(..) => Some(19),
|
|
||||||
ty::GeneratorWitness(..) => Some(20),
|
|
||||||
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
|
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match (type_category(a), type_category(b)) {
|
let strip_references = |mut t: Ty<'tcx>| -> Ty<'tcx> {
|
||||||
(Some(cat_a), Some(cat_b)) => match (a.kind(), b.kind()) {
|
loop {
|
||||||
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
|
match t.kind() {
|
||||||
_ => cat_a == cat_b,
|
ty::Ref(_, inner, _) | ty::RawPtr(ty::TypeAndMut { ty: inner, .. }) => {
|
||||||
},
|
t = inner
|
||||||
// infer and error can be equated to all types
|
}
|
||||||
_ => true,
|
_ => break t,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if !ignoring_lifetimes {
|
||||||
|
a = strip_references(a);
|
||||||
|
b = strip_references(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
let cat_a = type_category(self.tcx, a)?;
|
||||||
|
let cat_b = type_category(self.tcx, b)?;
|
||||||
|
if a == b {
|
||||||
|
Some(CandidateSimilarity::Exact { ignoring_lifetimes })
|
||||||
|
} else if cat_a == cat_b {
|
||||||
|
match (a.kind(), b.kind()) {
|
||||||
|
(ty::Adt(def_a, _), ty::Adt(def_b, _)) => def_a == def_b,
|
||||||
|
// Matching on references results in a lot of unhelpful
|
||||||
|
// suggestions, so let's just not do that for now.
|
||||||
|
//
|
||||||
|
// We still upgrade successful matches to `ignoring_lifetimes: true`
|
||||||
|
// to prioritize that impl.
|
||||||
|
(ty::Ref(..) | ty::RawPtr(..), ty::Ref(..) | ty::RawPtr(..)) => {
|
||||||
|
self.fuzzy_match_tys(a, b, true).is_some()
|
||||||
|
}
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
.then_some(CandidateSimilarity::Fuzzy { ignoring_lifetimes })
|
||||||
|
} else if ignoring_lifetimes {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
self.fuzzy_match_tys(a, b, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1500,58 +1555,25 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
fn find_similar_impl_candidates(
|
fn find_similar_impl_candidates(
|
||||||
&self,
|
&self,
|
||||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
) -> Vec<ty::TraitRef<'tcx>> {
|
) -> Vec<ImplCandidate<'tcx>> {
|
||||||
// We simplify params and strip references here.
|
self.tcx
|
||||||
//
|
.all_impls(trait_ref.def_id())
|
||||||
// This both removes a lot of unhelpful suggestions, e.g.
|
.filter_map(|def_id| {
|
||||||
// when searching for `&Foo: Trait` it doesn't suggestion `impl Trait for &Bar`,
|
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative {
|
||||||
// while also suggesting impls for `&Foo` when we're looking for `Foo: Trait`.
|
return None;
|
||||||
//
|
}
|
||||||
// The second thing isn't necessarily always a good thing, but
|
|
||||||
// any other simple setup results in a far worse output, so 🤷
|
|
||||||
let simp = fast_reject::simplify_type(
|
|
||||||
self.tcx,
|
|
||||||
trait_ref.skip_binder().self_ty(),
|
|
||||||
SimplifyParams::Yes,
|
|
||||||
StripReferences::Yes,
|
|
||||||
);
|
|
||||||
let all_impls = self.tcx.all_impls(trait_ref.def_id());
|
|
||||||
|
|
||||||
match simp {
|
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
|
||||||
Some(simp) => all_impls
|
|
||||||
.filter_map(|def_id| {
|
self.fuzzy_match_tys(trait_ref.skip_binder().self_ty(), imp.self_ty(), false)
|
||||||
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
|
.map(|similarity| ImplCandidate { trait_ref: imp, similarity })
|
||||||
let imp_simp = fast_reject::simplify_type(
|
})
|
||||||
self.tcx,
|
.collect()
|
||||||
imp.self_ty(),
|
|
||||||
SimplifyParams::Yes,
|
|
||||||
StripReferences::Yes,
|
|
||||||
);
|
|
||||||
if let Some(imp_simp) = imp_simp {
|
|
||||||
if simp != imp_simp {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(imp)
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
None => all_impls
|
|
||||||
.filter_map(|def_id| {
|
|
||||||
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
self.tcx.impl_trait_ref(def_id)
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_similar_impl_candidates(
|
fn report_similar_impl_candidates(
|
||||||
&self,
|
&self,
|
||||||
impl_candidates: Vec<ty::TraitRef<'tcx>>,
|
impl_candidates: Vec<ImplCandidate<'tcx>>,
|
||||||
err: &mut DiagnosticBuilder<'_>,
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
) {
|
) {
|
||||||
if impl_candidates.is_empty() {
|
if impl_candidates.is_empty() {
|
||||||
|
@ -1575,13 +1597,24 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sort impl candidates so that ordering is consistent for UI tests.
|
// Sort impl candidates so that ordering is consistent for UI tests.
|
||||||
let mut normalized_impl_candidates =
|
|
||||||
impl_candidates.iter().copied().map(normalize).collect::<Vec<String>>();
|
|
||||||
|
|
||||||
// Sort before taking the `..end` range,
|
|
||||||
// because the ordering of `impl_candidates` may not be deterministic:
|
// because the ordering of `impl_candidates` may not be deterministic:
|
||||||
// https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
|
// https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
|
||||||
normalized_impl_candidates.sort();
|
//
|
||||||
|
// Prefer more similar candidates first, then sort lexicographically
|
||||||
|
// by their normalized string representation.
|
||||||
|
let mut normalized_impl_candidates_and_similarities = impl_candidates
|
||||||
|
.into_iter()
|
||||||
|
.map(|ImplCandidate { trait_ref, similarity }| {
|
||||||
|
let normalized = normalize(trait_ref);
|
||||||
|
(similarity, normalized)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
normalized_impl_candidates_and_similarities.sort();
|
||||||
|
|
||||||
|
let normalized_impl_candidates = normalized_impl_candidates_and_similarities
|
||||||
|
.into_iter()
|
||||||
|
.map(|(_, normalized)| normalized)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
err.help(&format!(
|
err.help(&format!(
|
||||||
"the following implementations were found:{}{}",
|
"the following implementations were found:{}{}",
|
||||||
|
@ -1744,7 +1777,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
|
let impl_candidates = self
|
||||||
|
.find_similar_impl_candidates(trait_ref)
|
||||||
|
.into_iter()
|
||||||
|
.map(|candidate| candidate.trait_ref)
|
||||||
|
.collect();
|
||||||
let mut err = self.emit_inference_failure_err(
|
let mut err = self.emit_inference_failure_err(
|
||||||
body_id,
|
body_id,
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -56,7 +56,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
trait_ref.substs.types().skip(1),
|
trait_ref.substs.types().skip(1),
|
||||||
impl_trait_ref.substs.types().skip(1),
|
impl_trait_ref.substs.types().skip(1),
|
||||||
)
|
)
|
||||||
.all(|(u, v)| self.fuzzy_match_tys(u, v))
|
.all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some())
|
||||||
{
|
{
|
||||||
fuzzy_match_impls.push(def_id);
|
fuzzy_match_impls.push(def_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ use rustc_infer::infer::LateBoundRegionConversionTime;
|
||||||
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
|
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
|
||||||
use rustc_middle::mir::interpret::ErrorHandled;
|
use rustc_middle::mir::interpret::ErrorHandled;
|
||||||
use rustc_middle::thir::abstract_const::NotConstEvaluatable;
|
use rustc_middle::thir::abstract_const::NotConstEvaluatable;
|
||||||
use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
|
use rustc_middle::ty::fast_reject::{self, SimplifyParams};
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::relate::TypeRelation;
|
use rustc_middle::ty::relate::TypeRelation;
|
||||||
use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef};
|
use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef};
|
||||||
|
@ -2172,14 +2172,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
self.tcx(),
|
self.tcx(),
|
||||||
obligation_ty,
|
obligation_ty,
|
||||||
SimplifyParams::Yes,
|
SimplifyParams::Yes,
|
||||||
StripReferences::No,
|
|
||||||
);
|
|
||||||
let simplified_impl_ty = fast_reject::simplify_type(
|
|
||||||
self.tcx(),
|
|
||||||
impl_ty,
|
|
||||||
SimplifyParams::No,
|
|
||||||
StripReferences::No,
|
|
||||||
);
|
);
|
||||||
|
let simplified_impl_ty =
|
||||||
|
fast_reject::simplify_type(self.tcx(), impl_ty, SimplifyParams::No);
|
||||||
|
|
||||||
simplified_obligation_ty.is_some()
|
simplified_obligation_ty.is_some()
|
||||||
&& simplified_impl_ty.is_some()
|
&& simplified_impl_ty.is_some()
|
||||||
|
|
|
@ -2,7 +2,7 @@ use super::OverlapError;
|
||||||
|
|
||||||
use crate::traits;
|
use crate::traits;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences};
|
use rustc_middle::ty::fast_reject::{self, SimplifiedType, SimplifyParams};
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
|
||||||
|
|
||||||
|
@ -49,12 +49,7 @@ impl ChildrenExt<'_> for Children {
|
||||||
/// Insert an impl into this set of children without comparing to any existing impls.
|
/// Insert an impl into this set of children without comparing to any existing impls.
|
||||||
fn insert_blindly(&mut self, tcx: TyCtxt<'_>, impl_def_id: DefId) {
|
fn insert_blindly(&mut self, tcx: TyCtxt<'_>, impl_def_id: DefId) {
|
||||||
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
|
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
|
||||||
if let Some(st) = fast_reject::simplify_type(
|
if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), SimplifyParams::No) {
|
||||||
tcx,
|
|
||||||
trait_ref.self_ty(),
|
|
||||||
SimplifyParams::No,
|
|
||||||
StripReferences::No,
|
|
||||||
) {
|
|
||||||
debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st);
|
debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st);
|
||||||
self.non_blanket_impls.entry(st).or_default().push(impl_def_id)
|
self.non_blanket_impls.entry(st).or_default().push(impl_def_id)
|
||||||
} else {
|
} else {
|
||||||
|
@ -69,12 +64,7 @@ impl ChildrenExt<'_> for Children {
|
||||||
fn remove_existing(&mut self, tcx: TyCtxt<'_>, impl_def_id: DefId) {
|
fn remove_existing(&mut self, tcx: TyCtxt<'_>, impl_def_id: DefId) {
|
||||||
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
|
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
|
||||||
let vec: &mut Vec<DefId>;
|
let vec: &mut Vec<DefId>;
|
||||||
if let Some(st) = fast_reject::simplify_type(
|
if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), SimplifyParams::No) {
|
||||||
tcx,
|
|
||||||
trait_ref.self_ty(),
|
|
||||||
SimplifyParams::No,
|
|
||||||
StripReferences::No,
|
|
||||||
) {
|
|
||||||
debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st);
|
debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st);
|
||||||
vec = self.non_blanket_impls.get_mut(&st).unwrap();
|
vec = self.non_blanket_impls.get_mut(&st).unwrap();
|
||||||
} else {
|
} else {
|
||||||
|
@ -322,12 +312,7 @@ impl GraphExt for Graph {
|
||||||
|
|
||||||
let mut parent = trait_def_id;
|
let mut parent = trait_def_id;
|
||||||
let mut last_lint = None;
|
let mut last_lint = None;
|
||||||
let simplified = fast_reject::simplify_type(
|
let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), SimplifyParams::No);
|
||||||
tcx,
|
|
||||||
trait_ref.self_ty(),
|
|
||||||
SimplifyParams::No,
|
|
||||||
StripReferences::No,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Descend the specialization tree, where `parent` is the current parent node.
|
// Descend the specialization tree, where `parent` is the current parent node.
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -9,7 +9,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{ExprKind, Node, QPath};
|
use rustc_hir::{ExprKind, Node, QPath};
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
use rustc_middle::ty::fast_reject::{simplify_type, SimplifyParams, StripReferences};
|
use rustc_middle::ty::fast_reject::{simplify_type, SimplifyParams};
|
||||||
use rustc_middle::ty::print::with_crate_prefix;
|
use rustc_middle::ty::print::with_crate_prefix;
|
||||||
use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
|
||||||
use rustc_span::lev_distance;
|
use rustc_span::lev_distance;
|
||||||
|
@ -1748,8 +1748,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// FIXME: Even though negative bounds are not implemented, we could maybe handle
|
// FIXME: Even though negative bounds are not implemented, we could maybe handle
|
||||||
// cases where a positive bound implies a negative impl.
|
// cases where a positive bound implies a negative impl.
|
||||||
(candidates, Vec::new())
|
(candidates, Vec::new())
|
||||||
} else if let Some(simp_rcvr_ty) =
|
} else if let Some(simp_rcvr_ty) = simplify_type(self.tcx, rcvr_ty, SimplifyParams::Yes)
|
||||||
simplify_type(self.tcx, rcvr_ty, SimplifyParams::Yes, StripReferences::No)
|
|
||||||
{
|
{
|
||||||
let mut potential_candidates = Vec::new();
|
let mut potential_candidates = Vec::new();
|
||||||
let mut explicitly_negative = Vec::new();
|
let mut explicitly_negative = Vec::new();
|
||||||
|
@ -1763,12 +1762,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
.any(|imp_did| {
|
.any(|imp_did| {
|
||||||
let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
|
let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
|
||||||
let imp_simp = simplify_type(
|
let imp_simp =
|
||||||
self.tcx,
|
simplify_type(self.tcx, imp.self_ty(), SimplifyParams::Yes);
|
||||||
imp.self_ty(),
|
|
||||||
SimplifyParams::Yes,
|
|
||||||
StripReferences::No,
|
|
||||||
);
|
|
||||||
imp_simp.map_or(false, |s| s == simp_rcvr_ty)
|
imp_simp.map_or(false, |s| s == simp_rcvr_ty)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,6 +15,8 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied
|
||||||
LL | f1(2u32, 4u32);
|
LL | f1(2u32, 4u32);
|
||||||
| ^^ the trait `Foo` is not implemented for `u32`
|
| ^^ the trait `Foo` is not implemented for `u32`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<i32 as Foo>
|
||||||
note: required by a bound in `f1`
|
note: required by a bound in `f1`
|
||||||
--> $DIR/associated-types-path-2.rs:13:14
|
--> $DIR/associated-types-path-2.rs:13:14
|
||||||
|
|
|
|
||||||
|
@ -26,6 +28,9 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied
|
||||||
|
|
|
|
||||||
LL | f1(2u32, 4u32);
|
LL | f1(2u32, 4u32);
|
||||||
| ^^^^ the trait `Foo` is not implemented for `u32`
|
| ^^^^ the trait `Foo` is not implemented for `u32`
|
||||||
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<i32 as Foo>
|
||||||
|
|
||||||
error[E0277]: the trait bound `u32: Foo` is not satisfied
|
error[E0277]: the trait bound `u32: Foo` is not satisfied
|
||||||
--> $DIR/associated-types-path-2.rs:35:8
|
--> $DIR/associated-types-path-2.rs:35:8
|
||||||
|
@ -35,6 +40,8 @@ LL | f1(2u32, 4i32);
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<i32 as Foo>
|
||||||
note: required by a bound in `f1`
|
note: required by a bound in `f1`
|
||||||
--> $DIR/associated-types-path-2.rs:13:14
|
--> $DIR/associated-types-path-2.rs:13:14
|
||||||
|
|
|
|
||||||
|
@ -46,6 +53,9 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied
|
||||||
|
|
|
|
||||||
LL | f1(2u32, 4i32);
|
LL | f1(2u32, 4i32);
|
||||||
| ^^^^ the trait `Foo` is not implemented for `u32`
|
| ^^^^ the trait `Foo` is not implemented for `u32`
|
||||||
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<i32 as Foo>
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/associated-types-path-2.rs:41:18
|
--> $DIR/associated-types-path-2.rs:41:18
|
||||||
|
|
|
@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
|
||||||
LL | type U = str;
|
LL | type U = str;
|
||||||
| ^^^ the trait `Clone` is not implemented for `str`
|
| ^^^ the trait `Clone` is not implemented for `str`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<String as Clone>
|
||||||
note: required by a bound in `X`
|
note: required by a bound in `X`
|
||||||
--> $DIR/hr-associated-type-bound-1.rs:3:33
|
--> $DIR/hr-associated-type-bound-1.rs:3:33
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,8 +4,6 @@ error[E0277]: the trait bound `for<'b> <T as X<'b>>::U: Clone` is not satisfied
|
||||||
LL | fn f<'a, T: X<'a> + ?Sized>(x: &<T as X<'a>>::U) {
|
LL | fn f<'a, T: X<'a> + ?Sized>(x: &<T as X<'a>>::U) {
|
||||||
| ^^^^^ the trait `for<'b> Clone` is not implemented for `<T as X<'b>>::U`
|
| ^^^^^ the trait `for<'b> Clone` is not implemented for `<T as X<'b>>::U`
|
||||||
|
|
|
|
||||||
= help: the following implementations were found:
|
|
||||||
<&T as Clone>
|
|
||||||
note: required by a bound in `X`
|
note: required by a bound in `X`
|
||||||
--> $DIR/hr-associated-type-bound-object.rs:3:33
|
--> $DIR/hr-associated-type-bound-object.rs:3:33
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
|
||||||
LL | type V = str;
|
LL | type V = str;
|
||||||
| ^^^ the trait `Clone` is not implemented for `str`
|
| ^^^ the trait `Clone` is not implemented for `str`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<String as Clone>
|
||||||
note: required by a bound in `Y`
|
note: required by a bound in `Y`
|
||||||
--> $DIR/hr-associated-type-bound-param-1.rs:4:36
|
--> $DIR/hr-associated-type-bound-param-1.rs:4:36
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
|
||||||
LL | T: Z<'a, u16>,
|
LL | T: Z<'a, u16>,
|
||||||
| ^^^^^^^^^^ the trait `Clone` is not implemented for `str`
|
| ^^^^^^^^^^ the trait `Clone` is not implemented for `str`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<String as Clone>
|
||||||
note: required by a bound in `Z`
|
note: required by a bound in `Z`
|
||||||
--> $DIR/hr-associated-type-bound-param-2.rs:6:35
|
--> $DIR/hr-associated-type-bound-param-2.rs:6:35
|
||||||
|
|
|
|
||||||
|
@ -19,6 +21,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
|
||||||
LL | T: Z<'a, u16>,
|
LL | T: Z<'a, u16>,
|
||||||
| ^^^^^^^^^^ the trait `Clone` is not implemented for `str`
|
| ^^^^^^^^^^ the trait `Clone` is not implemented for `str`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<String as Clone>
|
||||||
note: required by a bound in `Z`
|
note: required by a bound in `Z`
|
||||||
--> $DIR/hr-associated-type-bound-param-2.rs:6:35
|
--> $DIR/hr-associated-type-bound-param-2.rs:6:35
|
||||||
|
|
|
|
||||||
|
@ -34,6 +38,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
|
||||||
LL | type W = str;
|
LL | type W = str;
|
||||||
| ^^^ the trait `Clone` is not implemented for `str`
|
| ^^^ the trait `Clone` is not implemented for `str`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<String as Clone>
|
||||||
note: required by a bound in `Z`
|
note: required by a bound in `Z`
|
||||||
--> $DIR/hr-associated-type-bound-param-2.rs:6:35
|
--> $DIR/hr-associated-type-bound-param-2.rs:6:35
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
|
||||||
LL | type U = str;
|
LL | type U = str;
|
||||||
| ^^^ the trait `Clone` is not implemented for `str`
|
| ^^^ the trait `Clone` is not implemented for `str`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<String as Clone>
|
||||||
note: required by a bound in `X`
|
note: required by a bound in `X`
|
||||||
--> $DIR/hr-associated-type-bound-param-3.rs:4:33
|
--> $DIR/hr-associated-type-bound-param-3.rs:4:33
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
|
||||||
LL | type U = str;
|
LL | type U = str;
|
||||||
| ^^^ the trait `Clone` is not implemented for `str`
|
| ^^^ the trait `Clone` is not implemented for `str`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<String as Clone>
|
||||||
note: required by a bound in `X`
|
note: required by a bound in `X`
|
||||||
--> $DIR/hr-associated-type-bound-param-4.rs:4:36
|
--> $DIR/hr-associated-type-bound-param-4.rs:4:36
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
|
||||||
LL | type U = str;
|
LL | type U = str;
|
||||||
| ^^^ the trait `Clone` is not implemented for `str`
|
| ^^^ the trait `Clone` is not implemented for `str`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<String as Clone>
|
||||||
note: required by a bound in `X`
|
note: required by a bound in `X`
|
||||||
--> $DIR/hr-associated-type-bound-param-5.rs:17:45
|
--> $DIR/hr-associated-type-bound-param-5.rs:17:45
|
||||||
|
|
|
|
||||||
|
@ -19,6 +21,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
|
||||||
LL | type U = str;
|
LL | type U = str;
|
||||||
| ^^^ the trait `Clone` is not implemented for `str`
|
| ^^^ the trait `Clone` is not implemented for `str`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<String as Clone>
|
||||||
note: required by a bound in `X`
|
note: required by a bound in `X`
|
||||||
--> $DIR/hr-associated-type-bound-param-5.rs:17:45
|
--> $DIR/hr-associated-type-bound-param-5.rs:17:45
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ error[E0277]: the trait bound `u32: Signed` is not satisfied
|
||||||
LL | is_defaulted::<&'static u32>();
|
LL | is_defaulted::<&'static u32>();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<i32 as Signed>
|
||||||
note: required because of the requirements on the impl of `Defaulted` for `&'static u32`
|
note: required because of the requirements on the impl of `Defaulted` for `&'static u32`
|
||||||
--> $DIR/typeck-default-trait-impl-precedence.rs:10:19
|
--> $DIR/typeck-default-trait-impl-precedence.rs:10:19
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,6 +4,9 @@ error[E0277]: the trait bound `f32: Foo` is not satisfied
|
||||||
LL | gimme::<f32>();
|
LL | gimme::<f32>();
|
||||||
| ^^^ the trait `Foo` is not implemented for `f32`
|
| ^^^ the trait `Foo` is not implemented for `f32`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<i32 as Foo>
|
||||||
|
<u32 as Foo>
|
||||||
note: required by a bound in `gimme`
|
note: required by a bound in `gimme`
|
||||||
--> $DIR/chalk_initial_program.rs:9:13
|
--> $DIR/chalk_initial_program.rs:9:13
|
||||||
|
|
|
|
||||||
|
|
|
@ -17,6 +17,8 @@ error[E0277]: the trait bound `f32: Foo` is not satisfied
|
||||||
LL | impl Baz<f32> for f32 { }
|
LL | impl Baz<f32> for f32 { }
|
||||||
| ^^^^^^^^ the trait `Foo` is not implemented for `f32`
|
| ^^^^^^^^ the trait `Foo` is not implemented for `f32`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<i32 as Foo>
|
||||||
note: required by a bound in `Baz`
|
note: required by a bound in `Baz`
|
||||||
--> $DIR/impl_wf.rs:18:31
|
--> $DIR/impl_wf.rs:18:31
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ error[E0277]: the trait bound `f32: Foo` is not satisfied
|
||||||
LL | type Item = f32;
|
LL | type Item = f32;
|
||||||
| ^^^ the trait `Foo` is not implemented for `f32`
|
| ^^^ the trait `Foo` is not implemented for `f32`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<i32 as Foo>
|
||||||
note: required by a bound in `Bar::Item`
|
note: required by a bound in `Bar::Item`
|
||||||
--> $DIR/impl_wf_2.rs:8:16
|
--> $DIR/impl_wf_2.rs:8:16
|
||||||
|
|
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ LL | let s = S {
|
||||||
| ^ the trait `Foo` is not implemented for `{float}`
|
| ^ the trait `Foo` is not implemented for `{float}`
|
||||||
|
|
|
|
||||||
= help: the following implementations were found:
|
= help: the following implementations were found:
|
||||||
<Option<T> as Foo>
|
|
||||||
<i32 as Foo>
|
<i32 as Foo>
|
||||||
note: required by a bound in `S`
|
note: required by a bound in `S`
|
||||||
--> $DIR/type_wf.rs:6:13
|
--> $DIR/type_wf.rs:6:13
|
||||||
|
|
|
@ -15,6 +15,7 @@ LL | fn uwu<const N: u8>() -> impl Traitor<N> {
|
||||||
|
|
|
|
||||||
= help: the following implementations were found:
|
= help: the following implementations were found:
|
||||||
<u32 as Traitor<N, 2_u8>>
|
<u32 as Traitor<N, 2_u8>>
|
||||||
|
<u64 as Traitor<1_u8, 2_u8>>
|
||||||
|
|
||||||
error[E0277]: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied
|
error[E0277]: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied
|
||||||
--> $DIR/rp_impl_trait_fail.rs:22:13
|
--> $DIR/rp_impl_trait_fail.rs:22:13
|
||||||
|
@ -24,6 +25,7 @@ LL | fn owo() -> impl Traitor {
|
||||||
|
|
|
|
||||||
= help: the following implementations were found:
|
= help: the following implementations were found:
|
||||||
<u64 as Traitor<1_u8, 2_u8>>
|
<u64 as Traitor<1_u8, 2_u8>>
|
||||||
|
<u32 as Traitor<N, 2_u8>>
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ LL | Foo::<i32>::bar(&1i8);
|
||||||
<i8 as Foo<u16>>
|
<i8 as Foo<u16>>
|
||||||
<i8 as Foo<u32>>
|
<i8 as Foo<u32>>
|
||||||
<i8 as Foo<u64>>
|
<i8 as Foo<u64>>
|
||||||
<i8 as Foo<u8>>
|
and 5 others
|
||||||
|
|
||||||
error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied
|
error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied
|
||||||
--> $DIR/issue-39802-show-5-trait-impls.rs:25:21
|
--> $DIR/issue-39802-show-5-trait-impls.rs:25:21
|
||||||
|
@ -26,6 +26,7 @@ LL | Foo::<i32>::bar(&1u8);
|
||||||
<u8 as Foo<u16>>
|
<u8 as Foo<u16>>
|
||||||
<u8 as Foo<u32>>
|
<u8 as Foo<u32>>
|
||||||
<u8 as Foo<u64>>
|
<u8 as Foo<u64>>
|
||||||
|
and 5 others
|
||||||
|
|
||||||
error[E0277]: the trait bound `bool: Foo<i32>` is not satisfied
|
error[E0277]: the trait bound `bool: Foo<i32>` is not satisfied
|
||||||
--> $DIR/issue-39802-show-5-trait-impls.rs:26:21
|
--> $DIR/issue-39802-show-5-trait-impls.rs:26:21
|
||||||
|
|
|
@ -6,6 +6,10 @@ LL | assert_copy::<&'static mut isize>();
|
||||||
|
|
|
|
||||||
= help: the following implementations were found:
|
= help: the following implementations were found:
|
||||||
<isize as Copy>
|
<isize as Copy>
|
||||||
|
<f32 as Copy>
|
||||||
|
<f64 as Copy>
|
||||||
|
<i128 as Copy>
|
||||||
|
and 10 others
|
||||||
note: required by a bound in `assert_copy`
|
note: required by a bound in `assert_copy`
|
||||||
--> $DIR/kindck-copy.rs:5:18
|
--> $DIR/kindck-copy.rs:5:18
|
||||||
|
|
|
|
||||||
|
@ -20,6 +24,10 @@ LL | assert_copy::<&'a mut isize>();
|
||||||
|
|
|
|
||||||
= help: the following implementations were found:
|
= help: the following implementations were found:
|
||||||
<isize as Copy>
|
<isize as Copy>
|
||||||
|
<f32 as Copy>
|
||||||
|
<f64 as Copy>
|
||||||
|
<i128 as Copy>
|
||||||
|
and 10 others
|
||||||
note: required by a bound in `assert_copy`
|
note: required by a bound in `assert_copy`
|
||||||
--> $DIR/kindck-copy.rs:5:18
|
--> $DIR/kindck-copy.rs:5:18
|
||||||
|
|
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
|
||||||
LL | default type U = str;
|
LL | default type U = str;
|
||||||
| ^^^ the trait `Clone` is not implemented for `str`
|
| ^^^ the trait `Clone` is not implemented for `str`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<String as Clone>
|
||||||
note: required by a bound in `X::U`
|
note: required by a bound in `X::U`
|
||||||
--> $DIR/default-associated-type-bound-1.rs:8:13
|
--> $DIR/default-associated-type-bound-1.rs:8:13
|
||||||
|
|
|
|
||||||
|
|
|
@ -7,6 +7,12 @@ LL | foo(String::new());
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
= note: to coerce a `String` into a `&str`, use `&*` as a prefix
|
= note: to coerce a `String` into a `&str`, use `&*` as a prefix
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<String as From<&String>>
|
||||||
|
<String as From<&mut str>>
|
||||||
|
<String as From<&str>>
|
||||||
|
<String as From<Box<str>>>
|
||||||
|
and 2 others
|
||||||
= note: required because of the requirements on the impl of `Into<&str>` for `String`
|
= note: required because of the requirements on the impl of `Into<&str>` for `String`
|
||||||
note: required by a bound in `foo`
|
note: required by a bound in `foo`
|
||||||
--> $DIR/into-str.rs:1:31
|
--> $DIR/into-str.rs:1:31
|
||||||
|
|
|
@ -4,6 +4,9 @@ error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied
|
||||||
LL | let _: &[i8] = data.into();
|
LL | let _: &[i8] = data.into();
|
||||||
| ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`
|
| ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<[T; LANES] as From<Simd<T, LANES>>>
|
||||||
|
<[bool; LANES] as From<Mask<T, LANES>>>
|
||||||
= note: required because of the requirements on the impl of `Into<&[i8]>` for `&[u8]`
|
= note: required because of the requirements on the impl of `Into<&[i8]>` for `&[u8]`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
|
@ -6,6 +6,8 @@ LL | bar(a);
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<&f32 as Tr>
|
||||||
note: required by a bound in `bar`
|
note: required by a bound in `bar`
|
||||||
--> $DIR/issue-84973-negative.rs:5:11
|
--> $DIR/issue-84973-negative.rs:5:11
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
|
||||||
LL | f::<dyn X<Y = str>>();
|
LL | f::<dyn X<Y = str>>();
|
||||||
| ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
|
| ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<String as Clone>
|
||||||
note: required by a bound in `f`
|
note: required by a bound in `f`
|
||||||
--> $DIR/check-trait-object-bounds-1.rs:7:9
|
--> $DIR/check-trait-object-bounds-1.rs:7:9
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
|
||||||
LL | f::<dyn X<Y = str>>();
|
LL | f::<dyn X<Y = str>>();
|
||||||
| ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
|
| ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<String as Clone>
|
||||||
note: required by a bound in `f`
|
note: required by a bound in `f`
|
||||||
--> $DIR/check-trait-object-bounds-4.rs:10:9
|
--> $DIR/check-trait-object-bounds-4.rs:10:9
|
||||||
|
|
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ LL | opts.get(<String as AsRef<[u8]>>::as_ref(opt));
|
||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
LL | opts.get(<String as AsRef<str>>::as_ref(opt));
|
LL | opts.get(<String as AsRef<str>>::as_ref(opt));
|
||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
and 4 other candidates
|
||||||
|
|
||||||
error[E0283]: type annotations needed
|
error[E0283]: type annotations needed
|
||||||
--> $DIR/issue-77982.rs:13:44
|
--> $DIR/issue-77982.rs:13:44
|
||||||
|
|
|
@ -9,6 +9,8 @@ LL | bar: &'a mut T
|
||||||
|
|
|
|
||||||
= help: the following implementations were found:
|
= help: the following implementations were found:
|
||||||
<&T as Clone>
|
<&T as Clone>
|
||||||
|
<*const T as Clone>
|
||||||
|
<*mut T as Clone>
|
||||||
= note: `Clone` is implemented for `&T`, but not for `&mut T`
|
= note: `Clone` is implemented for `&T`, but not for `&mut T`
|
||||||
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@ LL | takes_type_parameter(&string); // Error
|
||||||
| | help: consider adding dereference here: `&*string`
|
| | help: consider adding dereference here: `&*string`
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
|
= help: the following implementations were found:
|
||||||
|
<&str as SomeTrait>
|
||||||
note: required by a bound in `takes_type_parameter`
|
note: required by a bound in `takes_type_parameter`
|
||||||
--> $DIR/issue-62530.rs:4:44
|
--> $DIR/issue-62530.rs:4:44
|
||||||
|
|
|
|
||||||
|
|
|
@ -10,6 +10,9 @@ LL | Ok(Err(123_i32)?)
|
||||||
= help: the following implementations were found:
|
= help: the following implementations were found:
|
||||||
<u8 as From<NonZeroU8>>
|
<u8 as From<NonZeroU8>>
|
||||||
<u8 as From<bool>>
|
<u8 as From<bool>>
|
||||||
|
<f32 as From<i16>>
|
||||||
|
<f32 as From<i8>>
|
||||||
|
and 71 others
|
||||||
= note: required because of the requirements on the impl of `FromResidual<Result<Infallible, i32>>` for `Result<u64, u8>`
|
= note: required because of the requirements on the impl of `FromResidual<Result<Infallible, i32>>` for `Result<u64, u8>`
|
||||||
|
|
||||||
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
|
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue