Skip to content

Commit a13804f

Browse files
committed
WIP -- Fix checking of explicit self, which was relying on late-bound regions to work.
1 parent 0e3f440 commit a13804f

File tree

2 files changed

+48
-16
lines changed

2 files changed

+48
-16
lines changed

src/librustc_typeck/astconv.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ use middle::def;
5353
use middle::resolve_lifetime as rl;
5454
use middle::subst::{FnSpace, TypeSpace, AssocSpace, SelfSpace, Subst, Substs};
5555
use middle::subst::{VecPerParamSpace};
56-
use middle::ty::{mod, Ty};
57-
use middle::ty_fold;
56+
use middle::ty::{mod, RegionEscape, Ty};
5857
use rscope::{mod, UnelidableRscope, RegionScope, SpecificRscope,
5958
ShiftedRscope, BindingRscope};
6059
use TypeAndSubsts;
@@ -1142,10 +1141,9 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
11421141
let (self_ty, mut implied_output_region) = match opt_self_info {
11431142
None => (None, None),
11441143
Some(self_info) => {
1145-
// Shift regions in the self type by 1 to account for the binding
1146-
// level introduced by the function itself.
1147-
let untransformed_self_ty =
1148-
ty_fold::shift_regions(this.tcx(), 1, &self_info.untransformed_self_ty);
1144+
// This type comes from an impl or trait; no late-bound
1145+
// regions should be present.
1146+
assert!(!self_info.untransformed_self_ty.has_escaping_regions());
11491147

11501148
// Figure out and record the explicit self category.
11511149
let explicit_self_category =
@@ -1156,19 +1154,19 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
11561154
(None, None)
11571155
}
11581156
ty::ByValueExplicitSelfCategory => {
1159-
(Some(untransformed_self_ty), None)
1157+
(Some(self_info.untransformed_self_ty), None)
11601158
}
11611159
ty::ByReferenceExplicitSelfCategory(region, mutability) => {
11621160
(Some(ty::mk_rptr(this.tcx(),
11631161
region,
11641162
ty::mt {
1165-
ty: untransformed_self_ty,
1163+
ty: self_info.untransformed_self_ty,
11661164
mutbl: mutability
11671165
})),
11681166
Some(region))
11691167
}
11701168
ty::ByBoxExplicitSelfCategory => {
1171-
(Some(ty::mk_uniq(this.tcx(), untransformed_self_ty)), None)
1169+
(Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty)), None)
11721170
}
11731171
}
11741172
}

src/librustc_typeck/collect.rs

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use middle::subst;
4444
use middle::subst::{Substs};
4545
use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
4646
use middle::ty::{mod, RegionEscape, Ty, Polytype};
47-
use middle::ty_fold::{mod, TypeFolder};
47+
use middle::ty_fold::{mod, TypeFolder, TypeFoldable};
4848
use middle::infer;
4949
use rscope::*;
5050
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>,
21682168
subst::Substs::new(types, regions)
21692169
}
21702170

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.
21732177
fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
21742178
crate_context: &CrateCtxt<'a, 'tcx>,
21752179
rs: &RS,
@@ -2193,15 +2197,19 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
21932197
// parameters).
21942198
assert!(!base_type.has_regions_escaping_depth(1));
21952199
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)));
21982204

21992205
// The "base type" comes from the impl. It too may have late-bound
22002206
// regions from the method.
22012207
assert!(!base_type.has_regions_escaping_depth(1));
22022208
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)));
22052213

22062214
debug!("required_type={} required_type_free={} \
22072215
base_type={} base_type_free={}",
@@ -2222,4 +2230,30 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
22222230
}));
22232231
infcx.resolve_regions_and_report_errors();
22242232
}
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+
}
22252259
}

0 commit comments

Comments
 (0)