diff options
| author | Patrick Walton <[email protected]> | 2011-02-22 18:31:54 -0800 |
|---|---|---|
| committer | Patrick Walton <[email protected]> | 2011-02-22 18:33:07 -0800 |
| commit | b6f1c832e3c883a2ef2f5b47a68db79f33f5fb25 (patch) | |
| tree | 6dd2833fb72f26b09e5d1659e5deb081d3f7e11e | |
| parent | Un-XFAIL argv.rs and command-line-args.rs. (diff) | |
| download | rust-b6f1c832e3c883a2ef2f5b47a68db79f33f5fb25.tar.xz rust-b6f1c832e3c883a2ef2f5b47a68db79f33f5fb25.zip | |
rustc: Perform explicit type substitution as requested by the programmer
| -rw-r--r-- | src/comp/middle/typeck.rs | 66 |
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))); |