Skip to content

Defer reasoning about regions until after regionck #7187

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3 changes: 3 additions & 0 deletions src/librustc/middle/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ pass builds up the `scope_map`, which describes the parent links in
the region hierarchy. The second pass infers which types must be
region parameterized.

Most of the documentation on regions can be found in
`middle/typeck/infer/region_inference.rs`

*/


Expand Down
52 changes: 30 additions & 22 deletions src/librustc/middle/typeck/check/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use middle::typeck::check::demand;
use middle::typeck::check::{check_block, check_expr_has_type, FnCtxt};
use middle::typeck::check::{instantiate_path, lookup_def};
use middle::typeck::check::{structure_of, valid_range_bounds};
use middle::typeck::infer;
use middle::typeck::require_same_types;

use std::hashmap::{HashMap, HashSet};
Expand All @@ -29,26 +30,31 @@ pub fn check_match(fcx: @mut FnCtxt,
arms: &[ast::arm]) {
let tcx = fcx.ccx.tcx;

let pattern_ty = fcx.infcx().next_ty_var();
check_expr_has_type(fcx, discrim, pattern_ty);
let discrim_ty = fcx.infcx().next_ty_var();
check_expr_has_type(fcx, discrim, discrim_ty);

// Typecheck the patterns first, so that we get types for all the
// bindings.
for arms.iter().advance |arm| {
let pcx = pat_ctxt {
fcx: fcx,
map: pat_id_map(tcx.def_map, arm.pats[0]),
match_region: ty::re_scope(expr.id),
block_region: ty::re_scope(arm.body.node.id)
};

for arm.pats.iter().advance |p| { check_pat(&pcx, *p, pattern_ty);}
for arm.pats.iter().advance |p| { check_pat(&pcx, *p, discrim_ty);}
}

// The result of the match is the common supertype of all the
// arms. Start out the value as bottom, since it's the, well,
// bottom the type lattice, and we'll be moving up the lattice as
// we process each arm. (Note that any match with 0 arms is matching
// on any empty type and is therefore unreachable; should the flow
// of execution reach it, we will fail, so bottom is an appropriate
// type in that case)
let mut result_ty = ty::mk_bot();

// Now typecheck the blocks.
let mut result_ty = fcx.infcx().next_ty_var();
let mut arm_non_bot = false;
let mut saw_err = false;
let mut saw_err = ty::type_is_error(discrim_ty);
for arms.iter().advance |arm| {
let mut guard_err = false;
let mut guard_bot = false;
Expand All @@ -75,26 +81,28 @@ pub fn check_match(fcx: @mut FnCtxt,
else if guard_bot {
fcx.write_bot(arm.body.node.id);
}
else if !ty::type_is_bot(bty) {
arm_non_bot = true; // If the match *may* evaluate to a non-_|_
// expr, the whole thing is non-_|_
}
demand::suptype(fcx, arm.body.span, result_ty, bty);

result_ty =
infer::common_supertype(
fcx.infcx(),
infer::MatchExpression(expr.span),
true, // result_ty is "expected" here
result_ty,
bty);
}

if saw_err {
result_ty = ty::mk_err();
}
else if !arm_non_bot {
} else if ty::type_is_bot(discrim_ty) {
result_ty = ty::mk_bot();
}

fcx.write_ty(expr.id, result_ty);
}

pub struct pat_ctxt {
fcx: @mut FnCtxt,
map: PatIdMap,
match_region: ty::Region, // Region for the match as a whole
block_region: ty::Region, // Region for the block of the arm
}

pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: @ast::Path,
Expand Down Expand Up @@ -442,8 +450,8 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
// then the type of x is &M T where M is the mutability
// and T is the expected type
let region_var =
fcx.infcx().next_region_var_with_lb(
pat.span, pcx.block_region);
fcx.infcx().next_region_var(
infer::PatternRegion(pat.span));
let mt = ty::mt {ty: expected, mutbl: mutbl};
let region_ty = ty::mk_rptr(tcx, region_var, mt);
demand::eqtype(fcx, pat.span, region_ty, typ);
Expand Down Expand Up @@ -544,9 +552,8 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
}
ast::pat_vec(ref before, slice, ref after) => {
let default_region_var =
fcx.infcx().next_region_var_with_lb(
pat.span, pcx.block_region
);
fcx.infcx().next_region_var(
infer::PatternRegion(pat.span));

let (elt_type, region_var) = match structure_of(
fcx, pat.span, expected
Expand Down Expand Up @@ -651,3 +658,4 @@ pub fn check_pointer_pat(pcx: &pat_ctxt,

#[deriving(Eq)]
enum PointerKind { Managed, Send, Borrowed }

4 changes: 2 additions & 2 deletions src/librustc/middle/typeck/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub fn suptype_with_fn(fcx: @mut FnCtxt,
ty_a: ty::t, ty_b: ty::t,
handle_err: &fn(span, ty::t, ty::t, &ty::type_err)) {
// n.b.: order of actual, expected is reversed
match infer::mk_subty(fcx.infcx(), b_is_expected, sp,
match infer::mk_subty(fcx.infcx(), b_is_expected, infer::Misc(sp),
ty_b, ty_a) {
result::Ok(()) => { /* ok */ }
result::Err(ref err) => {
Expand All @@ -45,7 +45,7 @@ pub fn suptype_with_fn(fcx: @mut FnCtxt,
}

pub fn eqtype(fcx: @mut FnCtxt, sp: span, expected: ty::t, actual: ty::t) {
match infer::mk_eqty(fcx.infcx(), false, sp, actual, expected) {
match infer::mk_eqty(fcx.infcx(), false, infer::Misc(sp), actual, expected) {
Ok(()) => { /* ok */ }
Err(ref err) => {
fcx.report_mismatched_types(sp, expected, actual, err);
Expand Down
17 changes: 12 additions & 5 deletions src/librustc/middle/typeck/check/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -619,14 +619,18 @@ impl<'self> LookupContext<'self> {
autoref: None}))
}
ty::ty_rptr(_, self_mt) => {
let region = self.infcx().next_region_var_nb(self.expr.span);
let region =
self.infcx().next_region_var(
infer::Autoref(self.expr.span));
(ty::mk_rptr(tcx, region, self_mt),
ty::AutoDerefRef(ty::AutoDerefRef {
autoderefs: autoderefs+1,
autoref: Some(ty::AutoPtr(region, self_mt.mutbl))}))
}
ty::ty_evec(self_mt, vstore_slice(_)) => {
let region = self.infcx().next_region_var_nb(self.expr.span);
let region =
self.infcx().next_region_var(
infer::Autoref(self.expr.span));
(ty::mk_evec(tcx, self_mt, vstore_slice(region)),
ty::AutoDerefRef(ty::AutoDerefRef {
autoderefs: autoderefs,
Expand Down Expand Up @@ -758,7 +762,9 @@ impl<'self> LookupContext<'self> {
-> Option<method_map_entry> {
// This is hokey. We should have mutability inference as a
// variable. But for now, try &const, then &, then &mut:
let region = self.infcx().next_region_var_nb(self.expr.span);
let region =
self.infcx().next_region_var(
infer::Autoref(self.expr.span));
for mutbls.iter().advance |mutbl| {
let autoref_ty = mk_autoref_ty(*mutbl, region);
match self.search_for_method(autoref_ty) {
Expand Down Expand Up @@ -970,7 +976,8 @@ impl<'self> LookupContext<'self> {
let (_, opt_transformed_self_ty, fn_sig) =
replace_bound_regions_in_fn_sig(
tcx, @Nil, Some(transformed_self_ty), &bare_fn_ty.sig,
|_br| self.fcx.infcx().next_region_var_nb(self.expr.span));
|br| self.fcx.infcx().next_region_var(
infer::BoundRegionInFnCall(self.expr.span, br)));
let transformed_self_ty = opt_transformed_self_ty.get();
let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {sig: fn_sig, ..bare_fn_ty});
debug!("after replacing bound regions, fty=%s", self.ty_to_str(fty));
Expand All @@ -982,7 +989,7 @@ impl<'self> LookupContext<'self> {
// variables to unify etc). Since we checked beforehand, and
// nothing has changed in the meantime, this unification
// should never fail.
match self.fcx.mk_subty(false, self.self_expr.span,
match self.fcx.mk_subty(false, infer::Misc(self.self_expr.span),
rcvr_ty, transformed_self_ty) {
result::Ok(_) => (),
result::Err(_) => {
Expand Down
Loading