@@ -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 = 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" ) ;
62
+ // Check that there are no gross dyn-compatibility violations;
63
+ // most importantly, that the supertraits don't contain `Self`,
64
+ // to avoid ICEs.
65
+ for ( clause, span) in user_written_bounds. clauses ( ) {
66
+ if let Some ( trait_pred) = clause. as_trait_clause ( ) {
67
+ let violations =
68
+ hir_ty_lowering_dyn_compatibility_violations ( tcx, trait_pred. def_id ( ) ) ;
69
+ if !violations. is_empty ( ) {
70
+ let reported = report_dyn_incompatibility (
71
+ tcx,
72
+ span,
73
+ Some ( hir_id) ,
74
+ trait_pred. def_id ( ) ,
75
+ & violations,
76
+ )
77
+ . emit ( ) ;
78
+ return Ty :: new_error ( tcx, reported) ;
84
79
}
85
80
}
86
81
}
87
82
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 ( ) ) ) ;
83
+ let ( trait_bounds, mut projection_bounds) =
84
+ traits:: expand_trait_aliases ( tcx, user_written_bounds. clauses ( ) ) ;
85
+ let ( regular_traits, mut auto_traits) : ( Vec < _ > , Vec < _ > ) = trait_bounds
86
+ . into_iter ( )
87
+ . partition ( |( trait_ref, _) | !tcx. trait_is_auto ( trait_ref. def_id ( ) ) ) ;
95
88
89
+ // We don't support empty trait objects.
90
+ if regular_traits. is_empty ( ) && auto_traits. is_empty ( ) {
91
+ let guar =
92
+ self . report_trait_object_with_no_traits_error ( span, user_written_bounds. clauses ( ) ) ;
93
+ return Ty :: new_error ( tcx, guar) ;
94
+ }
96
95
// We don't support >1 principal
97
96
if regular_traits. len ( ) > 1 {
98
97
let guar = self . report_trait_object_addition_traits_error ( & regular_traits) ;
99
98
return Ty :: new_error ( tcx, guar) ;
100
99
}
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
100
// Don't create a dyn trait if we have errors in the principal.
107
- if let Err ( guar) = trait_bounds . error_reported ( ) {
101
+ if let Err ( guar) = regular_traits . error_reported ( ) {
108
102
return Ty :: new_error ( tcx, guar) ;
109
103
}
110
104
111
- // Check that there are no gross dyn-compatibility violations;
112
- // most importantly, that the supertraits don't contain `Self`,
113
- // 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) ;
127
- }
128
- }
105
+ let principal_trait = regular_traits. into_iter ( ) . next ( ) ;
129
106
130
107
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 ( ) ) ) ;
136
-
137
- for ( base_trait_ref, original_span) in regular_traits_refs_spans {
138
- let base_pred: ty:: Predicate < ' tcx > = base_trait_ref. upcast ( tcx) ;
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
@@ -186,12 +160,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
186
160
// the discussion in #56288 for alternatives.
187
161
if !references_self {
188
162
// Include projections defined on supertraits.
189
- projection_bounds. push ( ( pred, original_span ) ) ;
163
+ projection_bounds. push ( ( pred, supertrait_span ) ) ;
190
164
}
191
165
192
166
self . check_elaborated_projection_mentions_input_lifetimes (
193
167
pred,
194
- original_span ,
168
+ * spans . first ( ) . unwrap ( ) ,
195
169
supertrait_span,
196
170
) ;
197
171
}
@@ -204,24 +178,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
204
178
// So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated
205
179
// types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a
206
180
// corresponding `Projection` clause
207
- for ( projection_bound, span) in & projection_bounds {
181
+ for & ( projection_bound, span) in & projection_bounds {
208
182
let def_id = projection_bound. projection_def_id ( ) ;
209
183
needed_associated_types. swap_remove ( & def_id) ;
210
184
if tcx. generics_require_sized_self ( def_id) {
211
185
tcx. emit_node_span_lint (
212
186
UNUSED_ASSOCIATED_TYPE_BOUNDS ,
213
187
hir_id,
214
- * span,
215
- crate :: errors:: UnusedAssociatedTypeBounds { span : * span } ,
188
+ span,
189
+ crate :: errors:: UnusedAssociatedTypeBounds { span } ,
216
190
) ;
217
191
}
218
192
}
219
193
220
194
if let Err ( guar) = self . check_for_required_assoc_tys (
221
- principal_span ,
195
+ principal_trait . as_ref ( ) . map_or ( smallvec ! [ ] , | ( _ , spans ) | spans . clone ( ) ) ,
222
196
needed_associated_types,
223
197
potential_assoc_types,
224
- hir_trait_bounds ,
198
+ hir_bounds ,
225
199
) {
226
200
return Ty :: new_error ( tcx, guar) ;
227
201
}
@@ -231,15 +205,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
231
205
// We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering
232
206
// the bounds
233
207
let mut duplicates = FxHashSet :: default ( ) ;
234
- auto_traits. retain ( |i| duplicates. insert ( i. trait_ref ( ) . def_id ( ) ) ) ;
235
- debug ! ( ?regular_traits) ;
208
+ auto_traits. retain ( |( trait_pred, _) | duplicates. insert ( trait_pred. def_id ( ) ) ) ;
209
+
210
+ debug ! ( ?principal_trait) ;
236
211
debug ! ( ?auto_traits) ;
237
212
238
213
// Erase the `dummy_self` (`trait_object_dummy_self`) used above.
239
- let existential_trait_refs = regular_traits. iter ( ) . map ( |i| {
240
- i. trait_ref ( ) . map_bound ( |trait_ref : ty:: TraitRef < ' tcx > | {
214
+ let principal_trait_ref = principal_trait. map ( |( trait_pred, spans) | {
215
+ trait_pred. map_bound ( |trait_pred| {
216
+ let trait_ref = trait_pred. trait_ref ;
217
+ assert_eq ! ( trait_pred. polarity, ty:: PredicatePolarity :: Positive ) ;
241
218
assert_eq ! ( trait_ref. self_ty( ) , dummy_self) ;
242
219
220
+ let span = * spans. first ( ) . unwrap ( ) ;
221
+
243
222
// Verify that `dummy_self` did not leak inside default type parameters. This
244
223
// could not be done at path creation, since we need to see through trait aliases.
245
224
let mut missing_type_params = vec ! [ ] ;
@@ -249,7 +228,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
249
228
. args
250
229
. iter ( )
251
230
. enumerate ( )
252
- . skip ( 1 ) // Remove `Self` for `ExistentialPredicate`.
231
+ // Skip `Self`
232
+ . skip ( 1 )
253
233
. map ( |( index, arg) | {
254
234
if arg == dummy_self. into ( ) {
255
235
let param = & generics. own_params [ index] ;
@@ -268,8 +248,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
268
248
} )
269
249
. collect ( ) ;
270
250
271
- let span = i. bottom ( ) . 1 ;
272
- let empty_generic_args = hir_trait_bounds. iter ( ) . any ( |hir_bound| {
251
+ let empty_generic_args = hir_bounds. iter ( ) . any ( |hir_bound| {
273
252
hir_bound. trait_ref . path . res == Res :: Def ( DefKind :: Trait , trait_ref. def_id )
274
253
&& hir_bound. span . contains ( span)
275
254
} ) ;
@@ -280,26 +259,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
280
259
empty_generic_args,
281
260
) ;
282
261
283
- if references_self {
284
- let def_id = i. bottom ( ) . 0 . def_id ( ) ;
285
- struct_span_code_err ! (
286
- self . dcx( ) ,
287
- i. bottom( ) . 1 ,
288
- E0038 ,
289
- "the {} `{}` cannot be made into an object" ,
290
- tcx. def_descr( def_id) ,
291
- tcx. item_name( def_id) ,
292
- )
293
- . with_note (
294
- rustc_middle:: traits:: DynCompatibilityViolation :: SupertraitSelf (
295
- smallvec ! [ ] ,
296
- )
297
- . error_msg ( ) ,
298
- )
299
- . emit ( ) ;
300
- }
301
-
302
- ty:: ExistentialTraitRef :: new ( tcx, trait_ref. def_id , args)
262
+ ty:: ExistentialPredicate :: Trait ( ty:: ExistentialTraitRef :: new (
263
+ tcx,
264
+ trait_ref. def_id ,
265
+ args,
266
+ ) )
303
267
} )
304
268
} ) ;
305
269
@@ -322,21 +286,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
322
286
b. projection_term = replace_dummy_self_with_error ( tcx, b. projection_term , guar) ;
323
287
}
324
288
325
- ty:: ExistentialProjection :: erase_self_ty ( tcx, b)
289
+ ty:: ExistentialPredicate :: Projection ( ty:: ExistentialProjection :: erase_self_ty (
290
+ tcx, b,
291
+ ) )
326
292
} )
327
293
} ) ;
328
294
329
- let regular_trait_predicates = existential_trait_refs
330
- . map ( |trait_ref| trait_ref. map_bound ( ty:: ExistentialPredicate :: Trait ) ) ;
331
- let auto_trait_predicates = auto_traits. into_iter ( ) . map ( |trait_ref| {
332
- ty:: Binder :: dummy ( ty:: ExistentialPredicate :: AutoTrait ( trait_ref. trait_ref ( ) . def_id ( ) ) )
295
+ let auto_trait_predicates = auto_traits. into_iter ( ) . map ( |( trait_pred, _) | {
296
+ assert_eq ! ( trait_pred. polarity( ) , ty:: PredicatePolarity :: Positive ) ;
297
+ assert_eq ! ( trait_pred. self_ty( ) . skip_binder( ) , dummy_self) ;
298
+
299
+ ty:: Binder :: dummy ( ty:: ExistentialPredicate :: AutoTrait ( trait_pred. def_id ( ) ) )
333
300
} ) ;
301
+
334
302
// N.b. principal, projections, auto traits
335
303
// FIXME: This is actually wrong with multiple principals in regards to symbol mangling
336
- let mut v = regular_trait_predicates
337
- . chain (
338
- existential_projections. map ( |x| x. map_bound ( ty:: ExistentialPredicate :: Projection ) ) ,
339
- )
304
+ let mut v = principal_trait_ref
305
+ . into_iter ( )
306
+ . chain ( existential_projections)
340
307
. chain ( auto_trait_predicates)
341
308
. collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
342
309
v. sort_by ( |a, b| a. skip_binder ( ) . stable_cmp ( tcx, & b. skip_binder ( ) ) ) ;
0 commit comments