about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-03-21 15:22:12 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-03-21 15:22:12 -0700
commitc8ab0c1b3b2b6af4e9efa96773926bfa2f58f016 (patch)
tree55ad92b587e9874f31477f56b86d1c475003800e /src/rustc
parent324f57a180ed2c80b17894ccd0b0b75aab14ec97 (diff)
downloadrust-c8ab0c1b3b2b6af4e9efa96773926bfa2f58f016.tar.gz
rust-c8ab0c1b3b2b6af4e9efa96773926bfa2f58f016.zip
rustc: Replace region parameters in function return values
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/middle/typeck.rs44
1 files 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 util::ppaux::ty_to_str;
 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_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
     // 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;
     }