@@ -80,14 +80,28 @@ pub fn suggest_new_overflow_limit<'tcx, G: EmissionGuarantee>(
80
80
81
81
#[ extension( pub trait TypeErrCtxtExt <' tcx>) ]
82
82
impl < ' tcx > TypeErrCtxt < ' _ , ' tcx > {
83
+ #[ instrument( skip( self ) , level = "debug" ) ]
83
84
fn report_fulfillment_errors (
84
85
& self ,
85
86
mut errors : Vec < FulfillmentError < ' tcx > > ,
86
87
) -> ErrorGuaranteed {
88
+ if errors. is_empty ( ) {
89
+ bug ! ( "attempted to report fulfillment errors, but there we no errors" ) ;
90
+ }
91
+
87
92
self . sub_relations
88
93
. borrow_mut ( )
89
94
. add_constraints ( self , errors. iter ( ) . map ( |e| e. obligation . predicate ) ) ;
90
95
96
+ let mut reported = None ;
97
+
98
+ // We want to ignore desugarings when filtering errors: spans are equivalent even
99
+ // if one is the result of a desugaring and the other is not.
100
+ let strip_desugaring = |span : Span | {
101
+ let expn_data = span. ctxt ( ) . outer_expn_data ( ) ;
102
+ if let ExpnKind :: Desugaring ( _) = expn_data. kind { expn_data. call_site } else { span }
103
+ } ;
104
+
91
105
#[ derive( Debug ) ]
92
106
struct ErrorDescriptor < ' tcx > {
93
107
predicate : ty:: Predicate < ' tcx > ,
@@ -98,40 +112,32 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
98
112
. reported_trait_errors
99
113
. borrow ( )
100
114
. iter ( )
101
- . map ( |( & span, predicates) | {
102
- (
103
- span,
104
- predicates
105
- . 0
106
- . iter ( )
107
- . map ( |& predicate| ErrorDescriptor { predicate, index : None } )
108
- . collect ( ) ,
109
- )
115
+ . map ( |( & span, & ( ref predicates, guar) ) | {
116
+ reported = Some ( guar) ;
117
+ let span = strip_desugaring ( span) ;
118
+ let reported_errors = predicates
119
+ . iter ( )
120
+ . map ( |& predicate| ErrorDescriptor { predicate, index : None } )
121
+ . collect ( ) ;
122
+ ( span, reported_errors)
110
123
} )
111
124
. collect ( ) ;
112
125
113
126
// Ensure `T: Sized` and `T: WF` obligations come last. This lets us display diagnostics
114
- // with more relevant type information and hide redundant E0282 errors.
127
+ // with more relevant type information and hide redundant E0282 ("type annotations needed") errors.
115
128
errors. sort_by_key ( |e| match e. obligation . predicate . kind ( ) . skip_binder ( ) {
116
129
ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) )
117
130
if Some ( pred. def_id ( ) ) == self . tcx . lang_items ( ) . sized_trait ( ) =>
118
131
{
119
132
1
120
133
}
121
- ty:: PredicateKind :: Clause ( ty:: ClauseKind :: WellFormed ( _) ) => 3 ,
122
134
ty:: PredicateKind :: Coerce ( _) => 2 ,
135
+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: WellFormed ( _) ) => 3 ,
123
136
_ => 0 ,
124
137
} ) ;
125
138
126
139
for ( index, error) in errors. iter ( ) . enumerate ( ) {
127
- // We want to ignore desugarings here: spans are equivalent even
128
- // if one is the result of a desugaring and the other is not.
129
- let mut span = error. obligation . cause . span ;
130
- let expn_data = span. ctxt ( ) . outer_expn_data ( ) ;
131
- if let ExpnKind :: Desugaring ( _) = expn_data. kind {
132
- span = expn_data. call_site ;
133
- }
134
-
140
+ let span = strip_desugaring ( error. obligation . cause . span ) ;
135
141
error_map. entry ( span) . or_default ( ) . push ( ErrorDescriptor {
136
142
predicate : error. obligation . predicate ,
137
143
index : Some ( index) ,
@@ -144,59 +150,48 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
144
150
for ( _, error_set) in error_map. iter ( ) {
145
151
// We want to suppress "duplicate" errors with the same span.
146
152
for error in error_set {
147
- if let Some ( index) = error. index {
148
- // Suppress errors that are either:
149
- // 1) strictly implied by another error.
150
- // 2) implied by an error with a smaller index.
151
- for error2 in error_set {
152
- if error2. index . is_some_and ( |index2| is_suppressed[ index2] ) {
153
- // Avoid errors being suppressed by already-suppressed
154
- // errors, to prevent all errors from being suppressed
155
- // at once.
156
- continue ;
157
- }
153
+ let Some ( index) = error. index else {
154
+ continue ;
155
+ } ;
158
156
159
- if self . error_implies ( error2. predicate , error. predicate )
160
- && !( error2. index >= error. index
161
- && self . error_implies ( error. predicate , error2. predicate ) )
162
- {
163
- info ! ( "skipping {:?} (implied by {:?})" , error, error2) ;
164
- is_suppressed[ index] = true ;
165
- break ;
166
- }
157
+ // Suppress errors that are either:
158
+ // 1) strictly implied by another error.
159
+ // 2) implied by an error with a smaller index.
160
+ for error2 in error_set {
161
+ if self . error_implies ( error2. predicate , error. predicate )
162
+ && ( !error2. index . is_some_and ( |index2| index2 >= index)
163
+ || !self . error_implies ( error. predicate , error2. predicate ) )
164
+ {
165
+ info ! ( "skipping `{}` (implied by `{}`)" , error. predicate, error2. predicate) ;
166
+ is_suppressed[ index] = true ;
167
+ break ;
167
168
}
168
169
}
169
170
}
170
171
}
171
172
172
- let mut reported = None ;
173
-
174
173
for from_expansion in [ false , true ] {
175
- for ( error, suppressed) in iter:: zip ( & errors, & is_suppressed) {
176
- if !suppressed && error. obligation . cause . span . from_expansion ( ) == from_expansion {
177
- let guar = self . report_fulfillment_error ( error) ;
178
- reported = Some ( guar) ;
179
- // We want to ignore desugarings here: spans are equivalent even
180
- // if one is the result of a desugaring and the other is not.
181
- let mut span = error. obligation . cause . span ;
182
- let expn_data = span. ctxt ( ) . outer_expn_data ( ) ;
183
- if let ExpnKind :: Desugaring ( _) = expn_data. kind {
184
- span = expn_data. call_site ;
185
- }
186
- self . reported_trait_errors
187
- . borrow_mut ( )
188
- . entry ( span)
189
- . or_insert_with ( || ( vec ! [ ] , guar) )
190
- . 0
191
- . push ( error. obligation . predicate ) ;
174
+ for ( error, & suppressed) in iter:: zip ( & errors, & is_suppressed) {
175
+ let span = error. obligation . cause . span ;
176
+ if suppressed || span. from_expansion ( ) != from_expansion {
177
+ continue ;
192
178
}
179
+
180
+ let guar = self . report_fulfillment_error ( error) ;
181
+ reported = Some ( guar) ;
182
+
183
+ self . reported_trait_errors
184
+ . borrow_mut ( )
185
+ . entry ( span)
186
+ . or_insert_with ( || ( vec ! [ ] , guar) )
187
+ . 0
188
+ . push ( error. obligation . predicate ) ;
193
189
}
194
190
}
195
191
196
- // It could be that we don't report an error because we have seen an `ErrorReported` from
197
- // another source. We should probably be able to fix most of these, but some are delayed
198
- // bugs that get a proper error after this function.
199
- reported. unwrap_or_else ( || self . dcx ( ) . delayed_bug ( "failed to report fulfillment errors" ) )
192
+ // If all errors are suppressed, then we must have reported at least one error
193
+ // from a previous call to this function.
194
+ reported. unwrap_or_else ( || bug ! ( "failed to report fulfillment errors" ) )
200
195
}
201
196
202
197
/// Reports that an overflow has occurred and halts compilation. We
0 commit comments