Skip to content

Commit acaad3c

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 d4d4936 commit acaad3c

File tree

72 files changed

+278
-393
lines changed

Some content is hidden

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

72 files changed

+278
-393
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
@@ -361,7 +361,7 @@ fn check_opaque_type_well_formed<'tcx>(
361361
if errors.is_empty() {
362362
Ok(definition_ty)
363363
} else {
364-
Err(infcx.err_ctxt().report_fulfillment_errors(&errors))
364+
Err(infcx.err_ctxt().report_fulfillment_errors(errors))
365365
}
366366
}
367367

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 {
@@ -1627,6 +1627,6 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
16271627
let errors = fulfillment_cx.select_all_or_error(&infcx);
16281628
debug!(?errors);
16291629
if !errors.is_empty() {
1630-
infcx.err_ctxt().report_fulfillment_errors(&errors);
1630+
infcx.err_ctxt().report_fulfillment_errors(errors);
16311631
}
16321632
}

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ fn compare_method_predicate_entailment<'tcx>(
313313
// FIXME(-Ztrait-solver=next): Not needed when the hack below is removed.
314314
let errors = ocx.select_where_possible();
315315
if !errors.is_empty() {
316-
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
316+
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
317317
return Err(reported);
318318
}
319319

@@ -377,7 +377,7 @@ fn compare_method_predicate_entailment<'tcx>(
377377
});
378378
}
379379
CheckImpliedWfMode::Skip => {
380-
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
380+
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
381381
return Err(reported);
382382
}
383383
}
@@ -776,7 +776,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
776776
// RPITs.
777777
let errors = ocx.select_all_or_error();
778778
if !errors.is_empty() {
779-
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
779+
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
780780
return Err(reported);
781781
}
782782

@@ -1951,7 +1951,7 @@ fn compare_const_predicate_entailment<'tcx>(
19511951
// version.
19521952
let errors = ocx.select_all_or_error();
19531953
if !errors.is_empty() {
1954-
return Err(infcx.err_ctxt().report_fulfillment_errors(&errors));
1954+
return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
19551955
}
19561956

19571957
let outlives_env = OutlivesEnvironment::new(param_env);
@@ -2044,7 +2044,7 @@ fn compare_type_predicate_entailment<'tcx>(
20442044
// version.
20452045
let errors = ocx.select_all_or_error();
20462046
if !errors.is_empty() {
2047-
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
2047+
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
20482048
return Err(reported);
20492049
}
20502050

@@ -2259,7 +2259,7 @@ pub(super) fn check_type_bounds<'tcx>(
22592259
// version.
22602260
let errors = ocx.select_all_or_error();
22612261
if !errors.is_empty() {
2262-
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
2262+
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
22632263
return Err(reported);
22642264
}
22652265

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/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
@@ -271,7 +271,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
271271
}
272272
let errors = ocx.select_all_or_error();
273273
if !errors.is_empty() {
274-
infcx.err_ctxt().report_fulfillment_errors(&errors);
274+
infcx.err_ctxt().report_fulfillment_errors(errors);
275275
}
276276

277277
// Finally, resolve all regions.
@@ -511,7 +511,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
511511
ocx.register_obligation(obligation);
512512
let errors = ocx.select_all_or_error();
513513
if !errors.is_empty() {
514-
infcx.err_ctxt().report_fulfillment_errors(&errors);
514+
infcx.err_ctxt().report_fulfillment_errors(errors);
515515
}
516516

517517
// 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_analysis/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ fn require_same_types<'tcx>(
164164
Ok(()) => {
165165
let errors = ocx.select_all_or_error();
166166
if !errors.is_empty() {
167-
infcx.err_ctxt().report_fulfillment_errors(&errors);
167+
infcx.err_ctxt().report_fulfillment_errors(errors);
168168
}
169169
}
170170
Err(err) => {

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3004,7 +3004,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30043004
// There should be at least one error reported. If not, we
30053005
// will still delay a span bug in `report_fulfillment_errors`.
30063006
Ok::<_, NoSolution>((
3007-
self.err_ctxt().report_fulfillment_errors(&errors),
3007+
self.err_ctxt().report_fulfillment_errors(errors),
30083008
impl_trait_ref.args.type_at(1),
30093009
element_ty,
30103010
))

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
579579

580580
if !errors.is_empty() {
581581
self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);
582-
self.err_ctxt().report_fulfillment_errors(&errors);
582+
self.err_ctxt().report_fulfillment_errors(errors);
583583
}
584584
}
585585

@@ -592,7 +592,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
592592
if !result.is_empty() {
593593
mutate_fulfillment_errors(&mut result);
594594
self.adjust_fulfillment_errors_for_expr_obligation(&mut result);
595-
self.err_ctxt().report_fulfillment_errors(&result);
595+
self.err_ctxt().report_fulfillment_errors(result);
596596
}
597597
}
598598

@@ -1473,7 +1473,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14731473
{
14741474
Ok(normalized_ty) => normalized_ty,
14751475
Err(errors) => {
1476-
let guar = self.err_ctxt().report_fulfillment_errors(&errors);
1476+
let guar = self.err_ctxt().report_fulfillment_errors(errors);
14771477
return Ty::new_error(self.tcx,guar);
14781478
}
14791479
}

compiler/rustc_passes/src/check_attr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2300,7 +2300,7 @@ impl CheckAttrVisitor<'_> {
23002300

23012301
let errors = ocx.select_all_or_error();
23022302
if !errors.is_empty() {
2303-
infcx.err_ctxt().report_fulfillment_errors(&errors);
2303+
infcx.err_ctxt().report_fulfillment_errors(errors);
23042304
self.abort.set(true);
23052305
}
23062306
}

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)