Skip to content

Commit dcd716f

Browse files
committed
extend simplify_type
1 parent 83b32f2 commit dcd716f

File tree

10 files changed

+132
-43
lines changed

10 files changed

+132
-43
lines changed

compiler/rustc_metadata/src/rmeta/encoder.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use rustc_middle::mir::interpret;
2626
use rustc_middle::thir;
2727
use rustc_middle::traits::specialization_graph;
2828
use rustc_middle::ty::codec::TyEncoder;
29+
use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
2930
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
3031
use rustc_serialize::{opaque, Encodable, Encoder};
3132
use rustc_session::config::CrateType;
@@ -2033,15 +2034,19 @@ impl EncodeContext<'a, 'tcx> {
20332034

20342035
struct ImplVisitor<'tcx> {
20352036
tcx: TyCtxt<'tcx>,
2036-
impls: FxHashMap<DefId, Vec<(DefIndex, Option<ty::fast_reject::SimplifiedType>)>>,
2037+
impls: FxHashMap<DefId, Vec<(DefIndex, Option<fast_reject::SimplifiedType>)>>,
20372038
}
20382039

20392040
impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
20402041
fn visit_item(&mut self, item: &hir::Item<'_>) {
20412042
if let hir::ItemKind::Impl { .. } = item.kind {
20422043
if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) {
2043-
let simplified_self_ty =
2044-
ty::fast_reject::simplify_type(self.tcx, trait_ref.self_ty(), false);
2044+
let simplified_self_ty = fast_reject::simplify_type(
2045+
self.tcx,
2046+
trait_ref.self_ty(),
2047+
SimplifyParams::No,
2048+
StripReferences::No,
2049+
);
20452050

20462051
self.impls
20472052
.entry(trait_ref.def_id)

compiler/rustc_middle/src/ty/fast_reject.rs

+38-14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::mir::Mutability;
12
use crate::ty::{self, Ty, TyCtxt};
23
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
34
use rustc_hir::def_id::DefId;
@@ -27,9 +28,12 @@ where
2728
UintSimplifiedType(ty::UintTy),
2829
FloatSimplifiedType(ty::FloatTy),
2930
AdtSimplifiedType(D),
31+
ForeignSimplifiedType(DefId),
3032
StrSimplifiedType,
3133
ArraySimplifiedType,
32-
PtrSimplifiedType,
34+
SliceSimplifiedType,
35+
RefSimplifiedType(Mutability),
36+
PtrSimplifiedType(Mutability),
3337
NeverSimplifiedType,
3438
TupleSimplifiedType(usize),
3539
/// A trait object, all of whose components are markers
@@ -42,7 +46,18 @@ where
4246
OpaqueSimplifiedType(D),
4347
FunctionSimplifiedType(usize),
4448
ParameterSimplifiedType,
45-
ForeignSimplifiedType(DefId),
49+
}
50+
51+
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
52+
pub enum SimplifyParams {
53+
Yes,
54+
No,
55+
}
56+
57+
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
58+
pub enum StripReferences {
59+
Yes,
60+
No,
4661
}
4762

4863
/// Tries to simplify a type by dropping type parameters, deref'ing away any reference types, etc.
@@ -57,7 +72,8 @@ where
5772
pub fn simplify_type(
5873
tcx: TyCtxt<'_>,
5974
ty: Ty<'_>,
60-
can_simplify_params: bool,
75+
can_simplify_params: SimplifyParams,
76+
strip_references: StripReferences,
6177
) -> Option<SimplifiedType> {
6278
match *ty.kind() {
6379
ty::Bool => Some(BoolSimplifiedType),
@@ -67,19 +83,24 @@ pub fn simplify_type(
6783
ty::Float(float_type) => Some(FloatSimplifiedType(float_type)),
6884
ty::Adt(def, _) => Some(AdtSimplifiedType(def.did)),
6985
ty::Str => Some(StrSimplifiedType),
70-
ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType),
71-
ty::RawPtr(_) => Some(PtrSimplifiedType),
86+
ty::Array(..) => Some(ArraySimplifiedType),
87+
ty::Slice(..) => Some(SliceSimplifiedType),
88+
ty::RawPtr(ptr) => Some(PtrSimplifiedType(ptr.mutbl)),
7289
ty::Dynamic(ref trait_info, ..) => match trait_info.principal_def_id() {
7390
Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => {
7491
Some(TraitSimplifiedType(principal_def_id))
7592
}
7693
_ => Some(MarkerTraitObjectSimplifiedType),
7794
},
78-
ty::Ref(_, ty, _) => {
79-
// since we introduce auto-refs during method lookup, we
80-
// just treat &T and T as equivalent from the point of
81-
// view of possibly unifying
82-
simplify_type(tcx, ty, can_simplify_params)
95+
ty::Ref(_, ty, mutbl) => {
96+
if strip_references == StripReferences::Yes {
97+
// For diagnostics, when recommending similar impls we want to
98+
// recommend impls even when there is a reference mismatch,
99+
// so we treat &T and T equivalently in that case.
100+
simplify_type(tcx, ty, can_simplify_params, strip_references)
101+
} else {
102+
Some(RefSimplifiedType(mutbl))
103+
}
83104
}
84105
ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)),
85106
ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)),
@@ -90,7 +111,7 @@ pub fn simplify_type(
90111
ty::Tuple(ref tys) => Some(TupleSimplifiedType(tys.len())),
91112
ty::FnPtr(ref f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())),
92113
ty::Projection(_) | ty::Param(_) => {
93-
if can_simplify_params {
114+
if can_simplify_params == SimplifyParams::Yes {
94115
// In normalized types, projections don't unify with
95116
// anything. when lazy normalization happens, this
96117
// will change. It would still be nice to have a way
@@ -120,9 +141,12 @@ impl<D: Copy + Debug + Ord + Eq> SimplifiedTypeGen<D> {
120141
UintSimplifiedType(t) => UintSimplifiedType(t),
121142
FloatSimplifiedType(t) => FloatSimplifiedType(t),
122143
AdtSimplifiedType(d) => AdtSimplifiedType(map(d)),
144+
ForeignSimplifiedType(d) => ForeignSimplifiedType(d),
123145
StrSimplifiedType => StrSimplifiedType,
124146
ArraySimplifiedType => ArraySimplifiedType,
125-
PtrSimplifiedType => PtrSimplifiedType,
147+
SliceSimplifiedType => SliceSimplifiedType,
148+
RefSimplifiedType(m) => RefSimplifiedType(m),
149+
PtrSimplifiedType(m) => PtrSimplifiedType(m),
126150
NeverSimplifiedType => NeverSimplifiedType,
127151
MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType,
128152
TupleSimplifiedType(n) => TupleSimplifiedType(n),
@@ -133,7 +157,6 @@ impl<D: Copy + Debug + Ord + Eq> SimplifiedTypeGen<D> {
133157
OpaqueSimplifiedType(d) => OpaqueSimplifiedType(map(d)),
134158
FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
135159
ParameterSimplifiedType => ParameterSimplifiedType,
136-
ForeignSimplifiedType(d) => ForeignSimplifiedType(d),
137160
}
138161
}
139162
}
@@ -149,12 +172,13 @@ where
149172
| CharSimplifiedType
150173
| StrSimplifiedType
151174
| ArraySimplifiedType
152-
| PtrSimplifiedType
175+
| SliceSimplifiedType
153176
| NeverSimplifiedType
154177
| ParameterSimplifiedType
155178
| MarkerTraitObjectSimplifiedType => {
156179
// nothing to do
157180
}
181+
RefSimplifiedType(m) | PtrSimplifiedType(m) => m.hash_stable(hcx, hasher),
158182
IntSimplifiedType(t) => t.hash_stable(hcx, hasher),
159183
UintSimplifiedType(t) => t.hash_stable(hcx, hasher),
160184
FloatSimplifiedType(t) => t.hash_stable(hcx, hasher),

compiler/rustc_middle/src/ty/trait_def.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::traits::specialization_graph;
2-
use crate::ty::fast_reject;
2+
use crate::ty::fast_reject::{self, SimplifyParams, StripReferences};
33
use crate::ty::fold::TypeFoldable;
44
use crate::ty::{Ty, TyCtxt};
55
use rustc_hir as hir;
@@ -179,7 +179,9 @@ impl<'tcx> TyCtxt<'tcx> {
179179
// blanket and non-blanket impls, and compare them separately.
180180
//
181181
// I think we'll cross that bridge when we get to it.
182-
if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) {
182+
if let Some(simp) =
183+
fast_reject::simplify_type(self, self_ty, SimplifyParams::Yes, StripReferences::No)
184+
{
183185
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
184186
for &impl_def_id in impls {
185187
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
238240
continue;
239241
}
240242

241-
if let Some(simplified_self_ty) = fast_reject::simplify_type(tcx, impl_self_ty, false) {
243+
if let Some(simplified_self_ty) =
244+
fast_reject::simplify_type(tcx, impl_self_ty, SimplifyParams::No, StripReferences::No)
245+
{
242246
impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id);
243247
} else {
244248
impls.blanket_impls.push(impl_def_id);

compiler/rustc_trait_selection/src/traits/coherence.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ use crate::traits::{
1212
self, Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext,
1313
};
1414
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
15+
use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
1516
use rustc_middle::ty::fold::TypeFoldable;
1617
use rustc_middle::ty::subst::Subst;
17-
use rustc_middle::ty::{self, fast_reject, Ty, TyCtxt};
18+
use rustc_middle::ty::{self, Ty, TyCtxt};
1819
use rustc_span::symbol::sym;
1920
use rustc_span::DUMMY_SP;
2021
use std::iter;
@@ -82,12 +83,11 @@ where
8283
impl2_ref.iter().flat_map(|tref| tref.substs.types()),
8384
)
8485
.any(|(ty1, ty2)| {
85-
let t1 = fast_reject::simplify_type(tcx, ty1, false);
86-
let t2 = fast_reject::simplify_type(tcx, ty2, false);
86+
let t1 = fast_reject::simplify_type(tcx, ty1, SimplifyParams::No, StripReferences::No);
87+
let t2 = fast_reject::simplify_type(tcx, ty2, SimplifyParams::No, StripReferences::No);
8788
if let (Some(t1), Some(t2)) = (t1, t2) {
8889
// Simplified successfully
89-
// Types cannot unify if they differ in their reference mutability or simplify to different types
90-
t1 != t2 || ty1.ref_mutability() != ty2.ref_mutability()
90+
t1 != t2
9191
} else {
9292
// Types might unify
9393
false

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ use rustc_hir::Item;
2121
use rustc_hir::Node;
2222
use rustc_middle::thir::abstract_const::NotConstEvaluatable;
2323
use rustc_middle::ty::error::ExpectedFound;
24+
use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
2425
use rustc_middle::ty::fold::TypeFolder;
2526
use rustc_middle::ty::{
26-
self, fast_reject, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt,
27+
self, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt,
2728
TypeFoldable,
2829
};
2930
use rustc_session::DiagnosticMessageId;
@@ -1439,14 +1440,24 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
14391440
&self,
14401441
trait_ref: ty::PolyTraitRef<'tcx>,
14411442
) -> Vec<ty::TraitRef<'tcx>> {
1442-
let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true);
1443+
let simp = fast_reject::simplify_type(
1444+
self.tcx,
1445+
trait_ref.skip_binder().self_ty(),
1446+
SimplifyParams::Yes,
1447+
StripReferences::Yes,
1448+
);
14431449
let all_impls = self.tcx.all_impls(trait_ref.def_id());
14441450

14451451
match simp {
14461452
Some(simp) => all_impls
14471453
.filter_map(|def_id| {
14481454
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
1449-
let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
1455+
let imp_simp = fast_reject::simplify_type(
1456+
self.tcx,
1457+
imp.self_ty(),
1458+
SimplifyParams::Yes,
1459+
StripReferences::Yes,
1460+
);
14501461
if let Some(imp_simp) = imp_simp {
14511462
if simp != imp_simp {
14521463
return None;

compiler/rustc_trait_selection/src/traits/select/mod.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use rustc_infer::infer::LateBoundRegionConversionTime;
3535
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
3636
use rustc_middle::mir::interpret::ErrorHandled;
3737
use rustc_middle::thir::abstract_const::NotConstEvaluatable;
38-
use rustc_middle::ty::fast_reject;
38+
use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
3939
use rustc_middle::ty::print::with_no_trimmed_paths;
4040
use rustc_middle::ty::relate::TypeRelation;
4141
use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef};
@@ -2089,10 +2089,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20892089
|(obligation_arg, impl_arg)| {
20902090
match (obligation_arg.unpack(), impl_arg.unpack()) {
20912091
(GenericArgKind::Type(obligation_ty), GenericArgKind::Type(impl_ty)) => {
2092-
let simplified_obligation_ty =
2093-
fast_reject::simplify_type(self.tcx(), obligation_ty, true);
2094-
let simplified_impl_ty =
2095-
fast_reject::simplify_type(self.tcx(), impl_ty, false);
2092+
// Note, we simplify parameters for the obligation but not the
2093+
// impl so that we do not reject a blanket impl but do reject
2094+
// more concrete impls if we're searching for `T: Trait`.
2095+
let simplified_obligation_ty = fast_reject::simplify_type(
2096+
self.tcx(),
2097+
obligation_ty,
2098+
SimplifyParams::Yes,
2099+
StripReferences::No,
2100+
);
2101+
let simplified_impl_ty = fast_reject::simplify_type(
2102+
self.tcx(),
2103+
impl_ty,
2104+
SimplifyParams::No,
2105+
StripReferences::No,
2106+
);
20962107

20972108
simplified_obligation_ty.is_some()
20982109
&& simplified_impl_ty.is_some()

compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::OverlapError;
22

33
use crate::traits;
44
use rustc_hir::def_id::DefId;
5-
use rustc_middle::ty::fast_reject::{self, SimplifiedType};
5+
use rustc_middle::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences};
66
use rustc_middle::ty::print::with_no_trimmed_paths;
77
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
88

@@ -48,7 +48,12 @@ impl ChildrenExt for Children {
4848
/// Insert an impl into this set of children without comparing to any existing impls.
4949
fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
5050
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
51-
if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) {
51+
if let Some(st) = fast_reject::simplify_type(
52+
tcx,
53+
trait_ref.self_ty(),
54+
SimplifyParams::No,
55+
StripReferences::No,
56+
) {
5257
debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st);
5358
self.non_blanket_impls.entry(st).or_default().push(impl_def_id)
5459
} else {
@@ -63,7 +68,12 @@ impl ChildrenExt for Children {
6368
fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
6469
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
6570
let vec: &mut Vec<DefId>;
66-
if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) {
71+
if let Some(st) = fast_reject::simplify_type(
72+
tcx,
73+
trait_ref.self_ty(),
74+
SimplifyParams::No,
75+
StripReferences::No,
76+
) {
6777
debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st);
6878
vec = self.non_blanket_impls.get_mut(&st).unwrap();
6979
} else {
@@ -306,7 +316,12 @@ impl GraphExt for Graph {
306316

307317
let mut parent = trait_def_id;
308318
let mut last_lint = None;
309-
let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false);
319+
let simplified = fast_reject::simplify_type(
320+
tcx,
321+
trait_ref.self_ty(),
322+
SimplifyParams::No,
323+
StripReferences::No,
324+
);
310325

311326
// Descend the specialization tree, where `parent` is the current parent node.
312327
loop {

compiler/rustc_typeck/src/check/method/suggest.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
1010
use rustc_hir::lang_items::LangItem;
1111
use rustc_hir::{ExprKind, Node, QPath};
1212
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
13-
use rustc_middle::ty::fast_reject::simplify_type;
13+
use rustc_middle::ty::fast_reject::{simplify_type, SimplifyParams, StripReferences};
1414
use rustc_middle::ty::print::with_crate_prefix;
1515
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
1616
use rustc_span::lev_distance;
@@ -1703,7 +1703,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17031703
// FIXME: Even though negative bounds are not implemented, we could maybe handle
17041704
// cases where a positive bound implies a negative impl.
17051705
(candidates, Vec::new())
1706-
} else if let Some(simp_rcvr_ty) = simplify_type(self.tcx, rcvr_ty, true) {
1706+
} else if let Some(simp_rcvr_ty) =
1707+
simplify_type(self.tcx, rcvr_ty, SimplifyParams::Yes, StripReferences::No)
1708+
{
17071709
let mut potential_candidates = Vec::new();
17081710
let mut explicitly_negative = Vec::new();
17091711
for candidate in candidates {
@@ -1716,7 +1718,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17161718
})
17171719
.any(|imp_did| {
17181720
let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
1719-
let imp_simp = simplify_type(self.tcx, imp.self_ty(), true);
1721+
let imp_simp = simplify_type(
1722+
self.tcx,
1723+
imp.self_ty(),
1724+
SimplifyParams::Yes,
1725+
StripReferences::No,
1726+
);
17201727
imp_simp.map_or(false, |s| s == simp_rcvr_ty)
17211728
})
17221729
{

src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ error[E0277]: the trait bound `u32: Signed` is not satisfied
44
LL | is_defaulted::<&'static u32>();
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`
66
|
7-
= note: required because of the requirements on the impl of `Defaulted` for `&'static u32`
7+
note: required because of the requirements on the impl of `Defaulted` for `&'static u32`
8+
--> $DIR/typeck-default-trait-impl-precedence.rs:10:19
9+
|
10+
LL | impl<'a,T:Signed> Defaulted for &'a T { }
11+
| ^^^^^^^^^ ^^^^^
812
note: required by a bound in `is_defaulted`
913
--> $DIR/typeck-default-trait-impl-precedence.rs:12:19
1014
|

0 commit comments

Comments
 (0)