@@ -7,8 +7,8 @@ use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
7
7
use crate :: ty:: visit:: ValidateBoundVars ;
8
8
use crate :: ty:: InferTy :: * ;
9
9
use crate :: ty:: {
10
- self , AdtDef , DefIdTree , Discr , Term , Ty , TyCtxt , TypeFlags , TypeSuperVisitable , TypeVisitable ,
11
- TypeVisitor ,
10
+ self , AdtDef , DefIdTree , Discr , FallibleTypeFolder , Term , Ty , TyCtxt , TypeFlags , TypeFoldable ,
11
+ TypeSuperFoldable , TypeSuperVisitable , TypeVisitable , TypeVisitor ,
12
12
} ;
13
13
use crate :: ty:: { List , ParamEnv } ;
14
14
use hir:: def:: DefKind ;
@@ -1106,6 +1106,17 @@ impl<'tcx, T> Binder<'tcx, T> {
1106
1106
if self . 0 . has_escaping_bound_vars ( ) { None } else { Some ( self . skip_binder ( ) ) }
1107
1107
}
1108
1108
1109
+ pub fn no_bound_vars_ignoring_escaping ( self , tcx : TyCtxt < ' tcx > ) -> Option < T >
1110
+ where
1111
+ T : TypeFoldable < ' tcx > ,
1112
+ {
1113
+ if !self . 0 . has_escaping_bound_vars ( ) {
1114
+ Some ( self . skip_binder ( ) )
1115
+ } else {
1116
+ self . 0 . try_fold_with ( & mut SkipBindersAt { index : ty:: INNERMOST , tcx } ) . ok ( )
1117
+ }
1118
+ }
1119
+
1109
1120
/// Splits the contents into two things that share the same binder
1110
1121
/// level as the original, returning two distinct binders.
1111
1122
///
@@ -1135,6 +1146,81 @@ impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
1135
1146
}
1136
1147
}
1137
1148
1149
+ struct SkipBindersAt < ' tcx > {
1150
+ tcx : TyCtxt < ' tcx > ,
1151
+ index : ty:: DebruijnIndex ,
1152
+ }
1153
+
1154
+ impl < ' tcx > FallibleTypeFolder < ' tcx > for SkipBindersAt < ' tcx > {
1155
+ type Error = ( ) ;
1156
+
1157
+ fn tcx ( & self ) -> TyCtxt < ' tcx > {
1158
+ self . tcx
1159
+ }
1160
+
1161
+ fn try_fold_binder < T > ( & mut self , t : Binder < ' tcx , T > ) -> Result < Binder < ' tcx , T > , Self :: Error >
1162
+ where
1163
+ T : ty:: TypeFoldable < ' tcx > ,
1164
+ {
1165
+ self . index . shift_in ( 1 ) ;
1166
+ let value = t. try_map_bound ( |t| t. try_fold_with ( self ) ) ;
1167
+ self . index . shift_out ( 1 ) ;
1168
+ value
1169
+ }
1170
+
1171
+ fn try_fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Result < Ty < ' tcx > , Self :: Error > {
1172
+ if !ty. has_escaping_bound_vars ( ) {
1173
+ Ok ( ty)
1174
+ } else if let ty:: Bound ( index, bv) = * ty. kind ( ) {
1175
+ if index == self . index {
1176
+ Err ( ( ) )
1177
+ } else {
1178
+ Ok ( self . tcx ( ) . mk_ty ( ty:: Bound ( index. shifted_out ( 1 ) , bv) ) )
1179
+ }
1180
+ } else {
1181
+ ty. try_super_fold_with ( self )
1182
+ }
1183
+ }
1184
+
1185
+ fn try_fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> Result < ty:: Region < ' tcx > , Self :: Error > {
1186
+ if !r. has_escaping_bound_vars ( ) {
1187
+ Ok ( r)
1188
+ } else if let ty:: ReLateBound ( index, bv) = r. kind ( ) {
1189
+ if index == self . index {
1190
+ Err ( ( ) )
1191
+ } else {
1192
+ Ok ( self . tcx ( ) . mk_region ( ty:: ReLateBound ( index. shifted_out ( 1 ) , bv) ) )
1193
+ }
1194
+ } else {
1195
+ r. try_super_fold_with ( self )
1196
+ }
1197
+ }
1198
+
1199
+ fn try_fold_const ( & mut self , ct : ty:: Const < ' tcx > ) -> Result < ty:: Const < ' tcx > , Self :: Error > {
1200
+ if !ct. has_escaping_bound_vars ( ) {
1201
+ Ok ( ct)
1202
+ } else if let ty:: ConstKind :: Bound ( index, bv) = ct. kind ( ) {
1203
+ if index == self . index {
1204
+ Err ( ( ) )
1205
+ } else {
1206
+ Ok ( self . tcx ( ) . mk_const (
1207
+ ty:: ConstKind :: Bound ( index. shifted_out ( 1 ) , bv) ,
1208
+ ct. ty ( ) . try_fold_with ( self ) ?,
1209
+ ) )
1210
+ }
1211
+ } else {
1212
+ ct. try_super_fold_with ( self )
1213
+ }
1214
+ }
1215
+
1216
+ fn try_fold_predicate (
1217
+ & mut self ,
1218
+ p : ty:: Predicate < ' tcx > ,
1219
+ ) -> Result < ty:: Predicate < ' tcx > , Self :: Error > {
1220
+ if !p. has_escaping_bound_vars ( ) { Ok ( p) } else { p. try_super_fold_with ( self ) }
1221
+ }
1222
+ }
1223
+
1138
1224
/// Represents the projection of an associated type.
1139
1225
///
1140
1226
/// For a projection, this would be `<Ty as Trait<...>>::N`.
0 commit comments