@@ -4,13 +4,12 @@ use rustc_errors::struct_span_code_err;
4
4
use rustc_hir as hir;
5
5
use rustc_hir:: def:: { DefKind , Res } ;
6
6
use rustc_lint_defs:: builtin:: UNUSED_ASSOCIATED_TYPE_BOUNDS ;
7
- use rustc_middle:: span_bug;
8
7
use rustc_middle:: ty:: fold:: BottomUpFolder ;
9
8
use rustc_middle:: ty:: {
10
9
self , DynKind , ExistentialPredicateStableCmpExt as _, Ty , TyCtxt , TypeFoldable ,
11
10
TypeVisitableExt , Upcast ,
12
11
} ;
13
- use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span } ;
12
+ use rustc_span:: { ErrorGuaranteed , Span } ;
14
13
use rustc_trait_selection:: error_reporting:: traits:: report_dyn_incompatibility;
15
14
use rustc_trait_selection:: traits:: { self , hir_ty_lowering_dyn_compatibility_violations} ;
16
15
use rustc_type_ir:: elaborate:: ClauseWithSupertraitSpan ;
@@ -30,16 +29,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
30
29
& self ,
31
30
span : Span ,
32
31
hir_id : hir:: HirId ,
33
- hir_trait_bounds : & [ hir:: PolyTraitRef < ' tcx > ] ,
32
+ hir_bounds : & [ hir:: PolyTraitRef < ' tcx > ] ,
34
33
lifetime : & hir:: Lifetime ,
35
34
representation : DynKind ,
36
35
) -> Ty < ' tcx > {
37
36
let tcx = self . tcx ( ) ;
37
+ let dummy_self = tcx. types . trait_object_dummy_self ;
38
38
39
- let mut bounds = Bounds :: default ( ) ;
39
+ let mut user_written_bounds = Bounds :: default ( ) ;
40
40
let mut potential_assoc_types = Vec :: new ( ) ;
41
- let dummy_self = self . tcx ( ) . types . trait_object_dummy_self ;
42
- for trait_bound in hir_trait_bounds. iter ( ) . rev ( ) {
41
+ for trait_bound in hir_bounds. iter ( ) {
43
42
if let hir:: BoundPolarity :: Maybe ( _) = trait_bound. modifiers . polarity {
44
43
continue ;
45
44
}
@@ -53,92 +52,67 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
53
52
hir:: BoundConstness :: Never ,
54
53
hir:: BoundPolarity :: Positive ,
55
54
dummy_self,
56
- & mut bounds ,
55
+ & mut user_written_bounds ,
57
56
PredicateFilter :: SelfOnly ,
58
57
) {
59
58
potential_assoc_types. extend ( cur_potential_assoc_types) ;
60
59
}
61
60
}
62
61
63
- let mut trait_bounds = vec ! [ ] ;
64
- let mut projection_bounds = vec ! [ ] ;
65
- for ( pred, span) in bounds. clauses ( ) {
66
- let bound_pred = pred. kind ( ) ;
67
- match bound_pred. skip_binder ( ) {
68
- ty:: ClauseKind :: Trait ( trait_pred) => {
69
- assert_eq ! ( trait_pred. polarity, ty:: PredicatePolarity :: Positive ) ;
70
- trait_bounds. push ( ( bound_pred. rebind ( trait_pred. trait_ref ) , span) ) ;
71
- }
72
- ty:: ClauseKind :: Projection ( proj) => {
73
- projection_bounds. push ( ( bound_pred. rebind ( proj) , span) ) ;
74
- }
75
- ty:: ClauseKind :: TypeOutlives ( _) => {
76
- // Do nothing, we deal with regions separately
77
- }
78
- ty:: ClauseKind :: RegionOutlives ( _)
79
- | ty:: ClauseKind :: ConstArgHasType ( ..)
80
- | ty:: ClauseKind :: WellFormed ( _)
81
- | ty:: ClauseKind :: ConstEvaluatable ( _)
82
- | ty:: ClauseKind :: HostEffect ( ..) => {
83
- span_bug ! ( span, "did not expect {pred} clause in object bounds" ) ;
84
- }
85
- }
86
- }
87
-
88
- // Expand trait aliases recursively and check that only one regular (non-auto) trait
89
- // is used and no 'maybe' bounds are used.
90
- let expanded_traits =
91
- traits:: expand_trait_aliases ( tcx, trait_bounds. iter ( ) . map ( |& ( a, b) | ( a, b) ) ) ;
92
-
93
- let ( mut auto_traits, regular_traits) : ( Vec < _ > , Vec < _ > ) =
94
- expanded_traits. partition ( |i| tcx. trait_is_auto ( i. trait_ref ( ) . def_id ( ) ) ) ;
62
+ let ( trait_bounds, mut projection_bounds) =
63
+ traits:: expand_trait_aliases ( tcx, user_written_bounds. clauses ( ) ) ;
64
+ let ( regular_traits, mut auto_traits) : ( Vec < _ > , Vec < _ > ) = trait_bounds
65
+ . into_iter ( )
66
+ . partition ( |( trait_ref, _) | !tcx. trait_is_auto ( trait_ref. def_id ( ) ) ) ;
95
67
68
+ // We don't support empty trait objects.
69
+ if regular_traits. is_empty ( ) && auto_traits. is_empty ( ) {
70
+ let guar =
71
+ self . report_trait_object_with_no_traits_error ( span, user_written_bounds. clauses ( ) ) ;
72
+ return Ty :: new_error ( tcx, guar) ;
73
+ }
96
74
// We don't support >1 principal
97
75
if regular_traits. len ( ) > 1 {
98
76
let guar = self . report_trait_object_addition_traits_error ( & regular_traits) ;
99
77
return Ty :: new_error ( tcx, guar) ;
100
78
}
101
- // We don't support empty trait objects.
102
- if regular_traits. is_empty ( ) && auto_traits. is_empty ( ) {
103
- let guar = self . report_trait_object_with_no_traits_error ( span, & trait_bounds) ;
104
- return Ty :: new_error ( tcx, guar) ;
105
- }
106
79
// Don't create a dyn trait if we have errors in the principal.
107
- if let Err ( guar) = trait_bounds . error_reported ( ) {
80
+ if let Err ( guar) = regular_traits . error_reported ( ) {
108
81
return Ty :: new_error ( tcx, guar) ;
109
82
}
110
83
111
84
// Check that there are no gross dyn-compatibility violations;
112
85
// most importantly, that the supertraits don't contain `Self`,
113
86
// to avoid ICEs.
114
- for item in & regular_traits {
115
- let violations =
116
- hir_ty_lowering_dyn_compatibility_violations ( tcx, item. trait_ref ( ) . def_id ( ) ) ;
117
- if !violations. is_empty ( ) {
118
- let reported = report_dyn_incompatibility (
119
- tcx,
120
- span,
121
- Some ( hir_id) ,
122
- item. trait_ref ( ) . def_id ( ) ,
123
- & violations,
124
- )
125
- . emit ( ) ;
126
- return Ty :: new_error ( tcx, reported) ;
87
+ for ( clause, span) in user_written_bounds. clauses ( ) {
88
+ if let Some ( trait_pred) = clause. as_trait_clause ( ) {
89
+ let violations =
90
+ hir_ty_lowering_dyn_compatibility_violations ( tcx, trait_pred. def_id ( ) ) ;
91
+ if !violations. is_empty ( ) {
92
+ let reported = report_dyn_incompatibility (
93
+ tcx,
94
+ span,
95
+ Some ( hir_id) ,
96
+ trait_pred. def_id ( ) ,
97
+ & violations,
98
+ )
99
+ . emit ( ) ;
100
+ return Ty :: new_error ( tcx, reported) ;
101
+ }
127
102
}
128
103
}
129
104
130
- let mut needed_associated_types = FxIndexSet :: default ( ) ;
131
-
132
- let principal_span = regular_traits. first ( ) . map_or ( DUMMY_SP , |info| info. bottom ( ) . 1 ) ;
133
- let regular_traits_refs_spans = trait_bounds
134
- . into_iter ( )
135
- . filter ( |( trait_ref, _) | !tcx. trait_is_auto ( trait_ref. def_id ( ) ) ) ;
105
+ let principal_trait = regular_traits. into_iter ( ) . next ( ) ;
136
106
137
- for ( base_trait_ref, original_span) in regular_traits_refs_spans {
138
- let base_pred: ty:: Predicate < ' tcx > = base_trait_ref. upcast ( tcx) ;
107
+ let mut needed_associated_types = FxIndexSet :: default ( ) ;
108
+ if let Some ( ( principal_trait, spans) ) = & principal_trait {
109
+ let pred: ty:: Predicate < ' tcx > = ( * principal_trait) . upcast ( tcx) ;
139
110
for ClauseWithSupertraitSpan { pred, supertrait_span } in
140
- traits:: elaborate ( tcx, [ ClauseWithSupertraitSpan :: new ( base_pred, original_span) ] )
141
- . filter_only_self ( )
111
+ traits:: elaborate ( tcx, [ ClauseWithSupertraitSpan :: new (
112
+ pred,
113
+ * spans. last ( ) . unwrap ( ) ,
114
+ ) ] )
115
+ . filter_only_self ( )
142
116
{
143
117
debug ! ( "observing object predicate `{pred:?}`" ) ;
144
118
@@ -188,12 +162,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
188
162
// the discussion in #56288 for alternatives.
189
163
if !references_self {
190
164
// Include projections defined on supertraits.
191
- projection_bounds. push ( ( pred, original_span ) ) ;
165
+ projection_bounds. push ( ( pred, supertrait_span ) ) ;
192
166
}
193
167
194
168
self . check_elaborated_projection_mentions_input_lifetimes (
195
169
pred,
196
- original_span ,
170
+ * spans . first ( ) . unwrap ( ) ,
197
171
supertrait_span,
198
172
) ;
199
173
}
@@ -206,7 +180,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
206
180
// So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated
207
181
// types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a
208
182
// corresponding `Projection` clause
209
- for ( projection_bound, span) in & projection_bounds {
183
+ for & ( projection_bound, span) in & projection_bounds {
210
184
let def_id = projection_bound. item_def_id ( ) ;
211
185
let trait_ref = tcx. anonymize_bound_vars (
212
186
projection_bound. map_bound ( |p| p. projection_term . trait_ref ( tcx) ) ,
@@ -216,17 +190,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
216
190
tcx. emit_node_span_lint (
217
191
UNUSED_ASSOCIATED_TYPE_BOUNDS ,
218
192
hir_id,
219
- * span,
220
- crate :: errors:: UnusedAssociatedTypeBounds { span : * span } ,
193
+ span,
194
+ crate :: errors:: UnusedAssociatedTypeBounds { span } ,
221
195
) ;
222
196
}
223
197
}
224
198
225
199
if let Err ( guar) = self . check_for_required_assoc_tys (
226
- principal_span ,
200
+ principal_trait . as_ref ( ) . map_or ( smallvec ! [ ] , | ( _ , spans ) | spans . clone ( ) ) ,
227
201
needed_associated_types,
228
202
potential_assoc_types,
229
- hir_trait_bounds ,
203
+ hir_bounds ,
230
204
) {
231
205
return Ty :: new_error ( tcx, guar) ;
232
206
}
@@ -236,15 +210,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
236
210
// We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering
237
211
// the bounds
238
212
let mut duplicates = FxHashSet :: default ( ) ;
239
- auto_traits. retain ( |i| duplicates. insert ( i. trait_ref ( ) . def_id ( ) ) ) ;
240
- debug ! ( ?regular_traits) ;
213
+ auto_traits. retain ( |( trait_pred, _) | duplicates. insert ( trait_pred. def_id ( ) ) ) ;
214
+
215
+ debug ! ( ?principal_trait) ;
241
216
debug ! ( ?auto_traits) ;
242
217
243
218
// Erase the `dummy_self` (`trait_object_dummy_self`) used above.
244
- let existential_trait_refs = regular_traits. iter ( ) . map ( |i| {
245
- i. trait_ref ( ) . map_bound ( |trait_ref : ty:: TraitRef < ' tcx > | {
219
+ let principal_trait_ref = principal_trait. map ( |( trait_pred, spans) | {
220
+ trait_pred. map_bound ( |trait_pred| {
221
+ let trait_ref = trait_pred. trait_ref ;
222
+ assert_eq ! ( trait_pred. polarity, ty:: PredicatePolarity :: Positive ) ;
246
223
assert_eq ! ( trait_ref. self_ty( ) , dummy_self) ;
247
224
225
+ let span = * spans. first ( ) . unwrap ( ) ;
226
+
248
227
// Verify that `dummy_self` did not leak inside default type parameters. This
249
228
// could not be done at path creation, since we need to see through trait aliases.
250
229
let mut missing_type_params = vec ! [ ] ;
@@ -254,7 +233,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
254
233
. args
255
234
. iter ( )
256
235
. enumerate ( )
257
- . skip ( 1 ) // Remove `Self` for `ExistentialPredicate`.
236
+ // Skip `Self`
237
+ . skip ( 1 )
258
238
. map ( |( index, arg) | {
259
239
if arg == dummy_self. into ( ) {
260
240
let param = & generics. own_params [ index] ;
@@ -273,8 +253,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
273
253
} )
274
254
. collect ( ) ;
275
255
276
- let span = i. bottom ( ) . 1 ;
277
- let empty_generic_args = hir_trait_bounds. iter ( ) . any ( |hir_bound| {
256
+ let empty_generic_args = hir_bounds. iter ( ) . any ( |hir_bound| {
278
257
hir_bound. trait_ref . path . res == Res :: Def ( DefKind :: Trait , trait_ref. def_id )
279
258
&& hir_bound. span . contains ( span)
280
259
} ) ;
@@ -285,26 +264,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
285
264
empty_generic_args,
286
265
) ;
287
266
288
- if references_self {
289
- let def_id = i. bottom ( ) . 0 . def_id ( ) ;
290
- struct_span_code_err ! (
291
- self . dcx( ) ,
292
- i. bottom( ) . 1 ,
293
- E0038 ,
294
- "the {} `{}` cannot be made into an object" ,
295
- tcx. def_descr( def_id) ,
296
- tcx. item_name( def_id) ,
297
- )
298
- . with_note (
299
- rustc_middle:: traits:: DynCompatibilityViolation :: SupertraitSelf (
300
- smallvec ! [ ] ,
301
- )
302
- . error_msg ( ) ,
303
- )
304
- . emit ( ) ;
305
- }
306
-
307
- ty:: ExistentialTraitRef :: new ( tcx, trait_ref. def_id , args)
267
+ ty:: ExistentialPredicate :: Trait ( ty:: ExistentialTraitRef :: new (
268
+ tcx,
269
+ trait_ref. def_id ,
270
+ args,
271
+ ) )
308
272
} )
309
273
} ) ;
310
274
@@ -327,21 +291,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
327
291
b. projection_term = replace_dummy_self_with_error ( tcx, b. projection_term , guar) ;
328
292
}
329
293
330
- ty:: ExistentialProjection :: erase_self_ty ( tcx, b)
294
+ ty:: ExistentialPredicate :: Projection ( ty:: ExistentialProjection :: erase_self_ty (
295
+ tcx, b,
296
+ ) )
331
297
} )
332
298
} ) ;
333
299
334
- let regular_trait_predicates = existential_trait_refs
335
- . map ( |trait_ref| trait_ref. map_bound ( ty:: ExistentialPredicate :: Trait ) ) ;
336
- let auto_trait_predicates = auto_traits. into_iter ( ) . map ( |trait_ref| {
337
- ty:: Binder :: dummy ( ty:: ExistentialPredicate :: AutoTrait ( trait_ref. trait_ref ( ) . def_id ( ) ) )
300
+ let auto_trait_predicates = auto_traits. into_iter ( ) . map ( |( trait_pred, _) | {
301
+ assert_eq ! ( trait_pred. polarity( ) , ty:: PredicatePolarity :: Positive ) ;
302
+ assert_eq ! ( trait_pred. self_ty( ) . skip_binder( ) , dummy_self) ;
303
+
304
+ ty:: Binder :: dummy ( ty:: ExistentialPredicate :: AutoTrait ( trait_pred. def_id ( ) ) )
338
305
} ) ;
306
+
339
307
// N.b. principal, projections, auto traits
340
308
// FIXME: This is actually wrong with multiple principals in regards to symbol mangling
341
- let mut v = regular_trait_predicates
342
- . chain (
343
- existential_projections. map ( |x| x. map_bound ( ty:: ExistentialPredicate :: Projection ) ) ,
344
- )
309
+ let mut v = principal_trait_ref
310
+ . into_iter ( )
311
+ . chain ( existential_projections)
345
312
. chain ( auto_trait_predicates)
346
313
. collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
347
314
v. sort_by ( |a, b| a. skip_binder ( ) . stable_cmp ( tcx, & b. skip_binder ( ) ) ) ;
0 commit comments