aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Walton <[email protected]>2011-02-22 18:31:54 -0800
committerPatrick Walton <[email protected]>2011-02-22 18:33:07 -0800
commitb6f1c832e3c883a2ef2f5b47a68db79f33f5fb25 (patch)
tree6dd2833fb72f26b09e5d1659e5deb081d3f7e11e
parentUn-XFAIL argv.rs and command-line-args.rs. (diff)
downloadrust-b6f1c832e3c883a2ef2f5b47a68db79f33f5fb25.tar.xz
rust-b6f1c832e3c883a2ef2f5b47a68db79f33f5fb25.zip
rustc: Perform explicit type substitution as requested by the programmer
-rw-r--r--src/comp/middle/typeck.rs66
1 files changed, 66 insertions, 0 deletions
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 1b39cdf5..8f19e3ad 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -25,6 +25,7 @@ import middle.ty.type_is_scalar;
import std._str;
import std._uint;
import std._vec;
+import std.map;
import std.map.hashmap;
import std.option;
import std.option.none;
@@ -78,6 +79,65 @@ fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t {
ret ty.fold_ty(generalizer, t);
}
+// Substitutes the user's explicit types for the parameters in a path
+// expression.
+fn substitute_ty_params(&@crate_ctxt ccx,
+ @ty.t typ,
+ vec[@ast.ty] supplied,
+ &span sp) -> @ty.t {
+ state obj ty_substituter(@crate_ctxt ccx,
+ @mutable uint i,
+ vec[@ast.ty] supplied,
+ @hashmap[int,@ty.t] substs) {
+ fn fold_simple_ty(@ty.t typ) -> @ty.t {
+ alt (typ.struct) {
+ case (ty.ty_var(?vid)) {
+ alt (substs.find(vid)) {
+ case (some[@ty.t](?resolved_ty)) {
+ ret resolved_ty;
+ }
+ case (none[@ty.t]) {
+ if (i >= _vec.len[@ast.ty](supplied)) {
+ // Just leave it as an unresolved parameter
+ // for now. (We will error out later.)
+ ret typ;
+ }
+
+ auto result = ast_ty_to_ty_crate(ccx,
+ supplied.(*i));
+ *i += 1u;
+ substs.insert(vid, result);
+ ret result;
+ }
+ }
+ }
+ case (_) { ret typ; }
+ }
+ }
+ }
+
+ fn hash_int(&int x) -> uint { ret x as uint; }
+ fn eq_int(&int a, &int b) -> bool { ret a == b; }
+ auto hasher = hash_int;
+ auto eqer = eq_int;
+ auto substs = @map.mk_hashmap[int,@ty.t](hasher, eqer);
+
+ auto subst_count = @mutable 0u;
+ auto substituter = ty_substituter(ccx, subst_count, supplied, substs);
+
+ auto result = ty.fold_ty(substituter, typ);
+
+ auto supplied_len = _vec.len[@ast.ty](supplied);
+ if ((*subst_count) != supplied_len) {
+ ccx.sess.span_err(sp, "expected " + _uint.to_str(*subst_count, 10u) +
+ " type parameter(s) but found " +
+ _uint.to_str(supplied_len, 10u) + " parameter(s)");
+ fail;
+ }
+
+ ret result;
+}
+
// Parses the programmer's textual representation of a type into our internal
// notion of a type. `getter` is a function that returns the type
// corresponding to a definition ID.
@@ -1445,6 +1505,12 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
}
}
+ // Substitute type parameters if the user provided some.
+ if (_vec.len[@ast.ty](pth.node.types) > 0u) {
+ t = substitute_ty_params(fcx.ccx, t, pth.node.types,
+ expr.span);
+ }
+
ret @fold.respan[ast.expr_](expr.span,
ast.expr_path(pth, defopt,
ast.ann_type(t)));