|
9 | 9 | // except according to those terms. |
10 | 10 |
|
11 | 11 | use rustc::ty::TypeFoldable; |
| 12 | +use std::fmt::Debug; |
12 | 13 |
|
13 | 14 | use super::*; |
14 | 15 |
|
@@ -1081,18 +1082,25 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { |
1081 | 1082 | return None; |
1082 | 1083 | } |
1083 | 1084 |
|
| 1085 | + let mut bounds_vec = bounds.into_iter().collect(); |
| 1086 | + self.sort_where_bounds(&mut bounds_vec); |
| 1087 | + |
1084 | 1088 | Some(WherePredicate::BoundPredicate { |
1085 | 1089 | ty, |
1086 | | - bounds: bounds.into_iter().collect(), |
| 1090 | + bounds: bounds_vec, |
1087 | 1091 | }) |
1088 | 1092 | }) |
1089 | 1093 | .chain( |
1090 | 1094 | lifetime_to_bounds |
1091 | 1095 | .into_iter() |
1092 | 1096 | .filter(|&(_, ref bounds)| !bounds.is_empty()) |
1093 | | - .map(|(lifetime, bounds)| WherePredicate::RegionPredicate { |
1094 | | - lifetime, |
1095 | | - bounds: bounds.into_iter().collect(), |
| 1097 | + .map(|(lifetime, bounds)| { |
| 1098 | + let mut bounds_vec = bounds.into_iter().collect(); |
| 1099 | + self.sort_where_lifetimes(&mut bounds_vec); |
| 1100 | + WherePredicate::RegionPredicate { |
| 1101 | + lifetime, |
| 1102 | + bounds: bounds_vec, |
| 1103 | + } |
1096 | 1104 | }), |
1097 | 1105 | ) |
1098 | 1106 | .collect() |
@@ -1372,40 +1380,64 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { |
1372 | 1380 | // a given set of predicates always appears in the same order - |
1373 | 1381 | // both for visual consistency between 'rustdoc' runs, and to |
1374 | 1382 | // make writing tests much easier |
1375 | | - fn sort_where_predicates(&self, predicates: &mut Vec<WherePredicate>) { |
| 1383 | + #[inline] |
| 1384 | + fn sort_where_predicates(&self, mut predicates: &mut Vec<WherePredicate>) { |
1376 | 1385 | // We should never have identical bounds - and if we do, |
1377 | 1386 | // they're visually identical as well. Therefore, using |
1378 | 1387 | // an unstable sort is fine. |
1379 | | - predicates.sort_unstable_by(|first, second| { |
1380 | | - // This might look horrendously hacky, but it's actually not that bad. |
1381 | | - // |
1382 | | - // For performance reasons, we use several different FxHashMaps |
1383 | | - // in the process of computing the final set of where predicates. |
1384 | | - // However, the iteration order of a HashMap is completely unspecified. |
1385 | | - // In fact, the iteration of an FxHashMap can even vary between platforms, |
1386 | | - // since FxHasher has different behavior for 32-bit and 64-bit platforms. |
1387 | | - // |
1388 | | - // Obviously, it's extremely undesireable for documentation rendering |
1389 | | - // to be depndent on the platform it's run on. Apart from being confusing |
1390 | | - // to end users, it makes writing tests much more difficult, as predicates |
1391 | | - // can appear in any order in the final result. |
1392 | | - // |
1393 | | - // To solve this problem, we sort WherePredicates by their Debug |
1394 | | - // string. The thing to keep in mind is that we don't really |
1395 | | - // care what the final order is - we're synthesizing an impl |
1396 | | - // ourselves, so any order can be considered equally valid. |
1397 | | - // By sorting the predicates, however, we ensure that for |
1398 | | - // a given codebase, all auto-trait impls always render |
1399 | | - // in exactly the same way. |
1400 | | - // |
1401 | | - // Using the Debug impementation for sorting prevents |
1402 | | - // us from needing to write quite a bit of almost |
1403 | | - // entirely useless code (e.g. how should two |
1404 | | - // Types be sorted relative to each other). |
1405 | | - // This approach is probably somewhat slower, but |
1406 | | - // the small number of items involved (impls |
1407 | | - // rarely have more than a few bounds) means |
1408 | | - // that it shouldn't matter in practice. |
| 1388 | + self.unstable_debug_sort(&mut predicates); |
| 1389 | + } |
| 1390 | + |
| 1391 | + // Ensure that the bounds are in a consistent order. The precise |
| 1392 | + // ordering doesn't actually matter, but it's important that |
| 1393 | + // a given set of bounds always appears in the same order - |
| 1394 | + // both for visual consistency between 'rustdoc' runs, and to |
| 1395 | + // make writing tests much easier |
| 1396 | + #[inline] |
| 1397 | + fn sort_where_bounds(&self, mut bounds: &mut Vec<TyParamBound>) { |
| 1398 | + // We should never have identical bounds - and if we do, |
| 1399 | + // they're visually identical as well. Therefore, using |
| 1400 | + // an unstable sort is fine. |
| 1401 | + self.unstable_debug_sort(&mut bounds); |
| 1402 | + } |
| 1403 | + |
| 1404 | + #[inline] |
| 1405 | + fn sort_where_lifetimes(&self, mut bounds: &mut Vec<Lifetime>) { |
| 1406 | + // We should never have identical bounds - and if we do, |
| 1407 | + // they're visually identical as well. Therefore, using |
| 1408 | + // an unstable sort is fine. |
| 1409 | + self.unstable_debug_sort(&mut bounds); |
| 1410 | + } |
| 1411 | + |
| 1412 | + // This might look horrendously hacky, but it's actually not that bad. |
| 1413 | + // |
| 1414 | + // For performance reasons, we use several different FxHashMaps |
| 1415 | + // in the process of computing the final set of where predicates. |
| 1416 | + // However, the iteration order of a HashMap is completely unspecified. |
| 1417 | + // In fact, the iteration of an FxHashMap can even vary between platforms, |
| 1418 | + // since FxHasher has different behavior for 32-bit and 64-bit platforms. |
| 1419 | + // |
| 1420 | + // Obviously, it's extremely undesireable for documentation rendering |
| 1421 | + // to be depndent on the platform it's run on. Apart from being confusing |
| 1422 | + // to end users, it makes writing tests much more difficult, as predicates |
| 1423 | + // can appear in any order in the final result. |
| 1424 | + // |
| 1425 | + // To solve this problem, we sort WherePredicates and TyParamBounds |
| 1426 | + // by their Debug string. The thing to keep in mind is that we don't really |
| 1427 | + // care what the final order is - we're synthesizing an impl or bound |
| 1428 | + // ourselves, so any order can be considered equally valid. By sorting the |
| 1429 | + // predicates and bounds, however, we ensure that for a given codebase, all |
| 1430 | + // auto-trait impls always render in exactly the same way. |
| 1431 | + // |
| 1432 | + // Using the Debug impementation for sorting prevents us from needing to |
| 1433 | + // write quite a bit of almost entirely useless code (e.g. how should two |
| 1434 | + // Types be sorted relative to each other). It also allows us to solve the |
| 1435 | + // problem for both WherePredicates and TyParamBounds at the same time. This |
| 1436 | + // approach is probably somewhat slower, but the small number of items |
| 1437 | + // involved (impls rarely have more than a few bounds) means that it |
| 1438 | + // shouldn't matter in practice. |
| 1439 | + fn unstable_debug_sort<T: Debug>(&self, vec: &mut Vec<T>) { |
| 1440 | + vec.sort_unstable_by(|first, second| { |
1409 | 1441 | format!("{:?}", first).cmp(&format!("{:?}", second)) |
1410 | 1442 | }); |
1411 | 1443 | } |
|
0 commit comments