@@ -3,15 +3,14 @@ use rustc_errors::codes::*;
33use rustc_errors:: struct_span_code_err;
44use rustc_hir as hir;
55use rustc_hir:: def:: { DefKind , Res } ;
6- use rustc_hir:: def_id:: DefId ;
76use rustc_lint_defs:: builtin:: UNUSED_ASSOCIATED_TYPE_BOUNDS ;
87use rustc_middle:: span_bug;
98use rustc_middle:: ty:: fold:: BottomUpFolder ;
109use rustc_middle:: ty:: {
1110 self , DynKind , ExistentialPredicateStableCmpExt as _, Ty , TyCtxt , TypeFoldable ,
1211 TypeVisitableExt , Upcast ,
1312} ;
14- use rustc_span:: { ErrorGuaranteed , Span } ;
13+ use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span } ;
1514use rustc_trait_selection:: error_reporting:: traits:: report_dyn_incompatibility;
1615use rustc_trait_selection:: traits:: { self , hir_ty_lowering_dyn_compatibility_violations} ;
1716use rustc_type_ir:: elaborate:: ClauseWithSupertraitSpan ;
@@ -62,7 +61,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
6261 }
6362
6463 let mut trait_bounds = vec ! [ ] ;
65- let mut projection_bounds = vec ! [ ] ;
64+ let mut projection_bounds = FxIndexMap :: default ( ) ;
6665 for ( pred, span) in bounds. clauses ( ) {
6766 let bound_pred = pred. kind ( ) ;
6867 match bound_pred. skip_binder ( ) {
@@ -71,7 +70,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
7170 trait_bounds. push ( ( bound_pred. rebind ( trait_pred. trait_ref ) , span) ) ;
7271 }
7372 ty:: ClauseKind :: Projection ( proj) => {
74- projection_bounds. push ( ( bound_pred. rebind ( proj) , span) ) ;
73+ let anon = tcx. anonymize_bound_vars ( bound_pred. rebind ( proj) ) ;
74+ projection_bounds. insert ( anon, ( bound_pred. rebind ( proj) , span) ) ;
7575 }
7676 ty:: ClauseKind :: TypeOutlives ( _) => {
7777 // Do nothing, we deal with regions separately
@@ -88,8 +88,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
8888
8989 // Expand trait aliases recursively and check that only one regular (non-auto) trait
9090 // is used and no 'maybe' bounds are used.
91- let expanded_traits =
92- traits:: expand_trait_aliases ( tcx, trait_bounds. iter ( ) . map ( |& ( a, b) | ( a, b) ) ) ;
91+ let mut trait_alias_projection_bounds = FxIndexSet :: default ( ) ;
92+ let expanded_traits = traits:: expand_trait_aliases (
93+ tcx,
94+ & mut trait_alias_projection_bounds,
95+ trait_bounds. iter ( ) . map ( |& ( a, b) | ( a, b) ) ,
96+ ) ;
9397
9498 let ( mut auto_traits, regular_traits) : ( Vec < _ > , Vec < _ > ) =
9599 expanded_traits. partition ( |i| tcx. trait_is_auto ( i. trait_ref ( ) . def_id ( ) ) ) ;
@@ -128,12 +132,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
128132 }
129133 }
130134
131- let mut associated_types : FxIndexMap < Span , FxIndexSet < DefId > > = FxIndexMap :: default ( ) ;
135+ let mut needed_associated_types = FxIndexSet :: default ( ) ;
132136
137+ let principal_span = regular_traits. first ( ) . map_or ( DUMMY_SP , |info| info. bottom ( ) . 1 ) ;
133138 let regular_traits_refs_spans = trait_bounds
134139 . into_iter ( )
135140 . filter ( |( trait_ref, _) | !tcx. trait_is_auto ( trait_ref. def_id ( ) ) ) ;
136141
142+ let mut implied_projection_bounds = vec ! [ ] ;
137143 for ( base_trait_ref, original_span) in regular_traits_refs_spans {
138144 let base_pred: ty:: Predicate < ' tcx > = base_trait_ref. upcast ( tcx) ;
139145 for ClauseWithSupertraitSpan { pred, supertrait_span } in
@@ -145,17 +151,28 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
145151 let bound_predicate = pred. kind ( ) ;
146152 match bound_predicate. skip_binder ( ) {
147153 ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) => {
148- let pred = bound_predicate. rebind ( pred) ;
149- associated_types. entry ( original_span) . or_default ( ) . extend (
150- tcx. associated_items ( pred. def_id ( ) )
154+ // FIXME(negative_bounds): Handle this correctly...
155+ let trait_ref =
156+ tcx. anonymize_bound_vars ( bound_predicate. rebind ( pred. trait_ref ) ) ;
157+ needed_associated_types. extend (
158+ tcx. associated_items ( trait_ref. def_id ( ) )
151159 . in_definition_order ( )
152160 . filter ( |item| item. kind == ty:: AssocKind :: Type )
153161 . filter ( |item| !item. is_impl_trait_in_trait ( ) )
154- . map ( |item| item. def_id ) ,
162+ // If the associated type has a `where Self: Sized` bound,
163+ // we do not need to constrain the associated type.
164+ . filter ( |item| !tcx. generics_require_sized_self ( item. def_id ) )
165+ . map ( |item| ( item. def_id , trait_ref) ) ,
155166 ) ;
156167 }
157168 ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( pred) ) => {
158169 let pred = bound_predicate. rebind ( pred) ;
170+
171+ let pred_key = tcx. anonymize_bound_vars ( pred) ;
172+ if !trait_alias_projection_bounds. contains ( & pred_key) {
173+ projection_bounds. shift_remove ( & pred_key) ;
174+ }
175+
159176 // A `Self` within the original bound will be instantiated with a
160177 // `trait_object_dummy_self`, so check for that.
161178 let references_self = match pred. skip_binder ( ) . term . unpack ( ) {
@@ -182,8 +199,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
182199 // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
183200 // the discussion in #56288 for alternatives.
184201 if !references_self {
185- // Include projections defined on supertraits.
186- projection_bounds. push ( ( pred, original_span) ) ;
202+ if trait_alias_projection_bounds. contains ( & pred_key) {
203+ // Include projections defined on supertraits.
204+ projection_bounds. insert ( pred_key, ( pred, supertrait_span) ) ;
205+ } else {
206+ // Include projections defined on supertraits.
207+ implied_projection_bounds. push ( pred) ;
208+ }
187209 }
188210
189211 self . check_elaborated_projection_mentions_input_lifetimes (
@@ -201,26 +223,32 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
201223 // So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated
202224 // types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a
203225 // corresponding `Projection` clause
204- for def_ids in associated_types. values_mut ( ) {
205- for ( projection_bound, span) in & projection_bounds {
206- let def_id = projection_bound. projection_def_id ( ) ;
207- def_ids. swap_remove ( & def_id) ;
208- if tcx. generics_require_sized_self ( def_id) {
209- tcx. emit_node_span_lint (
210- UNUSED_ASSOCIATED_TYPE_BOUNDS ,
211- hir_id,
212- * span,
213- crate :: errors:: UnusedAssociatedTypeBounds { span : * span } ,
214- ) ;
215- }
226+ for ( projection_bound, span) in projection_bounds. values ( ) {
227+ let def_id = projection_bound. projection_def_id ( ) ;
228+ let trait_ref = tcx. anonymize_bound_vars (
229+ projection_bound. map_bound ( |p| p. projection_term . trait_ref ( tcx) ) ,
230+ ) ;
231+ needed_associated_types. swap_remove ( & ( def_id, trait_ref) ) ;
232+ if tcx. generics_require_sized_self ( def_id) {
233+ tcx. emit_node_span_lint (
234+ UNUSED_ASSOCIATED_TYPE_BOUNDS ,
235+ hir_id,
236+ * span,
237+ crate :: errors:: UnusedAssociatedTypeBounds { span : * span } ,
238+ ) ;
216239 }
217- // If the associated type has a `where Self: Sized` bound, we do not need to constrain the associated
218- // type in the `dyn Trait`.
219- def_ids. retain ( |def_id| !tcx. generics_require_sized_self ( def_id) ) ;
240+ }
241+ for projection_bound in & implied_projection_bounds {
242+ let def_id = projection_bound. projection_def_id ( ) ;
243+ let trait_ref = tcx. anonymize_bound_vars (
244+ projection_bound. map_bound ( |p| p. projection_term . trait_ref ( tcx) ) ,
245+ ) ;
246+ needed_associated_types. swap_remove ( & ( def_id, trait_ref) ) ;
220247 }
221248
222249 self . complain_about_missing_assoc_tys (
223- associated_types,
250+ principal_span,
251+ needed_associated_types,
224252 potential_assoc_types,
225253 hir_trait_bounds,
226254 ) ;
@@ -302,7 +330,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
302330 } )
303331 } ) ;
304332
305- let existential_projections = projection_bounds. iter ( ) . map ( |( bound, _) | {
333+ let existential_projections = projection_bounds. values ( ) . map ( |( bound, _) | {
306334 bound. map_bound ( |mut b| {
307335 assert_eq ! ( b. projection_term. self_ty( ) , dummy_self) ;
308336
0 commit comments