1- use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
1+ use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
22use rustc_errors:: codes:: * ;
33use rustc_errors:: struct_span_code_err;
44use rustc_hir as hir;
@@ -58,9 +58,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
5858 }
5959 }
6060
61- let ( trait_bounds , mut projection_bounds ) =
61+ let ( elaborated_trait_bounds , elaborated_projection_bounds ) =
6262 traits:: expand_trait_aliases ( tcx, user_written_bounds. iter ( ) . copied ( ) ) ;
63- let ( regular_traits, mut auto_traits) : ( Vec < _ > , Vec < _ > ) = trait_bounds
63+ let ( regular_traits, mut auto_traits) : ( Vec < _ > , Vec < _ > ) = elaborated_trait_bounds
6464 . into_iter ( )
6565 . partition ( |( trait_ref, _) | !tcx. trait_is_auto ( trait_ref. def_id ( ) ) ) ;
6666
@@ -103,37 +103,89 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
103103 }
104104 }
105105
106+ // Map the projection bounds onto a key that makes it easy to remove redundant
107+ // bounds that are constrained by supertraits of the principal def id.
108+ //
109+ // Also make sure we detect conflicting bounds from expanding a trait alias and
110+ // also specifying it manually, like:
111+ // ```
112+ // type Alias = Trait<Assoc = i32>;
113+ // let _: &dyn Alias<Assoc = u32> = /* ... */;
114+ // ```
115+ let mut projection_bounds = FxIndexMap :: default ( ) ;
116+ for ( proj, proj_span) in elaborated_projection_bounds {
117+ let key = (
118+ proj. skip_binder ( ) . projection_term . def_id ,
119+ tcx. anonymize_bound_vars (
120+ proj. map_bound ( |proj| proj. projection_term . trait_ref ( tcx) ) ,
121+ ) ,
122+ ) ;
123+ if let Some ( ( old_proj, old_proj_span) ) =
124+ projection_bounds. insert ( key, ( proj, proj_span) )
125+ && tcx. anonymize_bound_vars ( proj) != tcx. anonymize_bound_vars ( old_proj)
126+ {
127+ let item = tcx. item_name ( proj. item_def_id ( ) ) ;
128+ self . dcx ( )
129+ . struct_span_err (
130+ span,
131+ format ! (
132+ "conflicting associated type bounds for `{item}` when \
133+ expanding trait alias"
134+ ) ,
135+ )
136+ . with_span_label (
137+ old_proj_span,
138+ format ! ( "`{item}` is specified to be `{}` here" , old_proj. term( ) ) ,
139+ )
140+ . with_span_label (
141+ proj_span,
142+ format ! ( "`{item}` is specified to be `{}` here" , proj. term( ) ) ,
143+ )
144+ . emit ( ) ;
145+ }
146+ }
147+
106148 let principal_trait = regular_traits. into_iter ( ) . next ( ) ;
107149
108- let mut needed_associated_types = FxIndexSet :: default ( ) ;
109- if let Some ( ( principal_trait, spans) ) = & principal_trait {
110- let pred: ty:: Predicate < ' tcx > = ( * principal_trait) . upcast ( tcx) ;
111- for ClauseWithSupertraitSpan { pred, supertrait_span } in traits:: elaborate (
150+ let mut needed_associated_types = vec ! [ ] ;
151+ if let Some ( ( principal_trait, ref spans) ) = principal_trait {
152+ let principal_trait = principal_trait. map_bound ( |trait_pred| {
153+ assert_eq ! ( trait_pred. polarity, ty:: PredicatePolarity :: Positive ) ;
154+ trait_pred. trait_ref
155+ } ) ;
156+
157+ for ClauseWithSupertraitSpan { clause, supertrait_span } in traits:: elaborate (
112158 tcx,
113- [ ClauseWithSupertraitSpan :: new ( pred, * spans. last ( ) . unwrap ( ) ) ] ,
159+ [ ClauseWithSupertraitSpan :: new (
160+ ty:: TraitRef :: identity ( tcx, principal_trait. def_id ( ) ) . upcast ( tcx) ,
161+ * spans. last ( ) . unwrap ( ) ,
162+ ) ] ,
114163 )
115164 . filter_only_self ( )
116165 {
117- debug ! ( "observing object predicate `{pred:?}`" ) ;
166+ let clause = clause. instantiate_supertrait ( tcx, principal_trait) ;
167+ debug ! ( "observing object predicate `{clause:?}`" ) ;
118168
119- let bound_predicate = pred . kind ( ) ;
169+ let bound_predicate = clause . kind ( ) ;
120170 match bound_predicate. skip_binder ( ) {
121- ty:: PredicateKind :: Clause ( ty :: ClauseKind :: Trait ( pred) ) => {
171+ ty:: ClauseKind :: Trait ( pred) => {
122172 // FIXME(negative_bounds): Handle this correctly...
123173 let trait_ref =
124174 tcx. anonymize_bound_vars ( bound_predicate. rebind ( pred. trait_ref ) ) ;
125175 needed_associated_types. extend (
126- tcx. associated_items ( trait_ref. def_id ( ) )
176+ tcx. associated_items ( pred . trait_ref . def_id )
127177 . in_definition_order ( )
178+ // We only care about associated types.
128179 . filter ( |item| item. kind == ty:: AssocKind :: Type )
180+ // No RPITITs -- even with `async_fn_in_dyn_trait`, they are implicit.
129181 . filter ( |item| !item. is_impl_trait_in_trait ( ) )
130182 // If the associated type has a `where Self: Sized` bound,
131183 // we do not need to constrain the associated type.
132184 . filter ( |item| !tcx. generics_require_sized_self ( item. def_id ) )
133185 . map ( |item| ( item. def_id , trait_ref) ) ,
134186 ) ;
135187 }
136- ty:: PredicateKind :: Clause ( ty :: ClauseKind :: Projection ( pred) ) => {
188+ ty:: ClauseKind :: Projection ( pred) => {
137189 let pred = bound_predicate. rebind ( pred) ;
138190 // A `Self` within the original bound will be instantiated with a
139191 // `trait_object_dummy_self`, so check for that.
@@ -161,8 +213,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
161213 // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
162214 // the discussion in #56288 for alternatives.
163215 if !references_self {
164- // Include projections defined on supertraits.
165- projection_bounds. push ( ( pred, supertrait_span) ) ;
216+ let key = (
217+ pred. skip_binder ( ) . projection_term . def_id ,
218+ tcx. anonymize_bound_vars (
219+ pred. map_bound ( |proj| proj. projection_term . trait_ref ( tcx) ) ,
220+ ) ,
221+ ) ;
222+ if !projection_bounds. contains_key ( & key) {
223+ projection_bounds. insert ( key, ( pred, supertrait_span) ) ;
224+ }
166225 }
167226
168227 self . check_elaborated_projection_mentions_input_lifetimes (
@@ -182,12 +241,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
182241 // types that we expect to be provided by the user, so the following loop
183242 // removes all the associated types that have a corresponding `Projection`
184243 // clause, either from expanding trait aliases or written by the user.
185- for & ( projection_bound, span) in & projection_bounds {
244+ for & ( projection_bound, span) in projection_bounds. values ( ) {
186245 let def_id = projection_bound. item_def_id ( ) ;
187- let trait_ref = tcx. anonymize_bound_vars (
188- projection_bound. map_bound ( |p| p. projection_term . trait_ref ( tcx) ) ,
189- ) ;
190- needed_associated_types. swap_remove ( & ( def_id, trait_ref) ) ;
191246 if tcx. generics_require_sized_self ( def_id) {
192247 tcx. emit_node_span_lint (
193248 UNUSED_ASSOCIATED_TYPE_BOUNDS ,
@@ -198,9 +253,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
198253 }
199254 }
200255
256+ let mut missing_assoc_types = FxIndexSet :: default ( ) ;
257+ let projection_bounds: Vec < _ > = needed_associated_types
258+ . into_iter ( )
259+ . filter_map ( |key| {
260+ if let Some ( assoc) = projection_bounds. get ( & key) {
261+ Some ( * assoc)
262+ } else {
263+ missing_assoc_types. insert ( key) ;
264+ None
265+ }
266+ } )
267+ . collect ( ) ;
268+
201269 if let Err ( guar) = self . check_for_required_assoc_tys (
202270 principal_trait. as_ref ( ) . map_or ( smallvec ! [ ] , |( _, spans) | spans. clone ( ) ) ,
203- needed_associated_types ,
271+ missing_assoc_types ,
204272 potential_assoc_types,
205273 hir_bounds,
206274 ) {
@@ -266,7 +334,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
266334 } )
267335 } ) ;
268336
269- let existential_projections = projection_bounds. iter ( ) . map ( |( bound, _) | {
337+ let existential_projections = projection_bounds. into_iter ( ) . map ( |( bound, _) | {
270338 bound. map_bound ( |mut b| {
271339 assert_eq ! ( b. projection_term. self_ty( ) , dummy_self) ;
272340
@@ -291,12 +359,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
291359 } )
292360 } ) ;
293361
294- let auto_trait_predicates = auto_traits. into_iter ( ) . map ( |( trait_pred, _) | {
295- assert_eq ! ( trait_pred. polarity( ) , ty:: PredicatePolarity :: Positive ) ;
296- assert_eq ! ( trait_pred. self_ty( ) . skip_binder( ) , dummy_self) ;
362+ let mut auto_trait_predicates: Vec < _ > = auto_traits
363+ . into_iter ( )
364+ . map ( |( trait_pred, _) | {
365+ assert_eq ! ( trait_pred. polarity( ) , ty:: PredicatePolarity :: Positive ) ;
366+ assert_eq ! ( trait_pred. self_ty( ) . skip_binder( ) , dummy_self) ;
297367
298- ty:: Binder :: dummy ( ty:: ExistentialPredicate :: AutoTrait ( trait_pred. def_id ( ) ) )
299- } ) ;
368+ ty:: Binder :: dummy ( ty:: ExistentialPredicate :: AutoTrait ( trait_pred. def_id ( ) ) )
369+ } )
370+ . collect ( ) ;
371+ auto_trait_predicates. dedup ( ) ;
300372
301373 // N.b. principal, projections, auto traits
302374 // FIXME: This is actually wrong with multiple principals in regards to symbol mangling
@@ -306,7 +378,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
306378 . chain ( auto_trait_predicates)
307379 . collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
308380 v. sort_by ( |a, b| a. skip_binder ( ) . stable_cmp ( tcx, & b. skip_binder ( ) ) ) ;
309- v. dedup ( ) ;
310381 let existential_predicates = tcx. mk_poly_existential_predicates ( & v) ;
311382
312383 // Use explicitly-specified region bound, unless the bound is missing.
0 commit comments