|
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