@@ -3,76 +3,56 @@ use rustc_hir as hir;
3
3
use rustc_hir:: def:: DefKind ;
4
4
use rustc_index:: bit_set:: BitSet ;
5
5
use rustc_middle:: query:: Providers ;
6
- use rustc_middle:: ty:: { self , EarlyBinder , Ty , TyCtxt , TypeVisitor } ;
6
+ use rustc_middle:: ty:: { self , EarlyBinder , Ty , TyCtxt , TypeVisitableExt , TypeVisitor } ;
7
7
use rustc_middle:: ty:: { ToPredicate , TypeSuperVisitable , TypeVisitable } ;
8
8
use rustc_span:: def_id:: { DefId , LocalDefId , CRATE_DEF_ID } ;
9
9
use rustc_span:: DUMMY_SP ;
10
10
use rustc_trait_selection:: traits;
11
11
12
- fn sized_constraint_for_ty < ' tcx > (
13
- tcx : TyCtxt < ' tcx > ,
14
- adtdef : ty:: AdtDef < ' tcx > ,
15
- ty : Ty < ' tcx > ,
16
- ) -> Vec < Ty < ' tcx > > {
12
+ #[ instrument( level = "debug" , skip( tcx) , ret) ]
13
+ fn sized_constraint_for_ty < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> Option < Ty < ' tcx > > {
17
14
use rustc_type_ir:: TyKind :: * ;
18
15
19
- let result = match ty. kind ( ) {
20
- Bool | Char | Int ( ..) | Uint ( ..) | Float ( ..) | RawPtr ( ..) | Ref ( ..) | FnDef ( ..)
21
- | FnPtr ( _) | Array ( ..) | Closure ( ..) | CoroutineClosure ( ..) | Coroutine ( ..) | Never => {
22
- vec ! [ ]
23
- }
24
-
25
- Str | Dynamic ( ..) | Slice ( _) | Foreign ( ..) | Error ( _) | CoroutineWitness ( ..) => {
26
- // these are never sized - return the target type
27
- vec ! [ ty]
28
- }
29
-
30
- Tuple ( tys) => match tys. last ( ) {
31
- None => vec ! [ ] ,
32
- Some ( & ty) => sized_constraint_for_ty ( tcx, adtdef, ty) ,
33
- } ,
34
-
16
+ match ty. kind ( ) {
17
+ // these are always sized
18
+ Bool
19
+ | Char
20
+ | Int ( ..)
21
+ | Uint ( ..)
22
+ | Float ( ..)
23
+ | RawPtr ( ..)
24
+ | Ref ( ..)
25
+ | FnDef ( ..)
26
+ | FnPtr ( ..)
27
+ | Array ( ..)
28
+ | Closure ( ..)
29
+ | CoroutineClosure ( ..)
30
+ | Coroutine ( ..)
31
+ | CoroutineWitness ( ..)
32
+ | Never
33
+ | Dynamic ( _, _, ty:: DynStar ) => None ,
34
+
35
+ // these are never sized
36
+ Str | Slice ( ..) | Dynamic ( _, _, ty:: Dyn ) | Foreign ( ..) => Some ( ty) ,
37
+
38
+ Tuple ( tys) => tys. last ( ) . and_then ( |& ty| sized_constraint_for_ty ( tcx, ty) ) ,
39
+
40
+ // recursive case
35
41
Adt ( adt, args) => {
36
- // recursive case
37
- let adt_tys = adt. sized_constraint ( tcx) ;
38
- debug ! ( "sized_constraint_for_ty({:?}) intermediate = {:?}" , ty, adt_tys) ;
39
- adt_tys
40
- . iter_instantiated ( tcx, args)
41
- . flat_map ( |ty| sized_constraint_for_ty ( tcx, adtdef, ty) )
42
- . collect ( )
43
- }
44
-
45
- Alias ( ..) => {
46
- // must calculate explicitly.
47
- // FIXME: consider special-casing always-Sized projections
48
- vec ! [ ty]
42
+ let intermediate = adt. sized_constraint ( tcx) ;
43
+ intermediate. and_then ( |intermediate| {
44
+ let ty = intermediate. instantiate ( tcx, args) ;
45
+ sized_constraint_for_ty ( tcx, ty)
46
+ } )
49
47
}
50
48
51
- Param ( ..) => {
52
- // perf hack: if there is a `T: Sized` bound, then
53
- // we know that `T` is Sized and do not need to check
54
- // it on the impl.
55
-
56
- let Some ( sized_trait_def_id) = tcx. lang_items ( ) . sized_trait ( ) else { return vec ! [ ty] } ;
57
- let predicates = tcx. predicates_of ( adtdef. did ( ) ) . predicates ;
58
- if predicates. iter ( ) . any ( |( p, _) | {
59
- p. as_trait_clause ( ) . is_some_and ( |trait_pred| {
60
- trait_pred. def_id ( ) == sized_trait_def_id
61
- && trait_pred. self_ty ( ) . skip_binder ( ) == ty
62
- } )
63
- } ) {
64
- vec ! [ ]
65
- } else {
66
- vec ! [ ty]
67
- }
68
- }
49
+ // these can be sized or unsized
50
+ Param ( ..) | Alias ( ..) | Error ( _) => Some ( ty) ,
69
51
70
52
Placeholder ( ..) | Bound ( ..) | Infer ( ..) => {
71
- bug ! ( "unexpected type `{:?}` in sized_constraint_for_ty" , ty )
53
+ bug ! ( "unexpected type `{ty :?}` in sized_constraint_for_ty" )
72
54
}
73
- } ;
74
- debug ! ( "sized_constraint_for_ty({:?}) = {:?}" , ty, result) ;
75
- result
55
+ }
76
56
}
77
57
78
58
fn defaultness ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> hir:: Defaultness {
@@ -90,29 +70,52 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness {
90
70
///
91
71
/// In fact, there are only a few options for the types in the constraint:
92
72
/// - an obviously-unsized type
93
- /// - a type parameter or projection whose Sizedness can't be known
94
- /// - a tuple of type parameters or projections, if there are multiple
95
- /// such.
73
+ /// - a type parameter or projection whose sizedness can't be known
96
74
/// - an Error, if a type is infinitely sized
75
+ #[ instrument( level = "debug" , skip( tcx) , ret) ]
97
76
fn adt_sized_constraint < ' tcx > (
98
77
tcx : TyCtxt < ' tcx > ,
99
78
def_id : DefId ,
100
- ) -> ty :: EarlyBinder < & ' tcx ty:: List < Ty < ' tcx > > > {
79
+ ) -> Option < ty:: EarlyBinder < Ty < ' tcx > > > {
101
80
if let Some ( def_id) = def_id. as_local ( ) {
102
81
if let ty:: Representability :: Infinite ( guar) = tcx. representability ( def_id) {
103
- return ty:: EarlyBinder :: bind ( tcx . mk_type_list ( & [ Ty :: new_error ( tcx, guar) ] ) ) ;
82
+ return Some ( ty:: EarlyBinder :: bind ( Ty :: new_error ( tcx, guar) ) ) ;
104
83
}
105
84
}
106
85
let def = tcx. adt_def ( def_id) ;
107
86
108
- let result =
109
- tcx. mk_type_list_from_iter ( def. variants ( ) . iter ( ) . filter_map ( |v| v. tail_opt ( ) ) . flat_map (
110
- |f| sized_constraint_for_ty ( tcx, def, tcx. type_of ( f. did ) . instantiate_identity ( ) ) ,
111
- ) ) ;
87
+ if !def. is_struct ( ) {
88
+ bug ! ( "`adt_sized_constraint` called on non-struct type: {def:?}" ) ;
89
+ }
90
+
91
+ let tail_def = def. non_enum_variant ( ) . tail_opt ( ) ?;
92
+ let tail_ty = tcx. type_of ( tail_def. did ) . instantiate_identity ( ) ;
93
+
94
+ let result = sized_constraint_for_ty ( tcx, tail_ty) ;
95
+
96
+ let result = result. filter ( |& ty| {
97
+ // perf hack: if there is a `ty: Sized` bound, then we know that
98
+ // the type is sized and do not need to check it on the impl.
99
+
100
+ if ty. references_error ( ) {
101
+ return true ;
102
+ }
103
+
104
+ let Some ( sized_trait_def_id) = tcx. lang_items ( ) . sized_trait ( ) else {
105
+ return true ;
106
+ } ;
107
+
108
+ let predicates = tcx. predicates_of ( def. did ( ) ) . predicates ;
112
109
113
- debug ! ( "adt_sized_constraint: {:?} => {:?}" , def, result) ;
110
+ !predicates. iter ( ) . any ( |( p, _) | {
111
+ p. as_trait_clause ( ) . is_some_and ( |trait_pred| {
112
+ trait_pred. def_id ( ) == sized_trait_def_id
113
+ && trait_pred. self_ty ( ) . skip_binder ( ) == ty
114
+ } )
115
+ } )
116
+ } ) ;
114
117
115
- ty:: EarlyBinder :: bind ( result )
118
+ result . map ( ty:: EarlyBinder :: bind)
116
119
}
117
120
118
121
/// See `ParamEnv` struct definition for details.
0 commit comments