Skip to content

Commit e6c0ff6

Browse files
Create Weight enum
Add more comments for the global understanding
1 parent 61e6169 commit e6c0ff6

File tree

1 file changed

+64
-34
lines changed

1 file changed

+64
-34
lines changed

src/librustc/traits/error_reporting.rs

+64-34
Original file line numberDiff line numberDiff line change
@@ -82,54 +82,76 @@ fn impl_substs<'a, 'tcx>(fcx: &InferCtxt<'a, 'tcx>,
8282
substs
8383
}
8484

85+
// Enum used to differentiate the "big" and "little" weights.
86+
enum Weight {
87+
Coarse,
88+
Precise,
89+
}
90+
8591
trait AssociatedWeight {
86-
fn get_weight(&self) -> usize;
92+
fn get_weight(&self) -> (u32, u32);
8793
}
8894

8995
impl<'a> AssociatedWeight for TypeVariants<'a> {
90-
// First number is for "global" weight and second number is for bigger precision
91-
fn get_weight(&self) -> usize {
96+
// Left number is for "global"/"big" weight and right number is for better precision.
97+
fn get_weight(&self) -> (u32, u32) {
9298
match *self {
93-
TypeVariants::TyBool => 11,
94-
TypeVariants::TyChar => 12,
95-
TypeVariants::TyStr => 13,
96-
TypeVariants::TyInt(_) => 21,
97-
TypeVariants::TyUint(_) => 22,
98-
TypeVariants::TyFloat(_) => 23,
99-
TypeVariants::TyRawPtr(_) => 24,
100-
TypeVariants::TyEnum(_, _) => 31,
101-
TypeVariants::TyStruct(_, _) => 32,
102-
TypeVariants::TyBox(_) => 33,
103-
TypeVariants::TyTuple(_) => 34,
104-
TypeVariants::TyArray(_, _) => 41,
105-
TypeVariants::TySlice(_) => 42,
106-
TypeVariants::TyRef(_, _) => 51,
107-
TypeVariants::TyFnDef(_, _, _) => 52,
108-
TypeVariants::TyFnPtr(_) => 53,
109-
TypeVariants::TyTrait(_) => 61,
110-
TypeVariants::TyClosure(_, _) => 71,
111-
TypeVariants::TyProjection(_) => 81,
112-
TypeVariants::TyParam(_) => 82,
113-
TypeVariants::TyInfer(_) => 83,
114-
TypeVariants::TyError => 91,
99+
TypeVariants::TyBool => (1, 1),
100+
TypeVariants::TyChar => (1, 2),
101+
TypeVariants::TyStr => (1, 3),
102+
103+
TypeVariants::TyInt(_) => (2, 1),
104+
TypeVariants::TyUint(_) => (2, 2),
105+
TypeVariants::TyFloat(_) => (2, 3),
106+
TypeVariants::TyRawPtr(_) => (2, 4),
107+
108+
TypeVariants::TyEnum(_, _) => (3, 1),
109+
TypeVariants::TyStruct(_, _) => (3, 2),
110+
TypeVariants::TyBox(_) => (3, 3),
111+
TypeVariants::TyTuple(_) => (3, 4),
112+
113+
TypeVariants::TyArray(_, _) => (4, 1),
114+
TypeVariants::TySlice(_) => (4, 2),
115+
116+
TypeVariants::TyRef(_, _) => (5, 1),
117+
TypeVariants::TyFnDef(_, _, _) => (5, 2),
118+
TypeVariants::TyFnPtr(_) => (5, 3),
119+
120+
TypeVariants::TyTrait(_) => (6, 1),
121+
122+
TypeVariants::TyClosure(_, _) => (7, 1),
123+
124+
TypeVariants::TyProjection(_) => (8, 1),
125+
TypeVariants::TyParam(_) => (8, 2),
126+
TypeVariants::TyInfer(_) => (8, 3),
127+
128+
TypeVariants::TyError => (9, 1),
115129
}
116130
}
117131
}
118132

119-
// The "closer" the types are, the lesser the weight
120-
fn get_weight_diff(a: &ty::TypeVariants, b: &TypeVariants, big_weight: bool) -> usize {
121-
let w1 = if big_weight { a.get_weight() / 10 } else { a.get_weight() % 10 };
122-
let w2 = if big_weight { b.get_weight() / 10 } else { b.get_weight() % 10 };
123-
133+
// The "closer" the types are, the lesser the weight.
134+
fn get_weight_diff(a: &ty::TypeVariants, b: &TypeVariants, weight: Weight) -> u32 {
135+
let (w1, w2) = match weight {
136+
Weight::Coarse => (a.get_weight().0, b.get_weight().0),
137+
Weight::Precise => (a.get_weight().1, b.get_weight().1),
138+
};
124139
if w1 < w2 {
125140
w2 - w1
126141
} else {
127142
w1 - w2
128143
}
129144
}
130145

131-
// Once we have "globally matching" types, we need to run another filter on them
132-
fn filter_matching_types<'tcx>(weights: &[(usize, usize)],
146+
// Once we have "globally matching" types, we need to run another filter on them.
147+
//
148+
// In the function `get_best_matching_type`, we got the types which might fit the
149+
// most to the type we're looking for. This second filter now intends to get (if
150+
// possible) the type which fits the most.
151+
//
152+
// For example, the trait expects an `usize` and here you have `u32` and `i32`.
153+
// Obviously, the "correct" one is `u32`.
154+
fn filter_matching_types<'tcx>(weights: &[(usize, u32)],
133155
imps: &[(DefId, subst::Substs<'tcx>)],
134156
trait_types: &[ty::Ty<'tcx>])
135157
-> usize {
@@ -144,14 +166,22 @@ fn filter_matching_types<'tcx>(weights: &[(usize, usize)],
144166
.get_slice(ParamSpace::TypeSpace)
145167
.iter()
146168
.zip(trait_types.iter()) {
147-
weight += get_weight_diff(&type_to_compare.sty, &original_type.sty, false);
169+
weight += get_weight_diff(&type_to_compare.sty, &original_type.sty, Weight::Precise);
148170
}
149171
filtered_weights.push((pos, weight));
150172
}
151173
filtered_weights.sort_by(|a, b| a.1.cmp(&b.1));
152174
filtered_weights[0].0
153175
}
154176

177+
// Here, we run the "big" filter. Little example:
178+
//
179+
// We receive a `String`, an `u32` and an `i32`.
180+
// The trait expected an `usize`.
181+
// From human point of view, it's easy to determine that `String` doesn't correspond to
182+
// the expected type at all whereas `u32` and `i32` could.
183+
//
184+
// This first filter intends to only keep the types which match the most.
155185
fn get_best_matching_type<'tcx>(imps: &[(DefId, subst::Substs<'tcx>)],
156186
trait_types: &[ty::Ty<'tcx>]) -> usize {
157187
let mut weights = vec!();
@@ -162,7 +192,7 @@ fn get_best_matching_type<'tcx>(imps: &[(DefId, subst::Substs<'tcx>)],
162192
.get_slice(ParamSpace::TypeSpace)
163193
.iter()
164194
.zip(trait_types.iter()) {
165-
weight += get_weight_diff(&type_to_compare.sty, &original_type.sty, true);
195+
weight += get_weight_diff(&type_to_compare.sty, &original_type.sty, Weight::Coarse);
166196
}
167197
weights.push((pos, weight));
168198
}

0 commit comments

Comments
 (0)