@@ -80,61 +80,81 @@ pub fn suggest_new_overflow_limit<'tcx, G: EmissionGuarantee>(
8080
8181#[ extension( pub trait TypeErrCtxtExt <' tcx>) ]
8282impl < ' tcx > TypeErrCtxt < ' _ , ' tcx > {
83+ #[ instrument( skip( self ) , level = "debug" ) ]
8384 fn report_fulfillment_errors (
8485 & self ,
8586 mut errors : Vec < FulfillmentError < ' tcx > > ,
8687 ) -> ErrorGuaranteed {
88+ if errors. is_empty ( ) {
89+ bug ! ( "attempted to report fulfillment errors, but there we no errors" ) ;
90+ }
91+
8792 self . sub_relations
8893 . borrow_mut ( )
8994 . add_constraints ( self , errors. iter ( ) . map ( |e| e. obligation . predicate ) ) ;
9095
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+
91105 #[ derive( Debug ) ]
92- struct ErrorDescriptor < ' tcx > {
106+ struct ErrorDescriptor < ' tcx , ' err > {
93107 predicate : ty:: Predicate < ' tcx > ,
94- index : Option < usize > , // None if this is an old error
108+ source : Option < ( usize , & ' err FulfillmentError < ' tcx > ) > , // None if this is an old error
95109 }
96110
97111 let mut error_map: FxIndexMap < _ , Vec < _ > > = self
98112 . reported_trait_errors
99113 . borrow ( )
100114 . 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, source : None } )
121+ . collect ( ) ;
122+ ( span, reported_errors)
110123 } )
111124 . collect ( ) ;
112125
126+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , PartialOrd , Ord ) ]
127+ enum ErrorOrd {
128+ Default ,
129+ Sized ,
130+ Metadata ,
131+ Coerce ,
132+ WellFormed ,
133+ }
134+
113135 // 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.
136+ // with more relevant type information and hide redundant E0282 ("type annotations needed") errors.
115137 errors. sort_by_key ( |e| match e. obligation . predicate . kind ( ) . skip_binder ( ) {
116138 ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) )
117139 if Some ( pred. def_id ( ) ) == self . tcx . lang_items ( ) . sized_trait ( ) =>
118140 {
119- 1
141+ ErrorOrd :: Sized
142+ }
143+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( pred) )
144+ if Some ( pred. def_id ( ) ) == self . tcx . lang_items ( ) . metadata_type ( ) =>
145+ {
146+ ErrorOrd :: Metadata
120147 }
121- ty:: PredicateKind :: Clause ( ty :: ClauseKind :: WellFormed ( _ ) ) => 3 ,
122- ty:: PredicateKind :: Coerce ( _ ) => 2 ,
123- _ => 0 ,
148+ ty:: PredicateKind :: Coerce ( _ ) => ErrorOrd :: Coerce ,
149+ ty:: PredicateKind :: Clause ( ty :: ClauseKind :: WellFormed ( _ ) ) => ErrorOrd :: WellFormed ,
150+ _ => ErrorOrd :: Default ,
124151 } ) ;
125152
126153 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-
154+ let span = strip_desugaring ( error. obligation . cause . span ) ;
135155 error_map. entry ( span) . or_default ( ) . push ( ErrorDescriptor {
136156 predicate : error. obligation . predicate ,
137- index : Some ( index) ,
157+ source : Some ( ( index, error ) ) ,
138158 } ) ;
139159 }
140160
@@ -144,59 +164,63 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
144164 for ( _, error_set) in error_map. iter ( ) {
145165 // We want to suppress "duplicate" errors with the same span.
146166 for error in error_set {
147- if let Some ( index) = error. index {
167+ let Some ( ( index, error_source) ) = error. source else {
168+ continue ;
169+ } ;
170+
171+ for error2 in error_set {
148172 // Suppress errors that are either:
149173 // 1) strictly implied by another error.
150174 // 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- }
175+ if self . error_implied_by ( error. predicate , error2. predicate )
176+ && ( !error2. source . is_some_and ( |( index2, _) | index2 >= index)
177+ || !self . error_implied_by ( error2. predicate , error. predicate ) )
178+ {
179+ info ! ( "skipping `{}` (implied by `{}`)" , error. predicate, error2. predicate) ;
180+ is_suppressed[ index] = true ;
181+ break ;
182+ }
158183
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- }
184+ // Also suppress the error if we are absolutely certain that a different
185+ // error is the one that the user should fix. This will suppress errors
186+ // about `<T as Pointee>::Metadata == ()` that can be fixed by `T: Sized`.
187+ if error. predicate . to_opt_poly_projection_pred ( ) . is_some ( )
188+ && error2. predicate . to_opt_poly_trait_pred ( ) . is_some ( )
189+ && self . error_fixed_by (
190+ error_source. obligation . clone ( ) ,
191+ error2. predicate . expect_clause ( ) ,
192+ )
193+ {
194+ info ! ( "skipping `{}` (fixed by `{}`)" , error. predicate, error2. predicate) ;
195+ is_suppressed[ index] = true ;
196+ break ;
167197 }
168198 }
169199 }
170200 }
171201
172- let mut reported = None ;
173-
174202 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 ) ;
203+ for ( error, & suppressed) in iter:: zip ( & errors, & is_suppressed) {
204+ let span = error. obligation . cause . span ;
205+ if suppressed || span. from_expansion ( ) != from_expansion {
206+ continue ;
192207 }
208+
209+ let guar = self . report_fulfillment_error ( error) ;
210+ reported = Some ( guar) ;
211+
212+ self . reported_trait_errors
213+ . borrow_mut ( )
214+ . entry ( span)
215+ . or_insert_with ( || ( vec ! [ ] , guar) )
216+ . 0
217+ . push ( error. obligation . predicate ) ;
193218 }
194219 }
195220
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" ) )
221+ // If all errors are suppressed, then we must have reported at least one error
222+ // from a previous call to this function.
223+ reported. unwrap_or_else ( || bug ! ( "failed to report fulfillment errors" ) )
200224 }
201225
202226 /// Reports that an overflow has occurred and halts compilation. We
@@ -1465,10 +1489,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
14651489 && self . can_eq ( param_env, goal. term , assumption. term )
14661490 }
14671491
1468- // returns if `cond` not occurring implies that `error` does not occur - i.e., that
1469- // `error` occurring implies that `cond` occurs.
1492+ /// Returns whether `cond` not occurring implies that `error` does not occur - i.e., that
1493+ /// `error` occurring implies that `cond` occurs.
14701494 #[ instrument( level = "debug" , skip( self ) , ret) ]
1471- fn error_implies ( & self , cond : ty:: Predicate < ' tcx > , error : ty:: Predicate < ' tcx > ) -> bool {
1495+ fn error_implied_by ( & self , error : ty:: Predicate < ' tcx > , cond : ty:: Predicate < ' tcx > ) -> bool {
14721496 if cond == error {
14731497 return true ;
14741498 }
@@ -1490,6 +1514,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
14901514 }
14911515 }
14921516
1517+ /// Returns whether fixing `cond` will also fix `error`.
1518+ #[ instrument( level = "debug" , skip( self ) , ret) ]
1519+ fn error_fixed_by ( & self , mut error : PredicateObligation < ' tcx > , cond : ty:: Clause < ' tcx > ) -> bool {
1520+ self . probe ( |_| {
1521+ let ocx = ObligationCtxt :: new ( self ) ;
1522+
1523+ let clauses = elaborate ( self . tcx , std:: iter:: once ( cond) ) . collect :: < Vec < _ > > ( ) ;
1524+ let clauses = ocx. normalize ( & error. cause , error. param_env , clauses) ;
1525+ let mut clauses = self . resolve_vars_if_possible ( clauses) ;
1526+
1527+ if clauses. has_infer ( ) {
1528+ return false ;
1529+ }
1530+
1531+ clauses. extend ( error. param_env . caller_bounds ( ) ) ;
1532+ let clauses = self . tcx . mk_clauses ( & clauses) ;
1533+ error. param_env = ty:: ParamEnv :: new ( clauses, error. param_env . reveal ( ) ) ;
1534+
1535+ ocx. register_obligation ( error) ;
1536+ ocx. select_all_or_error ( ) . is_empty ( )
1537+ } )
1538+ }
1539+
14931540 #[ instrument( skip( self ) , level = "debug" ) ]
14941541 fn report_fulfillment_error ( & self , error : & FulfillmentError < ' tcx > ) -> ErrorGuaranteed {
14951542 if self . tcx . sess . opts . unstable_opts . next_solver . map ( |c| c. dump_tree ) . unwrap_or_default ( )
0 commit comments