extend simplify_type

This commit is contained in:
lcnr 2021-05-07 20:00:02 +02:00
parent 83b32f27fc
commit dcd716fee2
10 changed files with 132 additions and 43 deletions

View file

@ -26,6 +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, SimplifyParams, StripReferences};
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};
use rustc_session::config::CrateType; use rustc_session::config::CrateType;
@ -2033,15 +2034,19 @@ impl EncodeContext<'a, 'tcx> {
struct ImplVisitor<'tcx> { struct ImplVisitor<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
impls: FxHashMap<DefId, Vec<(DefIndex, Option<ty::fast_reject::SimplifiedType>)>>, impls: FxHashMap<DefId, Vec<(DefIndex, Option<fast_reject::SimplifiedType>)>>,
} }
impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> { impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
fn visit_item(&mut self, item: &hir::Item<'_>) { fn visit_item(&mut self, item: &hir::Item<'_>) {
if let hir::ItemKind::Impl { .. } = item.kind { if let hir::ItemKind::Impl { .. } = item.kind {
if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) { if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) {
let simplified_self_ty = let simplified_self_ty = fast_reject::simplify_type(
ty::fast_reject::simplify_type(self.tcx, trait_ref.self_ty(), false); self.tcx,
trait_ref.self_ty(),
SimplifyParams::No,
StripReferences::No,
);
self.impls self.impls
.entry(trait_ref.def_id) .entry(trait_ref.def_id)

View file

@ -1,3 +1,4 @@
use crate::mir::Mutability;
use crate::ty::{self, Ty, TyCtxt}; use crate::ty::{self, Ty, TyCtxt};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -27,9 +28,12 @@ where
UintSimplifiedType(ty::UintTy), UintSimplifiedType(ty::UintTy),
FloatSimplifiedType(ty::FloatTy), FloatSimplifiedType(ty::FloatTy),
AdtSimplifiedType(D), AdtSimplifiedType(D),
ForeignSimplifiedType(DefId),
StrSimplifiedType, StrSimplifiedType,
ArraySimplifiedType, ArraySimplifiedType,
PtrSimplifiedType, SliceSimplifiedType,
RefSimplifiedType(Mutability),
PtrSimplifiedType(Mutability),
NeverSimplifiedType, NeverSimplifiedType,
TupleSimplifiedType(usize), TupleSimplifiedType(usize),
/// A trait object, all of whose components are markers /// A trait object, all of whose components are markers
@ -42,7 +46,18 @@ where
OpaqueSimplifiedType(D), OpaqueSimplifiedType(D),
FunctionSimplifiedType(usize), FunctionSimplifiedType(usize),
ParameterSimplifiedType, ParameterSimplifiedType,
ForeignSimplifiedType(DefId), }
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
pub enum SimplifyParams {
Yes,
No,
}
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
pub enum StripReferences {
Yes,
No,
} }
/// Tries to simplify a type by dropping type parameters, deref'ing away any reference types, etc. /// Tries to simplify a type by dropping type parameters, deref'ing away any reference types, etc.
@ -57,7 +72,8 @@ where
pub fn simplify_type( pub fn simplify_type(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
ty: Ty<'_>, ty: Ty<'_>,
can_simplify_params: bool, 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),
@ -67,19 +83,24 @@ pub fn simplify_type(
ty::Float(float_type) => Some(FloatSimplifiedType(float_type)), ty::Float(float_type) => Some(FloatSimplifiedType(float_type)),
ty::Adt(def, _) => Some(AdtSimplifiedType(def.did)), ty::Adt(def, _) => Some(AdtSimplifiedType(def.did)),
ty::Str => Some(StrSimplifiedType), ty::Str => Some(StrSimplifiedType),
ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType), ty::Array(..) => Some(ArraySimplifiedType),
ty::RawPtr(_) => Some(PtrSimplifiedType), ty::Slice(..) => Some(SliceSimplifiedType),
ty::RawPtr(ptr) => Some(PtrSimplifiedType(ptr.mutbl)),
ty::Dynamic(ref trait_info, ..) => match trait_info.principal_def_id() { ty::Dynamic(ref trait_info, ..) => match trait_info.principal_def_id() {
Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => { Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => {
Some(TraitSimplifiedType(principal_def_id)) Some(TraitSimplifiedType(principal_def_id))
} }
_ => Some(MarkerTraitObjectSimplifiedType), _ => Some(MarkerTraitObjectSimplifiedType),
}, },
ty::Ref(_, ty, _) => { ty::Ref(_, ty, mutbl) => {
// since we introduce auto-refs during method lookup, we if strip_references == StripReferences::Yes {
// just treat &T and T as equivalent from the point of // For diagnostics, when recommending similar impls we want to
// view of possibly unifying // recommend impls even when there is a reference mismatch,
simplify_type(tcx, ty, can_simplify_params) // 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)),
@ -90,7 +111,7 @@ pub fn simplify_type(
ty::Tuple(ref tys) => Some(TupleSimplifiedType(tys.len())), ty::Tuple(ref tys) => Some(TupleSimplifiedType(tys.len())),
ty::FnPtr(ref f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())), ty::FnPtr(ref f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())),
ty::Projection(_) | ty::Param(_) => { ty::Projection(_) | ty::Param(_) => {
if can_simplify_params { if can_simplify_params == SimplifyParams::Yes {
// In normalized types, projections don't unify with // In normalized types, projections don't unify with
// anything. when lazy normalization happens, this // anything. when lazy normalization happens, this
// will change. It would still be nice to have a way // will change. It would still be nice to have a way
@ -120,9 +141,12 @@ impl<D: Copy + Debug + Ord + Eq> SimplifiedTypeGen<D> {
UintSimplifiedType(t) => UintSimplifiedType(t), UintSimplifiedType(t) => UintSimplifiedType(t),
FloatSimplifiedType(t) => FloatSimplifiedType(t), FloatSimplifiedType(t) => FloatSimplifiedType(t),
AdtSimplifiedType(d) => AdtSimplifiedType(map(d)), AdtSimplifiedType(d) => AdtSimplifiedType(map(d)),
ForeignSimplifiedType(d) => ForeignSimplifiedType(d),
StrSimplifiedType => StrSimplifiedType, StrSimplifiedType => StrSimplifiedType,
ArraySimplifiedType => ArraySimplifiedType, ArraySimplifiedType => ArraySimplifiedType,
PtrSimplifiedType => PtrSimplifiedType, SliceSimplifiedType => SliceSimplifiedType,
RefSimplifiedType(m) => RefSimplifiedType(m),
PtrSimplifiedType(m) => PtrSimplifiedType(m),
NeverSimplifiedType => NeverSimplifiedType, NeverSimplifiedType => NeverSimplifiedType,
MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType, MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType,
TupleSimplifiedType(n) => TupleSimplifiedType(n), TupleSimplifiedType(n) => TupleSimplifiedType(n),
@ -133,7 +157,6 @@ impl<D: Copy + Debug + Ord + Eq> SimplifiedTypeGen<D> {
OpaqueSimplifiedType(d) => OpaqueSimplifiedType(map(d)), OpaqueSimplifiedType(d) => OpaqueSimplifiedType(map(d)),
FunctionSimplifiedType(n) => FunctionSimplifiedType(n), FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
ParameterSimplifiedType => ParameterSimplifiedType, ParameterSimplifiedType => ParameterSimplifiedType,
ForeignSimplifiedType(d) => ForeignSimplifiedType(d),
} }
} }
} }
@ -149,12 +172,13 @@ where
| CharSimplifiedType | CharSimplifiedType
| StrSimplifiedType | StrSimplifiedType
| ArraySimplifiedType | ArraySimplifiedType
| PtrSimplifiedType | SliceSimplifiedType
| NeverSimplifiedType | NeverSimplifiedType
| ParameterSimplifiedType | ParameterSimplifiedType
| MarkerTraitObjectSimplifiedType => { | MarkerTraitObjectSimplifiedType => {
// nothing to do // nothing to do
} }
RefSimplifiedType(m) | PtrSimplifiedType(m) => m.hash_stable(hcx, hasher),
IntSimplifiedType(t) => t.hash_stable(hcx, hasher), IntSimplifiedType(t) => t.hash_stable(hcx, hasher),
UintSimplifiedType(t) => t.hash_stable(hcx, hasher), UintSimplifiedType(t) => t.hash_stable(hcx, hasher),
FloatSimplifiedType(t) => t.hash_stable(hcx, hasher), FloatSimplifiedType(t) => t.hash_stable(hcx, hasher),

View file

@ -1,5 +1,5 @@
use crate::traits::specialization_graph; use crate::traits::specialization_graph;
use crate::ty::fast_reject; use crate::ty::fast_reject::{self, SimplifyParams, StripReferences};
use crate::ty::fold::TypeFoldable; use crate::ty::fold::TypeFoldable;
use crate::ty::{Ty, TyCtxt}; use crate::ty::{Ty, TyCtxt};
use rustc_hir as hir; use rustc_hir as hir;
@ -179,7 +179,9 @@ impl<'tcx> TyCtxt<'tcx> {
// blanket and non-blanket impls, and compare them separately. // blanket and non-blanket impls, and compare them separately.
// //
// I think we'll cross that bridge when we get to it. // I think we'll cross that bridge when we get to it.
if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) { if let Some(simp) =
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) {
@ -238,7 +240,9 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
continue; continue;
} }
if let Some(simplified_self_ty) = fast_reject::simplify_type(tcx, impl_self_ty, false) { if let Some(simplified_self_ty) =
fast_reject::simplify_type(tcx, impl_self_ty, SimplifyParams::No, StripReferences::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 {
impls.blanket_impls.push(impl_def_id); impls.blanket_impls.push(impl_def_id);

View file

@ -12,9 +12,10 @@ use crate::traits::{
self, Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext, self, Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext,
}; };
use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
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, fast_reject, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
use std::iter; use std::iter;
@ -82,12 +83,11 @@ 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, false); let t1 = fast_reject::simplify_type(tcx, ty1, SimplifyParams::No, StripReferences::No);
let t2 = fast_reject::simplify_type(tcx, ty2, false); let t2 = fast_reject::simplify_type(tcx, ty2, SimplifyParams::No, StripReferences::No);
if let (Some(t1), Some(t2)) = (t1, t2) { if let (Some(t1), Some(t2)) = (t1, t2) {
// Simplified successfully // Simplified successfully
// Types cannot unify if they differ in their reference mutability or simplify to different types t1 != t2
t1 != t2 || ty1.ref_mutability() != ty2.ref_mutability()
} else { } else {
// Types might unify // Types might unify
false false

View file

@ -21,9 +21,10 @@ 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, fast_reject, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, self, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt,
TypeFoldable, TypeFoldable,
}; };
use rustc_session::DiagnosticMessageId; use rustc_session::DiagnosticMessageId;
@ -1439,14 +1440,24 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
&self, &self,
trait_ref: ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>,
) -> Vec<ty::TraitRef<'tcx>> { ) -> Vec<ty::TraitRef<'tcx>> {
let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true); 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()); let all_impls = self.tcx.all_impls(trait_ref.def_id());
match simp { match simp {
Some(simp) => all_impls Some(simp) => all_impls
.filter_map(|def_id| { .filter_map(|def_id| {
let imp = self.tcx.impl_trait_ref(def_id).unwrap(); let imp = self.tcx.impl_trait_ref(def_id).unwrap();
let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true); let imp_simp = fast_reject::simplify_type(
self.tcx,
imp.self_ty(),
SimplifyParams::Yes,
StripReferences::Yes,
);
if let Some(imp_simp) = imp_simp { if let Some(imp_simp) = imp_simp {
if simp != imp_simp { if simp != imp_simp {
return None; return None;

View file

@ -35,7 +35,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; use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
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};
@ -2089,10 +2089,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|(obligation_arg, impl_arg)| { |(obligation_arg, impl_arg)| {
match (obligation_arg.unpack(), impl_arg.unpack()) { match (obligation_arg.unpack(), impl_arg.unpack()) {
(GenericArgKind::Type(obligation_ty), GenericArgKind::Type(impl_ty)) => { (GenericArgKind::Type(obligation_ty), GenericArgKind::Type(impl_ty)) => {
let simplified_obligation_ty = // Note, we simplify parameters for the obligation but not the
fast_reject::simplify_type(self.tcx(), obligation_ty, true); // impl so that we do not reject a blanket impl but do reject
let simplified_impl_ty = // more concrete impls if we're searching for `T: Trait`.
fast_reject::simplify_type(self.tcx(), impl_ty, false); let simplified_obligation_ty = fast_reject::simplify_type(
self.tcx(),
obligation_ty,
SimplifyParams::Yes,
StripReferences::No,
);
let simplified_impl_ty = fast_reject::simplify_type(
self.tcx(),
impl_ty,
SimplifyParams::No,
StripReferences::No,
);
simplified_obligation_ty.is_some() simplified_obligation_ty.is_some()
&& simplified_impl_ty.is_some() && simplified_impl_ty.is_some()

View file

@ -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}; use rustc_middle::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences};
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};
@ -48,7 +48,12 @@ 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<'tcx>, impl_def_id: DefId) { fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, 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(tcx, trait_ref.self_ty(), false) { if let Some(st) = fast_reject::simplify_type(
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 {
@ -63,7 +68,12 @@ impl ChildrenExt for Children {
fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, 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(tcx, trait_ref.self_ty(), false) { if let Some(st) = fast_reject::simplify_type(
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 {
@ -306,7 +316,12 @@ 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(tcx, trait_ref.self_ty(), false); let simplified = fast_reject::simplify_type(
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 {

View file

@ -10,7 +10,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
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; use rustc_middle::ty::fast_reject::{simplify_type, SimplifyParams, StripReferences};
use rustc_middle::ty::print::with_crate_prefix; use rustc_middle::ty::print::with_crate_prefix;
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rustc_span::lev_distance; use rustc_span::lev_distance;
@ -1703,7 +1703,9 @@ 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) = simplify_type(self.tcx, rcvr_ty, true) { } else if let Some(simp_rcvr_ty) =
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();
for candidate in candidates { for candidate in candidates {
@ -1716,7 +1718,12 @@ 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(self.tcx, imp.self_ty(), true); let imp_simp = simplify_type(
self.tcx,
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)
}) })
{ {

View file

@ -4,7 +4,11 @@ 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`
| |
= 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
|
LL | impl<'a,T:Signed> Defaulted for &'a T { }
| ^^^^^^^^^ ^^^^^
note: required by a bound in `is_defaulted` note: required by a bound in `is_defaulted`
--> $DIR/typeck-default-trait-impl-precedence.rs:12:19 --> $DIR/typeck-default-trait-impl-precedence.rs:12:19
| |

View file

@ -5,7 +5,11 @@ LL | type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator
| |
= help: the trait `Iterator` is not implemented for `&T` = help: the trait `Iterator` is not implemented for `&T`
= note: required because of the requirements on the impl of `IntoIterator` for `&T` note: required because of the requirements on the impl of `IntoIterator` for `&T`
--> $DIR/hir-wf-check-erase-regions.rs:6:29
|
LL | impl<'a, T, const N: usize> IntoIterator for &'a Table<T, N> {
| ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
note: required by a bound in `Flatten` note: required by a bound in `Flatten`
--> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
| |
@ -19,7 +23,11 @@ LL | fn into_iter(self) -> Self::IntoIter {
| ^^^^^^^^^^^^^^ `&T` is not an iterator | ^^^^^^^^^^^^^^ `&T` is not an iterator
| |
= help: the trait `Iterator` is not implemented for `&T` = help: the trait `Iterator` is not implemented for `&T`
= note: required because of the requirements on the impl of `IntoIterator` for `&T` note: required because of the requirements on the impl of `IntoIterator` for `&T`
--> $DIR/hir-wf-check-erase-regions.rs:6:29
|
LL | impl<'a, T, const N: usize> IntoIterator for &'a Table<T, N> {
| ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
note: required by a bound in `Flatten` note: required by a bound in `Flatten`
--> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
| |