Skip to content

Commit 91b9ffe

Browse files
committed
Reorder fullfillment errors to keep more interesting ones first
In `report_fullfillment_errors` push back `T: Sized`, `T: WellFormed` and coercion errors to the end of the list. The pre-existing deduplication logic eliminates redundant errors better that way, keeping the resulting output with fewer errors than before, while also having more detail.
1 parent 2817ece commit 91b9ffe

File tree

76 files changed

+309
-403
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+309
-403
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ fn check_opaque_type_well_formed<'tcx>(
368368
if errors.is_empty() {
369369
Ok(definition_ty)
370370
} else {
371-
Err(infcx.err_ctxt().report_fulfillment_errors(&errors))
371+
Err(infcx.err_ctxt().report_fulfillment_errors(errors))
372372
}
373373
}
374374

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
743743

744744
let errors = ocx.select_all_or_error();
745745
if !errors.is_empty() {
746-
infcx.err_ctxt().report_fulfillment_errors(&errors);
746+
infcx.err_ctxt().report_fulfillment_errors(errors);
747747
}
748748

749749
// Attempting to call a trait method?

compiler/rustc_hir_analysis/src/check/check.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ fn check_opaque_meets_bounds<'tcx>(
327327
// version.
328328
let errors = ocx.select_all_or_error();
329329
if !errors.is_empty() {
330-
let guar = infcx.err_ctxt().report_fulfillment_errors(&errors);
330+
let guar = infcx.err_ctxt().report_fulfillment_errors(errors);
331331
return Err(guar);
332332
}
333333
match origin {
@@ -1512,6 +1512,6 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
15121512
let errors = fulfillment_cx.select_all_or_error(&infcx);
15131513
debug!(?errors);
15141514
if !errors.is_empty() {
1515-
infcx.err_ctxt().report_fulfillment_errors(&errors);
1515+
infcx.err_ctxt().report_fulfillment_errors(errors);
15161516
}
15171517
}

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ fn compare_method_predicate_entailment<'tcx>(
323323
// FIXME(-Ztrait-solver=next): Not needed when the hack below is removed.
324324
let errors = ocx.select_where_possible();
325325
if !errors.is_empty() {
326-
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
326+
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
327327
return Err(reported);
328328
}
329329

@@ -394,7 +394,7 @@ fn compare_method_predicate_entailment<'tcx>(
394394
});
395395
}
396396
CheckImpliedWfMode::Skip => {
397-
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
397+
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
398398
return Err(reported);
399399
}
400400
}
@@ -874,7 +874,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
874874
// RPITs.
875875
let errors = ocx.select_all_or_error();
876876
if !errors.is_empty() {
877-
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
877+
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
878878
return Err(reported);
879879
}
880880

@@ -2050,7 +2050,7 @@ fn compare_const_predicate_entailment<'tcx>(
20502050
// version.
20512051
let errors = ocx.select_all_or_error();
20522052
if !errors.is_empty() {
2053-
return Err(infcx.err_ctxt().report_fulfillment_errors(&errors));
2053+
return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
20542054
}
20552055

20562056
let outlives_env = OutlivesEnvironment::new(param_env);
@@ -2143,7 +2143,7 @@ fn compare_type_predicate_entailment<'tcx>(
21432143
// version.
21442144
let errors = ocx.select_all_or_error();
21452145
if !errors.is_empty() {
2146-
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
2146+
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
21472147
return Err(reported);
21482148
}
21492149

@@ -2358,7 +2358,7 @@ pub(super) fn check_type_bounds<'tcx>(
23582358
// version.
23592359
let errors = ocx.select_all_or_error();
23602360
if !errors.is_empty() {
2361-
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
2361+
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
23622362
return Err(reported);
23632363
}
23642364

compiler/rustc_hir_analysis/src/check/entry.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
158158
ocx.register_bound(cause, param_env, norm_return_ty, term_did);
159159
let errors = ocx.select_all_or_error();
160160
if !errors.is_empty() {
161-
infcx.err_ctxt().report_fulfillment_errors(&errors);
161+
infcx.err_ctxt().report_fulfillment_errors(errors);
162162
error = true;
163163
}
164164
// now we can take the return type of the given main function

compiler/rustc_hir_analysis/src/check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ pub fn check_function_signature<'tcx>(
588588
Ok(()) => {
589589
let errors = ocx.select_all_or_error();
590590
if !errors.is_empty() {
591-
infcx.err_ctxt().report_fulfillment_errors(&errors);
591+
infcx.err_ctxt().report_fulfillment_errors(errors);
592592
return;
593593
}
594594
}

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
116116

117117
let errors = wfcx.select_all_or_error();
118118
if !errors.is_empty() {
119-
infcx.err_ctxt().report_fulfillment_errors(&errors);
119+
infcx.err_ctxt().report_fulfillment_errors(errors);
120120
return;
121121
}
122122

compiler/rustc_hir_analysis/src/coherence/builtin.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
261261
}
262262
let errors = ocx.select_all_or_error();
263263
if !errors.is_empty() {
264-
infcx.err_ctxt().report_fulfillment_errors(&errors);
264+
infcx.err_ctxt().report_fulfillment_errors(errors);
265265
}
266266

267267
// Finally, resolve all regions.
@@ -470,7 +470,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
470470
ocx.register_obligation(obligation);
471471
let errors = ocx.select_all_or_error();
472472
if !errors.is_empty() {
473-
infcx.err_ctxt().report_fulfillment_errors(&errors);
473+
infcx.err_ctxt().report_fulfillment_errors(errors);
474474
}
475475

476476
// Finally, resolve all regions.

compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ fn get_impl_args(
196196

197197
let errors = ocx.select_all_or_error();
198198
if !errors.is_empty() {
199-
let guar = ocx.infcx.err_ctxt().report_fulfillment_errors(&errors);
199+
let guar = ocx.infcx.err_ctxt().report_fulfillment_errors(errors);
200200
return Err(guar);
201201
}
202202

compiler/rustc_hir_typeck/src/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3010,7 +3010,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30103010
// There should be at least one error reported. If not, we
30113011
// will still delay a span bug in `report_fulfillment_errors`.
30123012
Ok::<_, NoSolution>((
3013-
self.err_ctxt().report_fulfillment_errors(&errors),
3013+
self.err_ctxt().report_fulfillment_errors(errors),
30143014
impl_trait_ref.args.type_at(1),
30153015
element_ty,
30163016
))

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
564564

565565
if !errors.is_empty() {
566566
self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);
567-
self.err_ctxt().report_fulfillment_errors(&errors);
567+
self.err_ctxt().report_fulfillment_errors(errors);
568568
}
569569
}
570570

@@ -577,7 +577,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
577577
if !result.is_empty() {
578578
mutate_fulfillment_errors(&mut result);
579579
self.adjust_fulfillment_errors_for_expr_obligation(&mut result);
580-
self.err_ctxt().report_fulfillment_errors(&result);
580+
self.err_ctxt().report_fulfillment_errors(result);
581581
}
582582
}
583583

@@ -1477,7 +1477,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14771477
{
14781478
Ok(normalized_ty) => normalized_ty,
14791479
Err(errors) => {
1480-
let guar = self.err_ctxt().report_fulfillment_errors(&errors);
1480+
let guar = self.err_ctxt().report_fulfillment_errors(errors);
14811481
return Ty::new_error(self.tcx,guar);
14821482
}
14831483
}

compiler/rustc_passes/src/check_attr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2373,7 +2373,7 @@ impl CheckAttrVisitor<'_> {
23732373

23742374
let errors = ocx.select_all_or_error();
23752375
if !errors.is_empty() {
2376-
infcx.err_ctxt().report_fulfillment_errors(&errors);
2376+
infcx.err_ctxt().report_fulfillment_errors(errors);
23772377
self.abort.set(true);
23782378
}
23792379
}

compiler/rustc_passes/src/layout_test.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ pub fn ensure_wf<'tcx>(
5757
ocx.register_obligation(obligation);
5858
let errors = ocx.select_all_or_error();
5959
if !errors.is_empty() {
60-
infcx.err_ctxt().report_fulfillment_errors(&errors);
60+
infcx.err_ctxt().report_fulfillment_errors(errors);
6161
false
6262
} else {
6363
// looks WF!

compiler/rustc_trait_selection/src/traits/engine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
218218
def_id: LocalDefId,
219219
) -> Result<FxIndexSet<Ty<'tcx>>, ErrorGuaranteed> {
220220
self.assumed_wf_types(param_env, def_id)
221-
.map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(&errors))
221+
.map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors))
222222
}
223223

224224
pub fn assumed_wf_types(

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

+19-3
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ pub trait TypeErrCtxtExt<'tcx> {
137137

138138
fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed;
139139

140-
fn report_fulfillment_errors(&self, errors: &[FulfillmentError<'tcx>]) -> ErrorGuaranteed;
140+
fn report_fulfillment_errors(&self, errors: Vec<FulfillmentError<'tcx>>) -> ErrorGuaranteed;
141141

142142
fn report_overflow_obligation<T>(
143143
&self,
@@ -401,7 +401,10 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
401401
}
402402

403403
impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
404-
fn report_fulfillment_errors(&self, errors: &[FulfillmentError<'tcx>]) -> ErrorGuaranteed {
404+
fn report_fulfillment_errors(
405+
&self,
406+
mut errors: Vec<FulfillmentError<'tcx>>,
407+
) -> ErrorGuaranteed {
405408
#[derive(Debug)]
406409
struct ErrorDescriptor<'tcx> {
407410
predicate: ty::Predicate<'tcx>,
@@ -423,6 +426,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
423426
})
424427
.collect();
425428

429+
// Ensure `T: Sized` and `T: WF` obligations come last. This lets us display diagnostics
430+
// with more relevant type information and hide redundant E0282 errors.
431+
errors.sort_by_key(|e| match e.obligation.predicate.kind().skip_binder() {
432+
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
433+
if Some(pred.def_id()) == self.tcx.lang_items().sized_trait() =>
434+
{
435+
1
436+
}
437+
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => 3,
438+
ty::PredicateKind::Coerce(_) => 2,
439+
_ => 0,
440+
});
441+
426442
for (index, error) in errors.iter().enumerate() {
427443
// We want to ignore desugarings here: spans are equivalent even
428444
// if one is the result of a desugaring and the other is not.
@@ -476,7 +492,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
476492
}
477493

478494
for from_expansion in [false, true] {
479-
for (error, suppressed) in iter::zip(errors, &is_suppressed) {
495+
for (error, suppressed) in iter::zip(&errors, &is_suppressed) {
480496
if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion {
481497
self.report_fulfillment_error(error);
482498
}

compiler/rustc_trait_selection/src/traits/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ fn do_normalize_predicates<'tcx>(
204204
let predicates = match fully_normalize(&infcx, cause, elaborated_env, predicates) {
205205
Ok(predicates) => predicates,
206206
Err(errors) => {
207-
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
207+
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
208208
return Err(reported);
209209
}
210210
};

tests/ui/array-slice-vec/vector-no-ann.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `Vec<T>`
22
--> $DIR/vector-no-ann.rs:2:9
33
|
44
LL | let _foo = Vec::new();
5-
| ^^^^
5+
| ^^^^ ---------- type must be known at this point
66
|
77
help: consider giving `_foo` an explicit type, where the type for type parameter `T` is specified
88
|

tests/ui/const-generics/const-argument-if-length.full.stderr

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
error: unconstrained generic constant
2+
--> $DIR/const-argument-if-length.rs:17:10
3+
|
4+
LL | pad: [u8; is_zst::<T>()],
5+
| ^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: try adding a `where` bound using this expression: `where [(); is_zst::<T>()]:`
8+
19
error[E0277]: the size for values of type `T` cannot be known at compilation time
210
--> $DIR/const-argument-if-length.rs:15:12
311
|
@@ -22,14 +30,6 @@ help: the `Box` type always has a statically known size and allocates its conten
2230
LL | value: Box<T>,
2331
| ++++ +
2432

25-
error: unconstrained generic constant
26-
--> $DIR/const-argument-if-length.rs:17:10
27-
|
28-
LL | pad: [u8; is_zst::<T>()],
29-
| ^^^^^^^^^^^^^^^^^^^
30-
|
31-
= help: try adding a `where` bound using this expression: `where [(); is_zst::<T>()]:`
32-
3333
error: aborting due to 2 previous errors
3434

3535
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
1-
error[E0282]: type annotations needed
1+
error[E0283]: type annotations needed
22
--> $DIR/issue-83249.rs:19:9
33
|
44
LL | let _ = foo([0; 1]);
5-
| ^
5+
| ^ --- ------ type must be known at this point
6+
| |
7+
| required by a bound introduced by this call
68
|
9+
= note: cannot satisfy `_: Foo`
10+
= help: the trait `Foo` is implemented for `u8`
11+
note: required by a bound in `foo`
12+
--> $DIR/issue-83249.rs:12:11
13+
|
14+
LL | fn foo<T: Foo>(_: [u8; T::N]) -> T {
15+
| ^^^ required by this bound in `foo`
716
help: consider giving this pattern a type
817
|
918
LL | let _: /* Type */ = foo([0; 1]);
1019
| ++++++++++++
1120

1221
error: aborting due to previous error
1322

14-
For more information about this error, try `rustc --explain E0282`.
23+
For more information about this error, try `rustc --explain E0283`.

tests/ui/error-codes/E0282.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
fn main() {
2-
let x = "hello".chars().rev().collect();
2+
let x;
33
//~^ ERROR E0282
4-
//~| ERROR E0283
54
}

tests/ui/error-codes/E0282.stderr

+5-38
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,14 @@
11
error[E0282]: type annotations needed
22
--> $DIR/E0282.rs:2:9
33
|
4-
LL | let x = "hello".chars().rev().collect();
4+
LL | let x;
55
| ^
66
|
77
help: consider giving `x` an explicit type
88
|
9-
LL | let x: Vec<_> = "hello".chars().rev().collect();
10-
| ++++++++
9+
LL | let x: /* Type */;
10+
| ++++++++++++
1111

12-
error[E0283]: type annotations needed
13-
--> $DIR/E0282.rs:2:9
14-
|
15-
LL | let x = "hello".chars().rev().collect();
16-
| ^ ------- type must be known at this point
17-
|
18-
= note: multiple `impl`s satisfying `_: FromIterator<char>` found in the following crates: `alloc`, `hashbrown`, `std`:
19-
- impl FromIterator<char> for String;
20-
- impl<'a, T> FromIterator<T> for Cow<'a, [T]>
21-
where T: Clone;
22-
- impl<'a> FromIterator<char> for Cow<'a, str>;
23-
- impl<I> FromIterator<I> for Box<[I]>;
24-
- impl<T, S, A> FromIterator<T> for hashbrown::set::HashSet<T, S, A>
25-
where T: Eq, T: Hash, S: BuildHasher, S: Default, A: Default, A: Allocator, A: Clone;
26-
- impl<T, S> FromIterator<T> for HashSet<T, S>
27-
where T: Eq, T: Hash, S: BuildHasher, S: Default;
28-
- impl<T> FromIterator<T> for Arc<[T]>;
29-
- impl<T> FromIterator<T> for BTreeSet<T>
30-
where T: Ord;
31-
- impl<T> FromIterator<T> for BinaryHeap<T>
32-
where T: Ord;
33-
- impl<T> FromIterator<T> for LinkedList<T>;
34-
- impl<T> FromIterator<T> for Rc<[T]>;
35-
- impl<T> FromIterator<T> for Vec<T>;
36-
- impl<T> FromIterator<T> for VecDeque<T>;
37-
note: required by a bound in `collect`
38-
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
39-
help: consider giving `x` an explicit type
40-
|
41-
LL | let x: Vec<_> = "hello".chars().rev().collect();
42-
| ++++++++
43-
44-
error: aborting due to 2 previous errors
12+
error: aborting due to previous error
4513

46-
Some errors have detailed explanations: E0282, E0283.
47-
For more information about an error, try `rustc --explain E0282`.
14+
For more information about this error, try `rustc --explain E0282`.

0 commit comments

Comments
 (0)