Skip to content

Commit b309646

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 4417513 commit b309646

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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
742742

743743
let errors = ocx.select_all_or_error();
744744
if !errors.is_empty() {
745-
infcx.err_ctxt().report_fulfillment_errors(&errors);
745+
infcx.err_ctxt().report_fulfillment_errors(errors);
746746
}
747747

748748
// Attempting to call a trait method?

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ fn check_opaque_meets_bounds<'tcx>(
456456
// version.
457457
let errors = ocx.select_all_or_error();
458458
if !errors.is_empty() {
459-
let guar = infcx.err_ctxt().report_fulfillment_errors(&errors);
459+
let guar = infcx.err_ctxt().report_fulfillment_errors(errors);
460460
return Err(guar);
461461
}
462462
match origin {
@@ -1641,6 +1641,6 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
16411641
let errors = fulfillment_cx.select_all_or_error(&infcx);
16421642
debug!(?errors);
16431643
if !errors.is_empty() {
1644-
infcx.err_ctxt().report_fulfillment_errors(&errors);
1644+
infcx.err_ctxt().report_fulfillment_errors(errors);
16451645
}
16461646
}

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

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

@@ -393,7 +393,7 @@ fn compare_method_predicate_entailment<'tcx>(
393393
});
394394
}
395395
CheckImpliedWfMode::Skip => {
396-
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
396+
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
397397
return Err(reported);
398398
}
399399
}
@@ -873,7 +873,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
873873
// RPITs.
874874
let errors = ocx.select_all_or_error();
875875
if !errors.is_empty() {
876-
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
876+
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
877877
return Err(reported);
878878
}
879879

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

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

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

compiler/rustc_hir_analysis/src/check/entry.rs

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ pub fn check_function_signature<'tcx>(
577577
Ok(()) => {
578578
let errors = ocx.select_all_or_error();
579579
if !errors.is_empty() {
580-
infcx.err_ctxt().report_fulfillment_errors(&errors);
580+
infcx.err_ctxt().report_fulfillment_errors(errors);
581581
return;
582582
}
583583
}

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
113113

114114
let errors = wfcx.select_all_or_error();
115115
if !errors.is_empty() {
116-
infcx.err_ctxt().report_fulfillment_errors(&errors);
116+
infcx.err_ctxt().report_fulfillment_errors(errors);
117117
return;
118118
}
119119

compiler/rustc_hir_analysis/src/coherence/builtin.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
279279
}
280280
let errors = ocx.select_all_or_error();
281281
if !errors.is_empty() {
282-
infcx.err_ctxt().report_fulfillment_errors(&errors);
282+
infcx.err_ctxt().report_fulfillment_errors(errors);
283283
}
284284

285285
// Finally, resolve all regions.
@@ -519,7 +519,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
519519
ocx.register_obligation(obligation);
520520
let errors = ocx.select_all_or_error();
521521
if !errors.is_empty() {
522-
infcx.err_ctxt().report_fulfillment_errors(&errors);
522+
infcx.err_ctxt().report_fulfillment_errors(errors);
523523
}
524524

525525
// Finally, resolve all regions.

compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 3 additions & 3 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
203203
def_id: LocalDefId,
204204
) -> Result<FxIndexSet<Ty<'tcx>>, ErrorGuaranteed> {
205205
self.assumed_wf_types(param_env, def_id)
206-
.map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(&errors))
206+
.map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors))
207207
}
208208

209209
pub fn assumed_wf_types(

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

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ pub trait TypeErrCtxtExt<'tcx> {
134134

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

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

139139
fn report_overflow_obligation<T>(
140140
&self,
@@ -398,7 +398,10 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
398398
}
399399

400400
impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
401-
fn report_fulfillment_errors(&self, errors: &[FulfillmentError<'tcx>]) -> ErrorGuaranteed {
401+
fn report_fulfillment_errors(
402+
&self,
403+
mut errors: Vec<FulfillmentError<'tcx>>,
404+
) -> ErrorGuaranteed {
402405
#[derive(Debug)]
403406
struct ErrorDescriptor<'tcx> {
404407
predicate: ty::Predicate<'tcx>,
@@ -420,6 +423,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
420423
})
421424
.collect();
422425

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

475491
for from_expansion in [false, true] {
476-
for (error, suppressed) in iter::zip(errors, &is_suppressed) {
492+
for (error, suppressed) in iter::zip(&errors, &is_suppressed) {
477493
if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion {
478494
self.report_fulfillment_error(error);
479495
}

compiler/rustc_trait_selection/src/traits/mod.rs

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 8 additions & 8 deletions
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`.
Lines changed: 12 additions & 3 deletions
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

Lines changed: 1 addition & 2 deletions
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

Lines changed: 5 additions & 38 deletions
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)