From c8ab0c1b3b2b6af4e9efa96773926bfa2f58f016 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 21 Mar 2012 15:22:12 -0700 Subject: [PATCH] rustc: Replace region parameters in function return values --- src/rustc/middle/typeck.rs | 44 ++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 0b8f966fa58..8fba31e6daf 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -16,6 +16,7 @@ import std::smallintmap; import std::map::{hashmap, int_hash}; import std::serialization::{serialize_uint, deserialize_uint}; +import std::ufind; import syntax::print::pprust::*; export check_crate; @@ -1554,6 +1555,33 @@ fn universally_quantify_regions(tcx: ty::ctxt, ty: ty::t) -> ty::t { } } +// Replaces region parameter types in the given type with the appropriate +// bindings. +fn replace_region_params(tcx: ty::ctxt, + sp: span, + rb: @ty::unify::region_bindings, + ty: ty::t) + -> ty::t { + + if ty::type_has_rptrs(ty) { + ty::fold_ty(tcx, ty::fm_rptr({ |r| + alt r { + ty::re_param(n) { + if n < ufind::set_count(rb.sets) { + smallintmap::get(rb.regions, ufind::find(rb.sets, n)) + } else { + tcx.sess.span_err(sp, "unresolved region"); + r + } + } + _ { r } + } + }), ty) + } else { + ty + } +} + fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path, subpats: [@ast::pat], expected: ty::t) { // Typecheck the path. @@ -2277,40 +2305,38 @@ fn check_assignment(fcx: @fn_ctxt, _sp: span, lhs: @ast::expr, // A generic function for checking call expressions fn check_call(fcx: @fn_ctxt, sp: span, id: ast::node_id, f: @ast::expr, args: [@ast::expr]) - -> bool { + -> check_call_or_bind_result { let args_opt_0: [option<@ast::expr>] = []; for arg: @ast::expr in args { args_opt_0 += [some::<@ast::expr>(arg)]; } - let mut bot = check_expr(fcx, f); + let bot = check_expr(fcx, f); // Call the generic checker. let ccobr = check_call_or_bind(fcx, sp, id, expr_ty(fcx.ccx.tcx, f), args_opt_0); - bot |= ccobr.bot; - - // TODO: Munge return type. - - ret bot; + ret { bot: bot | ccobr.bot with ccobr }; } // A generic function for doing all of the checking for call expressions fn check_call_full(fcx: @fn_ctxt, sp: span, id: ast::node_id, f: @ast::expr, args: [@ast::expr]) -> bool { - let bot = check_call(fcx, sp, id, f, args); + let ccobr = check_call(fcx, sp, id, f, args); + let mut bot = ccobr.bot; /* need to restrict oper to being an explicit expr_path if we're inside a pure function */ require_pure_call(fcx.ccx, fcx.purity, f, sp); // Pull the return type out of the type of the function. let fty = ty::expr_ty(fcx.ccx.tcx, f); - let rt_1 = alt structure_of(fcx, sp, fty) { + let mut rt_1 = alt structure_of(fcx, sp, fty) { ty::ty_fn(f) { bot |= f.ret_style == ast::noreturn; f.output } _ { fcx.ccx.tcx.sess.span_fatal(sp, "calling non-function"); } }; + rt_1 = replace_region_params(fcx.ccx.tcx, f.span, ccobr.rb, rt_1); write_ty(fcx.ccx.tcx, id, rt_1); ret bot; } -- GitLab