diff options
| author | Simon Sapin <simon.sapin@exyr.org> | 2019-01-21 16:55:32 +0100 |
|---|---|---|
| committer | Simon Sapin <simon.sapin@exyr.org> | 2019-01-21 18:41:53 +0100 |
| commit | e195ce654a570606a85ead6cefb36042a206205a (patch) | |
| tree | 80a517b4e0e47f41708b7162d8dae32cc4159aa2 | |
| parent | 9be4c76910e0df7decb33c5d400260f1d8c217a1 (diff) | |
| download | rust-e195ce654a570606a85ead6cefb36042a206205a.tar.gz rust-e195ce654a570606a85ead6cefb36042a206205a.zip | |
Fix some non-determinism in help messages for E0277 errors.
The diagnostic for this error prints `the following implementations were found` followed by the first N relevant impls, sorted. This commit makes the sort happen before slicing, so that the set of impls being printed is deterministic when the input is not.
4 files changed, 11 insertions, 7 deletions
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 367a7eacdfc..1c92e2da588 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -471,7 +471,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } fn report_similar_impl_candidates(&self, - mut impl_candidates: Vec<ty::TraitRef<'tcx>>, + impl_candidates: Vec<ty::TraitRef<'tcx>>, err: &mut DiagnosticBuilder<'_>) { if impl_candidates.is_empty() { @@ -497,14 +497,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }); // Sort impl candidates so that ordering is consistent for UI tests. - let normalized_impl_candidates = &mut impl_candidates[0..end] + let mut normalized_impl_candidates = impl_candidates .iter() .map(normalize) .collect::<Vec<String>>(); + + // Sort before taking the `..end` range, + // because the ordering of `impl_candidates` may not be deterministic: + // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507 normalized_impl_candidates.sort(); err.help(&format!("the following implementations were found:{}{}", - normalized_impl_candidates.join(""), + normalized_impl_candidates[..end].join(""), if len > 5 { format!("\nand {} others", len - 4) } else { diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr index 140f98b4038..d6d5ce4d1a7 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr @@ -8,7 +8,7 @@ LL | f1.foo(1usize); <Bar as Foo<i16>> <Bar as Foo<i32>> <Bar as Foo<i8>> - <Bar as Foo<u8>> + <Bar as Foo<u16>> and 2 others error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index 23466980f92..3411958be62 100644 --- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -40,10 +40,10 @@ LL | Foo::<i32>::bar(&true); //~ ERROR is not satisfied | ^^^^^^^^^^^^^^^ the trait `Foo<i32>` is not implemented for `bool` | = help: the following implementations were found: + <bool as Foo<bool>> + <bool as Foo<i8>> <bool as Foo<u16>> <bool as Foo<u32>> - <bool as Foo<u64>> - <bool as Foo<u8>> and 2 others note: required by `Foo::bar` --> $DIR/issue-39802-show-5-trait-impls.rs:2:5 diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr index c2f9e9b52be..df8e646280c 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -5,10 +5,10 @@ LL | Err("")?; //~ ERROR the trait bound `i32: std::convert::From<&str>` | ^^^^^^^^ the trait `std::convert::From<&str>` is not implemented for `i32` | = help: the following implementations were found: + <i32 as std::convert::From<bool>> <i32 as std::convert::From<core::num::NonZeroI32>> <i32 as std::convert::From<i16>> <i32 as std::convert::From<i8>> - <i32 as std::convert::From<u8>> and 2 others = note: required by `std::convert::From::from` |
