@@ -44,7 +44,7 @@ use middle::subst;
44
44
use middle:: subst:: { Substs } ;
45
45
use middle:: ty:: { AsPredicate , ImplContainer , ImplOrTraitItemContainer , TraitContainer } ;
46
46
use middle:: ty:: { mod, RegionEscape , Ty , Polytype } ;
47
- use middle:: ty_fold:: { mod, TypeFolder } ;
47
+ use middle:: ty_fold:: { mod, TypeFolder , TypeFoldable } ;
48
48
use middle:: infer;
49
49
use rscope:: * ;
50
50
use { CrateCtxt , lookup_def_tcx, no_params, write_ty_to_tcx} ;
@@ -2168,8 +2168,12 @@ pub fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
2168
2168
subst:: Substs :: new ( types, regions)
2169
2169
}
2170
2170
2171
- /// Verifies that the explicit self type of a method matches the impl or
2172
- /// trait.
2171
+ /// Verifies that the explicit self type of a method matches the impl
2172
+ /// or trait. This is a bit weird but basically because right now we
2173
+ /// don't handle the general case, but instead map it to one of
2174
+ /// several pre-defined options using various heuristics, this method
2175
+ /// comes back to check after the fact that explicit type the user
2176
+ /// wrote actually matches what the pre-defined option said.
2173
2177
fn check_method_self_type < ' a , ' tcx , RS : RegionScope > (
2174
2178
crate_context : & CrateCtxt < ' a , ' tcx > ,
2175
2179
rs : & RS ,
@@ -2193,15 +2197,19 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
2193
2197
// parameters).
2194
2198
assert ! ( !base_type. has_regions_escaping_depth( 1 ) ) ;
2195
2199
let required_type_free =
2196
- ty:: liberate_late_bound_regions (
2197
- crate_context. tcx , body_scope, & ty:: Binder ( required_type) ) ;
2200
+ liberate_early_bound_regions (
2201
+ crate_context. tcx , body_scope,
2202
+ & ty:: liberate_late_bound_regions (
2203
+ crate_context. tcx , body_scope, & ty:: Binder ( required_type) ) ) ;
2198
2204
2199
2205
// The "base type" comes from the impl. It too may have late-bound
2200
2206
// regions from the method.
2201
2207
assert ! ( !base_type. has_regions_escaping_depth( 1 ) ) ;
2202
2208
let base_type_free =
2203
- ty:: liberate_late_bound_regions (
2204
- crate_context. tcx , body_scope, & ty:: Binder ( base_type) ) ;
2209
+ liberate_early_bound_regions (
2210
+ crate_context. tcx , body_scope,
2211
+ & ty:: liberate_late_bound_regions (
2212
+ crate_context. tcx , body_scope, & ty:: Binder ( base_type) ) ) ;
2205
2213
2206
2214
debug ! ( "required_type={} required_type_free={} \
2207
2215
base_type={} base_type_free={}",
@@ -2222,4 +2230,30 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
2222
2230
} ) ) ;
2223
2231
infcx. resolve_regions_and_report_errors ( ) ;
2224
2232
}
2233
+
2234
+ fn liberate_early_bound_regions < ' tcx , T > (
2235
+ tcx : & ty:: ctxt < ' tcx > ,
2236
+ scope : region:: CodeExtent ,
2237
+ value : & T )
2238
+ -> T
2239
+ where T : TypeFoldable < ' tcx > + Repr < ' tcx >
2240
+ {
2241
+ /*!
2242
+ * Convert early-bound regions into free regions; normally this is done by
2243
+ * applying the `free_substs` from the `ParameterEnvironment`, but this particular
2244
+ * method-self-type check is kind of hacky and done very early in the process,
2245
+ * before we really have a `ParameterEnvironment` to check.
2246
+ */
2247
+
2248
+ ty_fold:: fold_regions ( tcx, value, |region, _| {
2249
+ match region {
2250
+ ty:: ReEarlyBound ( id, _, _, name) => {
2251
+ let def_id = local_def ( id) ;
2252
+ ty:: ReFree ( ty:: FreeRegion { scope : scope,
2253
+ bound_region : ty:: BrNamed ( def_id, name) } )
2254
+ }
2255
+ _ => region
2256
+ }
2257
+ } )
2258
+ }
2225
2259
}
0 commit comments