@@ -3,76 +3,56 @@ use rustc_hir as hir;
33use rustc_hir:: def:: DefKind ;
44use rustc_index:: bit_set:: BitSet ;
55use 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 } ;
77use rustc_middle:: ty:: { ToPredicate , TypeSuperVisitable , TypeVisitable } ;
88use rustc_span:: def_id:: { DefId , LocalDefId , CRATE_DEF_ID } ;
99use rustc_span:: DUMMY_SP ;
1010use rustc_trait_selection:: traits;
1111
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 > > {
1714 use rustc_type_ir:: TyKind :: * ;
1815
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
3541 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+ } )
4947 }
5048
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) ,
6951
7052 Placeholder ( ..) | Bound ( ..) | Infer ( ..) => {
71- bug ! ( "unexpected type `{:?}` in sized_constraint_for_ty" , ty )
53+ bug ! ( "unexpected type `{ty :?}` in sized_constraint_for_ty" )
7254 }
73- } ;
74- debug ! ( "sized_constraint_for_ty({:?}) = {:?}" , ty, result) ;
75- result
55+ }
7656}
7757
7858fn defaultness ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> hir:: Defaultness {
@@ -90,29 +70,52 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness {
9070///
9171/// In fact, there are only a few options for the types in the constraint:
9272/// - 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
9674/// - an Error, if a type is infinitely sized
75+ #[ instrument( level = "debug" , skip( tcx) , ret) ]
9776fn adt_sized_constraint < ' tcx > (
9877 tcx : TyCtxt < ' tcx > ,
9978 def_id : DefId ,
100- ) -> ty :: EarlyBinder < & ' tcx ty:: List < Ty < ' tcx > > > {
79+ ) -> Option < ty:: EarlyBinder < Ty < ' tcx > > > {
10180 if let Some ( def_id) = def_id. as_local ( ) {
10281 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) ) ) ;
10483 }
10584 }
10685 let def = tcx. adt_def ( def_id) ;
10786
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 ;
112109
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+ } ) ;
114117
115- ty:: EarlyBinder :: bind ( result )
118+ result . map ( ty:: EarlyBinder :: bind)
116119}
117120
118121/// See `ParamEnv` struct definition for details.
0 commit comments