Skip to content

Commit 9e6d5e1

Browse files
committed
Defer reasoning about region relationships until after regionck.
This patch makes error handling for region inference failures more uniform by not reporting *any* region errors until the reigon inference step. This requires threading through more information about what caused a region constraint, so that we can still give informative error messages. I have only taken partial advantage of this information: when region inference fails, we still report the same error we always did, despite the fact that we now know precisely what caused the various constriants and what the region variable represents, which we did not know before. This change is required not only to improve error messages but because the region hierarchy is not in fact fully known until regionck, because it is not clear where closure bodies fit in (our current treatment is unsound). Moreover, the relationships between free variables cannot be fully determined until type inference is otherwise complete. cc #3238.
1 parent e482856 commit 9e6d5e1

39 files changed

+1211
-522
lines changed

src/librustc/middle/typeck/check/_match.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use middle::typeck::check::demand;
1515
use middle::typeck::check::{check_block, check_expr_has_type, FnCtxt};
1616
use middle::typeck::check::{instantiate_path, lookup_def};
1717
use middle::typeck::check::{structure_of, valid_range_bounds};
18+
use middle::typeck::infer;
1819
use middle::typeck::require_same_types;
1920

2021
use std::hashmap::{HashMap, HashSet};
@@ -38,8 +39,6 @@ pub fn check_match(fcx: @mut FnCtxt,
3839
let pcx = pat_ctxt {
3940
fcx: fcx,
4041
map: pat_id_map(tcx.def_map, arm.pats[0]),
41-
match_region: ty::re_scope(expr.id),
42-
block_region: ty::re_scope(arm.body.node.id)
4342
};
4443

4544
for arm.pats.iter().advance |p| { check_pat(&pcx, *p, pattern_ty);}
@@ -93,8 +92,6 @@ pub fn check_match(fcx: @mut FnCtxt,
9392
pub struct pat_ctxt {
9493
fcx: @mut FnCtxt,
9594
map: PatIdMap,
96-
match_region: ty::Region, // Region for the match as a whole
97-
block_region: ty::Region, // Region for the block of the arm
9895
}
9996

10097
pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: @ast::Path,
@@ -442,8 +439,8 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
442439
// then the type of x is &M T where M is the mutability
443440
// and T is the expected type
444441
let region_var =
445-
fcx.infcx().next_region_var_with_lb(
446-
pat.span, pcx.block_region);
442+
fcx.infcx().next_region_var(
443+
infer::PatternRegion(pat.span));
447444
let mt = ty::mt {ty: expected, mutbl: mutbl};
448445
let region_ty = ty::mk_rptr(tcx, region_var, mt);
449446
demand::eqtype(fcx, pat.span, region_ty, typ);
@@ -544,9 +541,8 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
544541
}
545542
ast::pat_vec(ref before, slice, ref after) => {
546543
let default_region_var =
547-
fcx.infcx().next_region_var_with_lb(
548-
pat.span, pcx.block_region
549-
);
544+
fcx.infcx().next_region_var(
545+
infer::PatternRegion(pat.span));
550546
551547
let (elt_type, region_var) = match structure_of(
552548
fcx, pat.span, expected

src/librustc/middle/typeck/check/demand.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub fn suptype_with_fn(fcx: @mut FnCtxt,
3535
ty_a: ty::t, ty_b: ty::t,
3636
handle_err: &fn(span, ty::t, ty::t, &ty::type_err)) {
3737
// n.b.: order of actual, expected is reversed
38-
match infer::mk_subty(fcx.infcx(), b_is_expected, sp,
38+
match infer::mk_subty(fcx.infcx(), b_is_expected, infer::Misc(sp),
3939
ty_b, ty_a) {
4040
result::Ok(()) => { /* ok */ }
4141
result::Err(ref err) => {
@@ -45,7 +45,7 @@ pub fn suptype_with_fn(fcx: @mut FnCtxt,
4545
}
4646

4747
pub fn eqtype(fcx: @mut FnCtxt, sp: span, expected: ty::t, actual: ty::t) {
48-
match infer::mk_eqty(fcx.infcx(), false, sp, actual, expected) {
48+
match infer::mk_eqty(fcx.infcx(), false, infer::Misc(sp), actual, expected) {
4949
Ok(()) => { /* ok */ }
5050
Err(ref err) => {
5151
fcx.report_mismatched_types(sp, expected, actual, err);

src/librustc/middle/typeck/check/method.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -619,14 +619,18 @@ impl<'self> LookupContext<'self> {
619619
autoref: None}))
620620
}
621621
ty::ty_rptr(_, self_mt) => {
622-
let region = self.infcx().next_region_var_nb(self.expr.span);
622+
let region =
623+
self.infcx().next_region_var(
624+
infer::Autoref(self.expr.span));
623625
(ty::mk_rptr(tcx, region, self_mt),
624626
ty::AutoDerefRef(ty::AutoDerefRef {
625627
autoderefs: autoderefs+1,
626628
autoref: Some(ty::AutoPtr(region, self_mt.mutbl))}))
627629
}
628630
ty::ty_evec(self_mt, vstore_slice(_)) => {
629-
let region = self.infcx().next_region_var_nb(self.expr.span);
631+
let region =
632+
self.infcx().next_region_var(
633+
infer::Autoref(self.expr.span));
630634
(ty::mk_evec(tcx, self_mt, vstore_slice(region)),
631635
ty::AutoDerefRef(ty::AutoDerefRef {
632636
autoderefs: autoderefs,
@@ -758,7 +762,9 @@ impl<'self> LookupContext<'self> {
758762
-> Option<method_map_entry> {
759763
// This is hokey. We should have mutability inference as a
760764
// variable. But for now, try &const, then &, then &mut:
761-
let region = self.infcx().next_region_var_nb(self.expr.span);
765+
let region =
766+
self.infcx().next_region_var(
767+
infer::Autoref(self.expr.span));
762768
for mutbls.iter().advance |mutbl| {
763769
let autoref_ty = mk_autoref_ty(*mutbl, region);
764770
match self.search_for_method(autoref_ty) {
@@ -970,7 +976,8 @@ impl<'self> LookupContext<'self> {
970976
let (_, opt_transformed_self_ty, fn_sig) =
971977
replace_bound_regions_in_fn_sig(
972978
tcx, @Nil, Some(transformed_self_ty), &bare_fn_ty.sig,
973-
|_br| self.fcx.infcx().next_region_var_nb(self.expr.span));
979+
|br| self.fcx.infcx().next_region_var(
980+
infer::BoundRegionInFnCall(self.expr.span, br)));
974981
let transformed_self_ty = opt_transformed_self_ty.get();
975982
let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {sig: fn_sig, ..bare_fn_ty});
976983
debug!("after replacing bound regions, fty=%s", self.ty_to_str(fty));
@@ -982,7 +989,7 @@ impl<'self> LookupContext<'self> {
982989
// variables to unify etc). Since we checked beforehand, and
983990
// nothing has changed in the meantime, this unification
984991
// should never fail.
985-
match self.fcx.mk_subty(false, self.self_expr.span,
992+
match self.fcx.mk_subty(false, infer::Misc(self.self_expr.span),
986993
rcvr_ty, transformed_self_ty) {
987994
result::Ok(_) => (),
988995
result::Err(_) => {

src/librustc/middle/typeck/check/mod.rs

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -467,8 +467,6 @@ pub fn check_fn(ccx: @mut CrateCtxt,
467467
let pcx = pat_ctxt {
468468
fcx: fcx,
469469
map: pat_id_map(tcx.def_map, input.pat),
470-
match_region: region,
471-
block_region: region,
472470
};
473471
_match::check_pat(&pcx, input.pat, *arg_ty);
474472
}
@@ -686,9 +684,14 @@ impl FnCtxt {
686684
result::Ok(self.block_region())
687685
} else {
688686
result::Err(RegionError {
689-
msg: fmt!("named region `%s` not in scope here",
690-
bound_region_ptr_to_str(self.tcx(), br)),
691-
replacement: self.infcx().next_region_var_nb(span)
687+
msg: {
688+
fmt!("named region `%s` not in scope here",
689+
bound_region_to_str(self.tcx(), br))
690+
},
691+
replacement: {
692+
self.infcx().next_region_var(
693+
infer::BoundRegionError(span))
694+
}
692695
})
693696
}
694697
}
@@ -698,7 +701,7 @@ impl FnCtxt {
698701

699702
impl region_scope for FnCtxt {
700703
fn anon_region(&self, span: span) -> Result<ty::Region, RegionError> {
701-
result::Ok(self.infcx().next_region_var_nb(span))
704+
result::Ok(self.infcx().next_region_var(infer::MiscVariable(span)))
702705
}
703706
fn self_region(&self, span: span) -> Result<ty::Region, RegionError> {
704707
self.search_in_scope_regions(span, ty::br_self)
@@ -845,21 +848,28 @@ impl FnCtxt {
845848

846849
pub fn mk_subty(&self,
847850
a_is_expected: bool,
848-
span: span,
851+
origin: infer::SubtypeOrigin,
849852
sub: ty::t,
850853
sup: ty::t)
851854
-> Result<(), ty::type_err> {
852-
infer::mk_subty(self.infcx(), a_is_expected, span, sub, sup)
855+
infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
853856
}
854857

855858
pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
856859
-> Result<(), ty::type_err> {
857860
infer::can_mk_subty(self.infcx(), sub, sup)
858861
}
859862

860-
pub fn mk_assignty(&self, expr: @ast::expr, sub: ty::t, sup: ty::t)
863+
pub fn mk_assignty(&self,
864+
expr: @ast::expr,
865+
sub: ty::t,
866+
sup: ty::t)
861867
-> Result<(), ty::type_err> {
862-
match infer::mk_coercety(self.infcx(), false, expr.span, sub, sup) {
868+
match infer::mk_coercety(self.infcx(),
869+
false,
870+
infer::ExprAssignable(expr),
871+
sub,
872+
sup) {
863873
Ok(None) => result::Ok(()),
864874
Err(ref e) => result::Err((*e)),
865875
Ok(Some(adjustment)) => {
@@ -876,20 +886,19 @@ impl FnCtxt {
876886

877887
pub fn mk_eqty(&self,
878888
a_is_expected: bool,
879-
span: span,
889+
origin: infer::SubtypeOrigin,
880890
sub: ty::t,
881891
sup: ty::t)
882892
-> Result<(), ty::type_err> {
883-
infer::mk_eqty(self.infcx(), a_is_expected, span, sub, sup)
893+
infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
884894
}
885895

886896
pub fn mk_subr(&self,
887897
a_is_expected: bool,
888-
span: span,
898+
origin: infer::SubregionOrigin,
889899
sub: ty::Region,
890-
sup: ty::Region)
891-
-> Result<(), ty::type_err> {
892-
infer::mk_subr(self.infcx(), a_is_expected, span, sub, sup)
900+
sup: ty::Region) {
901+
infer::mk_subr(self.infcx(), a_is_expected, origin, sub, sup)
893902
}
894903

895904
pub fn with_region_lb<R>(@mut self, lb: ast::node_id, f: &fn() -> R)
@@ -905,7 +914,9 @@ impl FnCtxt {
905914
rp: Option<ty::region_variance>,
906915
span: span)
907916
-> Option<ty::Region> {
908-
rp.map(|_rp| self.infcx().next_region_var_nb(span))
917+
rp.map(
918+
|_| self.infcx().next_region_var(
919+
infer::BoundRegionInTypeOrImpl(span)))
909920
}
910921

911922
pub fn type_error_message(&self,
@@ -1089,7 +1100,8 @@ pub fn impl_self_ty(vcx: &VtableContext,
10891100
};
10901101

10911102
let self_r = if region_param.is_some() {
1092-
Some(vcx.infcx.next_region_var_nb(location_info.span))
1103+
Some(vcx.infcx.next_region_var(
1104+
infer::BoundRegionInTypeOrImpl(location_info.span)))
10931105
} else {
10941106
None
10951107
};
@@ -1352,7 +1364,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
13521364
let (_, _, fn_sig) =
13531365
replace_bound_regions_in_fn_sig(
13541366
fcx.tcx(), @Nil, None, &fn_sig,
1355-
|_br| fcx.infcx().next_region_var_nb(call_expr.span));
1367+
|br| fcx.infcx().next_region_var(
1368+
infer::BoundRegionInFnCall(call_expr.span, br)));
13561369

13571370
// Call the generic checker.
13581371
check_argument_types(fcx, call_expr.span, fn_sig.inputs, f,
@@ -2085,7 +2098,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
20852098
let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
20862099
let inner_ty = match expected_sty {
20872100
Some(ty::ty_closure(ref fty)) => {
2088-
match fcx.mk_subty(false, expr.span,
2101+
match fcx.mk_subty(false, infer::Misc(expr.span),
20892102
fty.sig.output, ty::mk_bool()) {
20902103
result::Ok(_) => {
20912104
ty::mk_closure(tcx, ty::ClosureTy {
@@ -2395,7 +2408,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
23952408
// Finally, borrowck is charged with guaranteeing that the
23962409
// value whose address was taken can actually be made to live
23972410
// as long as it needs to live.
2398-
let region = fcx.infcx().next_region_var_nb(expr.span);
2411+
let region = fcx.infcx().next_region_var(
2412+
infer::AddrOfRegion(expr.span));
23992413

24002414
let tm = ty::mt { ty: fcx.expr_ty(oprnd), mutbl: mutbl };
24012415
let oprnd_t = if ty::type_is_error(tm.ty) {
@@ -2437,7 +2451,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
24372451
Some(t) => t, None => fcx.ret_ty
24382452
};
24392453
match expr_opt {
2440-
None => match fcx.mk_eqty(false, expr.span,
2454+
None => match fcx.mk_eqty(false, infer::Misc(expr.span),
24412455
ret_ty, ty::mk_nil()) {
24422456
result::Ok(_) => { /* fall through */ }
24432457
result::Err(_) => {
@@ -2686,7 +2700,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
26862700
let el = ty::sequence_element_type(fcx.tcx(),
26872701
t1);
26882702
infer::mk_eqty(fcx.infcx(), false,
2689-
sp, el, t2).is_ok()
2703+
infer::Misc(sp), el, t2).is_ok()
26902704
}
26912705
}
26922706

@@ -2907,8 +2921,6 @@ pub fn check_decl_local(fcx: @mut FnCtxt, local: @ast::local) {
29072921
let pcx = pat_ctxt {
29082922
fcx: fcx,
29092923
map: pat_id_map(tcx.def_map, local.node.pat),
2910-
match_region: region,
2911-
block_region: region,
29122924
};
29132925
_match::check_pat(&pcx, local.node.pat, t);
29142926
let pat_ty = fcx.node_ty(local.node.pat.id);
@@ -3412,7 +3424,7 @@ pub fn ast_expr_vstore_to_vstore(fcx: @mut FnCtxt,
34123424
ast::expr_vstore_uniq => ty::vstore_uniq,
34133425
ast::expr_vstore_box | ast::expr_vstore_mut_box => ty::vstore_box,
34143426
ast::expr_vstore_slice | ast::expr_vstore_mut_slice => {
3415-
let r = fcx.infcx().next_region_var_nb(e.span);
3427+
let r = fcx.infcx().next_region_var(infer::AddrOfSlice(e.span));
34163428
ty::vstore_slice(r)
34173429
}
34183430
}

0 commit comments

Comments
 (0)