Skip to content

Commit c8ab0c1

Browse files
committed
rustc: Replace region parameters in function return values
1 parent 324f57a commit c8ab0c1

File tree

1 file changed

+35
-9
lines changed

1 file changed

+35
-9
lines changed

src/rustc/middle/typeck.rs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import util::ppaux::ty_to_str;
1616
import std::smallintmap;
1717
import std::map::{hashmap, int_hash};
1818
import std::serialization::{serialize_uint, deserialize_uint};
19+
import std::ufind;
1920
import syntax::print::pprust::*;
2021

2122
export check_crate;
@@ -1554,6 +1555,33 @@ fn universally_quantify_regions(tcx: ty::ctxt, ty: ty::t) -> ty::t {
15541555
}
15551556
}
15561557

1558+
// Replaces region parameter types in the given type with the appropriate
1559+
// bindings.
1560+
fn replace_region_params(tcx: ty::ctxt,
1561+
sp: span,
1562+
rb: @ty::unify::region_bindings,
1563+
ty: ty::t)
1564+
-> ty::t {
1565+
1566+
if ty::type_has_rptrs(ty) {
1567+
ty::fold_ty(tcx, ty::fm_rptr({ |r|
1568+
alt r {
1569+
ty::re_param(n) {
1570+
if n < ufind::set_count(rb.sets) {
1571+
smallintmap::get(rb.regions, ufind::find(rb.sets, n))
1572+
} else {
1573+
tcx.sess.span_err(sp, "unresolved region");
1574+
r
1575+
}
1576+
}
1577+
_ { r }
1578+
}
1579+
}), ty)
1580+
} else {
1581+
ty
1582+
}
1583+
}
1584+
15571585
fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
15581586
subpats: [@ast::pat], expected: ty::t) {
15591587
// Typecheck the path.
@@ -2277,40 +2305,38 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
22772305
// A generic function for checking call expressions
22782306
fn check_call(fcx: @fn_ctxt, sp: span, id: ast::node_id, f: @ast::expr,
22792307
args: [@ast::expr])
2280-
-> bool {
2308+
-> check_call_or_bind_result {
22812309
let args_opt_0: [option<@ast::expr>] = [];
22822310
for arg: @ast::expr in args {
22832311
args_opt_0 += [some::<@ast::expr>(arg)];
22842312
}
22852313

2286-
let mut bot = check_expr(fcx, f);
2314+
let bot = check_expr(fcx, f);
22872315
// Call the generic checker.
22882316
let ccobr = check_call_or_bind(fcx, sp, id, expr_ty(fcx.ccx.tcx, f),
22892317
args_opt_0);
2290-
bot |= ccobr.bot;
2291-
2292-
// TODO: Munge return type.
2293-
2294-
ret bot;
2318+
ret { bot: bot | ccobr.bot with ccobr };
22952319
}
22962320

22972321
// A generic function for doing all of the checking for call expressions
22982322
fn check_call_full(fcx: @fn_ctxt, sp: span, id: ast::node_id,
22992323
f: @ast::expr, args: [@ast::expr]) -> bool {
2300-
let bot = check_call(fcx, sp, id, f, args);
2324+
let ccobr = check_call(fcx, sp, id, f, args);
2325+
let mut bot = ccobr.bot;
23012326
/* need to restrict oper to being an explicit expr_path if we're
23022327
inside a pure function */
23032328
require_pure_call(fcx.ccx, fcx.purity, f, sp);
23042329

23052330
// Pull the return type out of the type of the function.
23062331
let fty = ty::expr_ty(fcx.ccx.tcx, f);
2307-
let rt_1 = alt structure_of(fcx, sp, fty) {
2332+
let mut rt_1 = alt structure_of(fcx, sp, fty) {
23082333
ty::ty_fn(f) {
23092334
bot |= f.ret_style == ast::noreturn;
23102335
f.output
23112336
}
23122337
_ { fcx.ccx.tcx.sess.span_fatal(sp, "calling non-function"); }
23132338
};
2339+
rt_1 = replace_region_params(fcx.ccx.tcx, f.span, ccobr.rb, rt_1);
23142340
write_ty(fcx.ccx.tcx, id, rt_1);
23152341
ret bot;
23162342
}

0 commit comments

Comments
 (0)