Skip to content

Commit b6124ed

Browse files
Globally deduplicate matching fulfillment errors
1 parent 047c4fa commit b6124ed

18 files changed

+42
-268
lines changed

compiler/rustc_typeck/src/check/fn_ctxt/checks.rs

+5-10
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ use crate::check::{
1515
use crate::structured_errors::StructuredDiagnostic;
1616

1717
use rustc_ast as ast;
18-
use rustc_data_structures::fx::FxHashSet;
1918
use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticId, MultiSpan};
2019
use rustc_hir as hir;
2120
use rustc_hir::def::{CtorOf, DefKind, Res};
@@ -1618,12 +1617,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16181617
&self,
16191618
errors: &mut Vec<traits::FulfillmentError<'tcx>>,
16201619
) {
1621-
// Store a mapping from `(Span, Predicate) -> ObligationCause`, so that
1622-
// other errors that have the same span and predicate can also get fixed,
1623-
// even if their `ObligationCauseCode` isn't an `Expr*Obligation` kind.
1624-
// This is important since if we adjust one span but not the other, then
1625-
// we will have "duplicated" the error on the UI side.
1626-
let mut remap_cause = FxHashSet::default();
16271620
let mut not_adjusted = vec![];
16281621

16291622
for error in errors {
@@ -1634,6 +1627,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16341627
// Store both the predicate and the predicate *without constness*
16351628
// since sometimes we instantiate and check both of these in a
16361629
// method call, for example.
1630+
let mut remap_cause = self.remap_fulfillment_cause.borrow_mut();
16371631
remap_cause.insert((
16381632
before_span,
16391633
error.obligation.predicate,
@@ -1652,9 +1646,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16521646
}
16531647

16541648
for error in not_adjusted {
1655-
for (span, predicate, cause) in &remap_cause {
1649+
for (span, predicate, cause) in &*self.remap_fulfillment_cause.borrow() {
16561650
if *predicate == error.obligation.predicate
1657-
&& span.contains(error.obligation.cause.span)
1651+
&& span.overlaps(error.obligation.cause.span)
16581652
{
16591653
error.obligation.cause = cause.clone();
16601654
continue;
@@ -1667,7 +1661,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16671661
&self,
16681662
error: &mut traits::FulfillmentError<'tcx>,
16691663
) -> bool {
1670-
let (traits::ExprItemObligation(def_id, hir_id, idx) | traits::ExprBindingObligation(def_id, _, hir_id, idx))
1664+
let (traits::ExprItemObligation(def_id, hir_id, idx)
1665+
| traits::ExprBindingObligation(def_id, _, hir_id, idx))
16711666
= *error.obligation.cause.code().peel_derives() else { return false; };
16721667
let hir = self.tcx.hir();
16731668
let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; };

compiler/rustc_typeck/src/check/fn_ctxt/mod.rs

+10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod checks;
44
mod suggestions;
55

66
pub use _impl::*;
7+
use rustc_data_structures::fx::FxHashSet;
78
pub use suggestions::*;
89

910
use crate::astconv::AstConv;
@@ -129,6 +130,14 @@ pub struct FnCtxt<'a, 'tcx> {
129130

130131
/// True if the return type has an Opaque type
131132
pub(super) return_type_has_opaque: bool,
133+
134+
// Store a mapping from `(Span, Predicate) -> ObligationCause`, so that
135+
// other errors that have the same span and predicate can also get fixed,
136+
// even if their `ObligationCauseCode` isn't an `Expr{Item,Binding}Obligation`.
137+
// This is important since if we adjust one span but not the other, then
138+
// we will have "duplicated" the error on the UI side.
139+
pub(super) remap_fulfillment_cause:
140+
RefCell<FxHashSet<(Span, ty::Predicate<'tcx>, ObligationCause<'tcx>)>>,
132141
}
133142

134143
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -156,6 +165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
156165
inh,
157166
return_type_pre_known: true,
158167
return_type_has_opaque: false,
168+
remap_fulfillment_cause: Default::default(),
159169
}
160170
}
161171

src/test/ui/associated-types/associated-types-path-2.rs

-2
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,12 @@ pub fn f1_uint_uint() {
2929
f1(2u32, 4u32);
3030
//~^ ERROR `u32: Foo` is not satisfied
3131
//~| ERROR `u32: Foo` is not satisfied
32-
//~| ERROR `u32: Foo` is not satisfied
3332
}
3433

3534
pub fn f1_uint_int() {
3635
f1(2u32, 4i32);
3736
//~^ ERROR `u32: Foo` is not satisfied
3837
//~| ERROR `u32: Foo` is not satisfied
39-
//~| ERROR `u32: Foo` is not satisfied
4038
}
4139

4240
pub fn f2_int() {

src/test/ui/associated-types/associated-types-path-2.stderr

+4-20
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,6 @@ note: required by a bound in `f1`
3131
LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
3232
| ^^^ required by this bound in `f1`
3333

34-
error[E0277]: the trait bound `u32: Foo` is not satisfied
35-
--> $DIR/associated-types-path-2.rs:29:5
36-
|
37-
LL | f1(2u32, 4u32);
38-
| ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
39-
|
40-
= help: the trait `Foo` is implemented for `i32`
41-
4234
error[E0277]: the trait bound `u32: Foo` is not satisfied
4335
--> $DIR/associated-types-path-2.rs:29:14
4436
|
@@ -48,7 +40,7 @@ LL | f1(2u32, 4u32);
4840
= help: the trait `Foo` is implemented for `i32`
4941

5042
error[E0277]: the trait bound `u32: Foo` is not satisfied
51-
--> $DIR/associated-types-path-2.rs:36:8
43+
--> $DIR/associated-types-path-2.rs:35:8
5244
|
5345
LL | f1(2u32, 4i32);
5446
| -- ^^^^ the trait `Foo` is not implemented for `u32`
@@ -63,23 +55,15 @@ LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
6355
| ^^^ required by this bound in `f1`
6456

6557
error[E0277]: the trait bound `u32: Foo` is not satisfied
66-
--> $DIR/associated-types-path-2.rs:36:5
67-
|
68-
LL | f1(2u32, 4i32);
69-
| ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
70-
|
71-
= help: the trait `Foo` is implemented for `i32`
72-
73-
error[E0277]: the trait bound `u32: Foo` is not satisfied
74-
--> $DIR/associated-types-path-2.rs:36:14
58+
--> $DIR/associated-types-path-2.rs:35:14
7559
|
7660
LL | f1(2u32, 4i32);
7761
| ^^^^ the trait `Foo` is not implemented for `u32`
7862
|
7963
= help: the trait `Foo` is implemented for `i32`
8064

8165
error[E0308]: mismatched types
82-
--> $DIR/associated-types-path-2.rs:43:18
66+
--> $DIR/associated-types-path-2.rs:41:18
8367
|
8468
LL | let _: i32 = f2(2i32);
8569
| --- ^^^^^^^^ expected `i32`, found `u32`
@@ -91,7 +75,7 @@ help: you can convert a `u32` to an `i32` and panic if the converted value doesn
9175
LL | let _: i32 = f2(2i32).try_into().unwrap();
9276
| ++++++++++++++++++++
9377

94-
error: aborting due to 8 previous errors
78+
error: aborting due to 6 previous errors
9579

9680
Some errors have detailed explanations: E0277, E0308.
9781
For more information about an error, try `rustc --explain E0277`.

src/test/ui/box/into-boxed-slice-fail.rs

-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ fn main() {
66
let boxed_slice = Box::new([1,2,3]) as Box<[u8]>;
77
let _ = Box::into_boxed_slice(boxed_slice);
88
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
9-
//~^^ ERROR the size for values of type `[u8]` cannot be known at compilation time
109
let boxed_trait: Box<dyn Debug> = Box::new(5u8);
1110
let _ = Box::into_boxed_slice(boxed_trait);
1211
//~^ ERROR the size for values of type `dyn Debug` cannot be known at compilation time
13-
//~^^ ERROR the size for values of type `dyn Debug` cannot be known at compilation time
1412
}

src/test/ui/box/into-boxed-slice-fail.stderr

+2-20
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,8 @@ note: required by a bound in `Box::<T, A>::into_boxed_slice`
1313
LL | impl<T, A: Allocator> Box<T, A> {
1414
| ^ required by this bound in `Box::<T, A>::into_boxed_slice`
1515

16-
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
17-
--> $DIR/into-boxed-slice-fail.rs:7:13
18-
|
19-
LL | let _ = Box::into_boxed_slice(boxed_slice);
20-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
21-
|
22-
= help: the trait `Sized` is not implemented for `[u8]`
23-
= note: slice and array elements must have `Sized` type
24-
2516
error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
26-
--> $DIR/into-boxed-slice-fail.rs:11:35
17+
--> $DIR/into-boxed-slice-fail.rs:10:35
2718
|
2819
LL | let _ = Box::into_boxed_slice(boxed_trait);
2920
| --------------------- ^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -37,15 +28,6 @@ note: required by a bound in `Box::<T, A>::into_boxed_slice`
3728
LL | impl<T, A: Allocator> Box<T, A> {
3829
| ^ required by this bound in `Box::<T, A>::into_boxed_slice`
3930

40-
error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
41-
--> $DIR/into-boxed-slice-fail.rs:11:13
42-
|
43-
LL | let _ = Box::into_boxed_slice(boxed_trait);
44-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
45-
|
46-
= help: the trait `Sized` is not implemented for `dyn Debug`
47-
= note: slice and array elements must have `Sized` type
48-
49-
error: aborting due to 4 previous errors
31+
error: aborting due to 2 previous errors
5032

5133
For more information about this error, try `rustc --explain E0277`.

src/test/ui/iterators/issue-28098.rs

-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
fn main() {
22
let _ = Iterator::next(&mut ());
33
//~^ ERROR `()` is not an iterator
4-
//~| ERROR `()` is not an iterator
5-
//~| ERROR `()` is not an iterator
64

75
for _ in false {}
86
//~^ ERROR `bool` is not an iterator
97

108
let _ = Iterator::next(&mut ());
119
//~^ ERROR `()` is not an iterator
12-
//~| ERROR `()` is not an iterator
1310

1411
other()
1512
}
@@ -19,12 +16,9 @@ pub fn other() {
1916

2017
let _ = Iterator::next(&mut ());
2118
//~^ ERROR `()` is not an iterator
22-
//~| ERROR `()` is not an iterator
23-
//~| ERROR `()` is not an iterator
2419

2520
let _ = Iterator::next(&mut ());
2621
//~^ ERROR `()` is not an iterator
27-
//~| ERROR `()` is not an iterator
2822

2923
for _ in false {}
3024
//~^ ERROR `bool` is not an iterator

src/test/ui/iterators/issue-28098.stderr

+6-54
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,8 @@ LL | let _ = Iterator::next(&mut ());
88
|
99
= help: the trait `Iterator` is not implemented for `()`
1010

11-
error[E0277]: `()` is not an iterator
12-
--> $DIR/issue-28098.rs:2:13
13-
|
14-
LL | let _ = Iterator::next(&mut ());
15-
| ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
16-
|
17-
= help: the trait `Iterator` is not implemented for `()`
18-
1911
error[E0277]: `bool` is not an iterator
20-
--> $DIR/issue-28098.rs:7:14
12+
--> $DIR/issue-28098.rs:5:14
2113
|
2214
LL | for _ in false {}
2315
| ^^^^^ `bool` is not an iterator
@@ -26,7 +18,7 @@ LL | for _ in false {}
2618
= note: required for `bool` to implement `IntoIterator`
2719

2820
error[E0277]: `()` is not an iterator
29-
--> $DIR/issue-28098.rs:10:28
21+
--> $DIR/issue-28098.rs:8:28
3022
|
3123
LL | let _ = Iterator::next(&mut ());
3224
| -------------- ^^^^^^^ `()` is not an iterator
@@ -36,23 +28,7 @@ LL | let _ = Iterator::next(&mut ());
3628
= help: the trait `Iterator` is not implemented for `()`
3729

3830
error[E0277]: `()` is not an iterator
39-
--> $DIR/issue-28098.rs:10:13
40-
|
41-
LL | let _ = Iterator::next(&mut ());
42-
| ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
43-
|
44-
= help: the trait `Iterator` is not implemented for `()`
45-
46-
error[E0277]: `()` is not an iterator
47-
--> $DIR/issue-28098.rs:2:13
48-
|
49-
LL | let _ = Iterator::next(&mut ());
50-
| ^^^^^^^^^^^^^^ `()` is not an iterator
51-
|
52-
= help: the trait `Iterator` is not implemented for `()`
53-
54-
error[E0277]: `()` is not an iterator
55-
--> $DIR/issue-28098.rs:20:28
31+
--> $DIR/issue-28098.rs:17:28
5632
|
5733
LL | let _ = Iterator::next(&mut ());
5834
| -------------- ^^^^^^^ `()` is not an iterator
@@ -62,15 +38,7 @@ LL | let _ = Iterator::next(&mut ());
6238
= help: the trait `Iterator` is not implemented for `()`
6339

6440
error[E0277]: `()` is not an iterator
65-
--> $DIR/issue-28098.rs:20:13
66-
|
67-
LL | let _ = Iterator::next(&mut ());
68-
| ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
69-
|
70-
= help: the trait `Iterator` is not implemented for `()`
71-
72-
error[E0277]: `()` is not an iterator
73-
--> $DIR/issue-28098.rs:25:28
41+
--> $DIR/issue-28098.rs:20:28
7442
|
7543
LL | let _ = Iterator::next(&mut ());
7644
| -------------- ^^^^^^^ `()` is not an iterator
@@ -79,31 +47,15 @@ LL | let _ = Iterator::next(&mut ());
7947
|
8048
= help: the trait `Iterator` is not implemented for `()`
8149

82-
error[E0277]: `()` is not an iterator
83-
--> $DIR/issue-28098.rs:25:13
84-
|
85-
LL | let _ = Iterator::next(&mut ());
86-
| ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
87-
|
88-
= help: the trait `Iterator` is not implemented for `()`
89-
9050
error[E0277]: `bool` is not an iterator
91-
--> $DIR/issue-28098.rs:29:14
51+
--> $DIR/issue-28098.rs:23:14
9252
|
9353
LL | for _ in false {}
9454
| ^^^^^ `bool` is not an iterator
9555
|
9656
= help: the trait `Iterator` is not implemented for `bool`
9757
= note: required for `bool` to implement `IntoIterator`
9858

99-
error[E0277]: `()` is not an iterator
100-
--> $DIR/issue-28098.rs:20:13
101-
|
102-
LL | let _ = Iterator::next(&mut ());
103-
| ^^^^^^^^^^^^^^ `()` is not an iterator
104-
|
105-
= help: the trait `Iterator` is not implemented for `()`
106-
107-
error: aborting due to 12 previous errors
59+
error: aborting due to 6 previous errors
10860

10961
For more information about this error, try `rustc --explain E0277`.

src/test/ui/on-unimplemented/multiple-impls.rs

-6
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,8 @@ impl Index<Bar<usize>> for [i32] {
3232
fn main() {
3333
Index::index(&[] as &[i32], 2u32);
3434
//~^ ERROR E0277
35-
//~| ERROR E0277
36-
//~| ERROR E0277
3735
Index::index(&[] as &[i32], Foo(2u32));
3836
//~^ ERROR E0277
39-
//~| ERROR E0277
40-
//~| ERROR E0277
4137
Index::index(&[] as &[i32], Bar(2u32));
4238
//~^ ERROR E0277
43-
//~| ERROR E0277
44-
//~| ERROR E0277
4539
}

0 commit comments

Comments
 (0)