rewrite region resolution so it takes place in typeck
This commit is contained in:
parent
a532ad2828
commit
35a93e61d4
15 changed files with 1043 additions and 912 deletions
|
@ -1270,7 +1270,7 @@ are written after the name of the implementation, or if that is not
|
||||||
specified, after the `impl` keyword.
|
specified, after the `impl` keyword.
|
||||||
|
|
||||||
~~~~
|
~~~~
|
||||||
# iface seq { }
|
# iface seq<T> { }
|
||||||
|
|
||||||
impl <T> of seq<T> for [T] {
|
impl <T> of seq<T> for [T] {
|
||||||
/* ... */
|
/* ... */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
$ident = 0;
|
$indent = 0;
|
||||||
while (<>) {
|
while (<>) {
|
||||||
if (/^rust: ">>/) {
|
if (/^rust: ">>/) {
|
||||||
$indent += 1;
|
$indent += 1;
|
||||||
|
|
|
@ -101,6 +101,15 @@ impl extensions<T:copy> for option<T> {
|
||||||
#[doc = "Performs an operation on the contained value or does nothing"]
|
#[doc = "Performs an operation on the contained value or does nothing"]
|
||||||
fn iter(f: fn(T)) { iter(self, f) }
|
fn iter(f: fn(T)) { iter(self, f) }
|
||||||
|
|
||||||
|
#[doc = "Converts `none` to a zero-element list and `some` to a \
|
||||||
|
one-element list."]
|
||||||
|
fn to_vec() -> [T] {
|
||||||
|
alt self {
|
||||||
|
some(t) { [t] }
|
||||||
|
none { [] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[doc = "Performs an operation on the contained value or does nothing"]
|
#[doc = "Performs an operation on the contained value or does nothing"]
|
||||||
fn each(f: fn(T) -> bool) {
|
fn each(f: fn(T) -> bool) {
|
||||||
alt self {
|
alt self {
|
||||||
|
|
|
@ -451,9 +451,8 @@ type region = {id: node_id, node: region_};
|
||||||
|
|
||||||
#[auto_serialize]
|
#[auto_serialize]
|
||||||
enum region_ {
|
enum region_ {
|
||||||
re_inferred,
|
re_anon,
|
||||||
re_named(ident),
|
re_named(ident),
|
||||||
re_self,
|
|
||||||
re_static
|
re_static
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -451,15 +451,13 @@ fn parse_ret_ty(p: parser) -> (ast::ret_style, @ast::ty) {
|
||||||
fn region_from_name(p: parser, s: option<str>) -> ast::region {
|
fn region_from_name(p: parser, s: option<str>) -> ast::region {
|
||||||
let r = alt s {
|
let r = alt s {
|
||||||
some (string) {
|
some (string) {
|
||||||
if string == "self" {
|
if string == "static" {
|
||||||
ast::re_self
|
|
||||||
} else if string == "static" {
|
|
||||||
ast::re_static
|
ast::re_static
|
||||||
} else {
|
} else {
|
||||||
ast::re_named(string)
|
ast::re_named(string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
none { ast::re_inferred }
|
none { ast::re_anon }
|
||||||
};
|
};
|
||||||
|
|
||||||
{id: p.get_id(), node: r}
|
{id: p.get_id(), node: r}
|
||||||
|
|
|
@ -320,9 +320,8 @@ fn print_native_mod(s: ps, nmod: ast::native_mod, attrs: [ast::attribute]) {
|
||||||
|
|
||||||
fn print_region(s: ps, region: ast::region) {
|
fn print_region(s: ps, region: ast::region) {
|
||||||
alt region.node {
|
alt region.node {
|
||||||
ast::re_inferred { /* no-op */ }
|
ast::re_anon { /* no-op */ }
|
||||||
ast::re_named(name) { word(s.s, name); word(s.s, "."); }
|
ast::re_named(name) { word(s.s, name); word(s.s, "."); }
|
||||||
ast::re_self { word(s.s, "self"); word(s.s, "."); }
|
|
||||||
ast::re_static { word(s.s, "static"); word(s.s, "."); }
|
ast::re_static { word(s.s, "static"); word(s.s, "."); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -826,8 +825,7 @@ fn print_vstore(s: ps, t: ast::vstore) {
|
||||||
ast::vstore_box { word_space(s, "/@"); }
|
ast::vstore_box { word_space(s, "/@"); }
|
||||||
ast::vstore_slice(r) {
|
ast::vstore_slice(r) {
|
||||||
alt r.node {
|
alt r.node {
|
||||||
ast::re_inferred { word_space(s, "/&"); }
|
ast::re_anon { word_space(s, "/&"); }
|
||||||
ast::re_self { word_space(s, "/&self"); }
|
|
||||||
ast::re_static { word_space(s, "/&static"); }
|
ast::re_static { word_space(s, "/&static"); }
|
||||||
ast::re_named(name) {
|
ast::re_named(name) {
|
||||||
word(s.s, "/&");
|
word(s.s, "/&");
|
||||||
|
|
|
@ -104,10 +104,8 @@ fn enc_bound_region(w: io::writer, br: ty::bound_region) {
|
||||||
alt br {
|
alt br {
|
||||||
ty::br_self { w.write_char('s') }
|
ty::br_self { w.write_char('s') }
|
||||||
ty::br_anon { w.write_char('a') }
|
ty::br_anon { w.write_char('a') }
|
||||||
ty::br_param(id, s) {
|
ty::br_named(s) {
|
||||||
w.write_char('[');
|
w.write_char('[');
|
||||||
w.write_uint(id);
|
|
||||||
w.write_char('|');
|
|
||||||
w.write_str(s);
|
w.write_str(s);
|
||||||
w.write_char(']')
|
w.write_char(']')
|
||||||
}
|
}
|
||||||
|
@ -132,9 +130,6 @@ fn enc_region(w: io::writer, r: ty::region) {
|
||||||
w.write_int(nid);
|
w.write_int(nid);
|
||||||
w.write_char('|');
|
w.write_char('|');
|
||||||
}
|
}
|
||||||
ty::re_default {
|
|
||||||
w.write_char('i');
|
|
||||||
}
|
|
||||||
ty::re_var(id) {
|
ty::re_var(id) {
|
||||||
w.write_char('v');
|
w.write_char('v');
|
||||||
w.write_uint(id.to_uint());
|
w.write_uint(id.to_uint());
|
||||||
|
|
|
@ -592,7 +592,7 @@ impl resolve_methods for infer_ctxt {
|
||||||
self.rb,
|
self.rb,
|
||||||
{|_t| false },
|
{|_t| false },
|
||||||
rid,
|
rid,
|
||||||
{|| err(unresolved_region(rid)) });
|
{|| ok(ty::re_static) });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_ty(typ: ty::t) -> fres<ty::t> {
|
fn resolve_ty(typ: ty::t) -> fres<ty::t> {
|
||||||
|
@ -1169,7 +1169,10 @@ impl of combine for sub {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn regions(a: ty::region, b: ty::region) -> cres<ty::region> {
|
fn regions(a: ty::region, b: ty::region) -> cres<ty::region> {
|
||||||
#debug["regions(%s <= %s)", a.to_str(*self), b.to_str(*self)];
|
#debug["%s.regions(%s, %s)",
|
||||||
|
self.tag(),
|
||||||
|
a.to_str(self.infcx()),
|
||||||
|
b.to_str(self.infcx())];
|
||||||
indent {||
|
indent {||
|
||||||
alt (a, b) {
|
alt (a, b) {
|
||||||
(ty::re_var(a_id), ty::re_var(b_id)) {
|
(ty::re_var(a_id), ty::re_var(b_id)) {
|
||||||
|
@ -1376,8 +1379,7 @@ impl of combine for lub {
|
||||||
{|x, y| self.regions(x, y) })
|
{|x, y| self.regions(x, y) })
|
||||||
}
|
}
|
||||||
|
|
||||||
(ty::re_var(v_id), r) |
|
(ty::re_var(v_id), r) | (r, ty::re_var(v_id)) {
|
||||||
(r, ty::re_var(v_id)) {
|
|
||||||
lattice_var_t(self, self.infcx().rb,
|
lattice_var_t(self, self.infcx().rb,
|
||||||
v_id, r,
|
v_id, r,
|
||||||
{|x, y| self.regions(x, y) })
|
{|x, y| self.regions(x, y) })
|
||||||
|
@ -1415,12 +1417,6 @@ impl of combine for lub {
|
||||||
err(ty::terr_regions_differ(b, a))
|
err(ty::terr_regions_differ(b, a))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(ty::re_default, _) |
|
|
||||||
(_, ty::re_default) {
|
|
||||||
// actually a compiler bug, I think.
|
|
||||||
err(ty::terr_regions_differ(b, a))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1561,10 +1557,10 @@ impl of combine for glb {
|
||||||
{|x, y| self.regions(x, y) })
|
{|x, y| self.regions(x, y) })
|
||||||
}
|
}
|
||||||
|
|
||||||
(ty::re_var(v_id), _) | (_, ty::re_var(v_id)) {
|
(ty::re_var(v_id), r) | (r, ty::re_var(v_id)) {
|
||||||
lattice_var_t(self, self.infcx().rb,
|
lattice_var_t(self, self.infcx().rb,
|
||||||
v_id, b,
|
v_id, r,
|
||||||
{|x, y| self.regions(x, y) })
|
{|x, y| self.regions(x, y) })
|
||||||
}
|
}
|
||||||
|
|
||||||
(f @ ty::re_free(f_id, f_br), ty::re_scope(s_id)) |
|
(f @ ty::re_free(f_id, f_br), ty::re_scope(s_id)) |
|
||||||
|
@ -1601,12 +1597,6 @@ impl of combine for glb {
|
||||||
err(ty::terr_regions_differ(b, a))
|
err(ty::terr_regions_differ(b, a))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(ty::re_default, _) |
|
|
||||||
(_, ty::re_default) {
|
|
||||||
// actually a compiler bug, I think.
|
|
||||||
err(ty::terr_regions_differ(b, a))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1727,7 +1717,7 @@ fn lattice_vars<V:copy vid, T:copy to_str st, L:lattice_ops combine>(
|
||||||
let {root: a_vid, bounds: a_bounds} = self.infcx().get(vb, a_vid);
|
let {root: a_vid, bounds: a_bounds} = self.infcx().get(vb, a_vid);
|
||||||
let {root: b_vid, bounds: b_bounds} = self.infcx().get(vb, b_vid);
|
let {root: b_vid, bounds: b_bounds} = self.infcx().get(vb, b_vid);
|
||||||
|
|
||||||
#debug["%s.vars(%s=%s <: %s=%s)",
|
#debug["%s.lattice_vars(%s=%s <: %s=%s)",
|
||||||
self.tag(),
|
self.tag(),
|
||||||
a_vid.to_str(), a_bounds.to_str(self.infcx()),
|
a_vid.to_str(), a_bounds.to_str(self.infcx()),
|
||||||
b_vid.to_str(), b_bounds.to_str(self.infcx())];
|
b_vid.to_str(), b_bounds.to_str(self.infcx())];
|
||||||
|
@ -1758,15 +1748,15 @@ fn lattice_vars<V:copy vid, T:copy to_str st, L:lattice_ops combine>(
|
||||||
|
|
||||||
fn lattice_var_t<V:copy vid, T:copy to_str st, L:lattice_ops combine>(
|
fn lattice_var_t<V:copy vid, T:copy to_str st, L:lattice_ops combine>(
|
||||||
self: L, vb: vals_and_bindings<V, T>,
|
self: L, vb: vals_and_bindings<V, T>,
|
||||||
a_vid: V, b: T,
|
a_id: V, b: T,
|
||||||
c_ts: fn(T, T) -> cres<T>) -> cres<T> {
|
c_ts: fn(T, T) -> cres<T>) -> cres<T> {
|
||||||
|
|
||||||
let {root: a_id, bounds: a_bounds} = self.infcx().get(vb, a_vid);
|
let {root: a_id, bounds: a_bounds} = self.infcx().get(vb, a_id);
|
||||||
|
|
||||||
// The comments in this function are written for LUB, but they
|
// The comments in this function are written for LUB, but they
|
||||||
// apply equally well to GLB if you inverse upper/lower/sub/super/etc.
|
// apply equally well to GLB if you inverse upper/lower/sub/super/etc.
|
||||||
|
|
||||||
#debug["%s.var_ty(%s=%s <: %s)",
|
#debug["%s.lattice_vart(%s=%s <: %s)",
|
||||||
self.tag(),
|
self.tag(),
|
||||||
a_id.to_str(), a_bounds.to_str(self.infcx()),
|
a_id.to_str(), a_bounds.to_str(self.infcx()),
|
||||||
b.to_str(self.infcx())];
|
b.to_str(self.infcx())];
|
||||||
|
|
|
@ -162,12 +162,9 @@ type binding = {node_id: ast::node_id,
|
||||||
type region_map = {
|
type region_map = {
|
||||||
/* Mapping from a block/function expression to its parent. */
|
/* Mapping from a block/function expression to its parent. */
|
||||||
parents: hashmap<ast::node_id,ast::node_id>,
|
parents: hashmap<ast::node_id,ast::node_id>,
|
||||||
/* Mapping from a region type in the AST to its resolved region. */
|
|
||||||
ast_type_to_region: hashmap<ast::node_id,ty::region>,
|
|
||||||
/* Mapping from a local variable to its containing block. */
|
/* Mapping from a local variable to its containing block. */
|
||||||
local_blocks: hashmap<ast::node_id,ast::node_id>,
|
local_blocks: hashmap<ast::node_id,ast::node_id>
|
||||||
/* Mapping from an AST type node to the region that `&` resolves to. */
|
|
||||||
ast_type_to_inferred_region: hashmap<ast::node_id,ty::region>,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type region_scope = @{
|
type region_scope = @{
|
||||||
|
@ -198,69 +195,6 @@ impl methods for region_scope {
|
||||||
fn self_subscope(node_id: ast::node_id) -> region_scope {
|
fn self_subscope(node_id: ast::node_id) -> region_scope {
|
||||||
@{node_id: node_id, kind: rsk_self(self)}
|
@{node_id: node_id, kind: rsk_self(self)}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find(nm: str) -> option<binding> {
|
|
||||||
alt self.kind {
|
|
||||||
rsk_root { none }
|
|
||||||
rsk_body(parent) { parent.find(nm) }
|
|
||||||
rsk_self(parent) { parent.find(nm) }
|
|
||||||
rsk_binding(parent, bs) {
|
|
||||||
alt (*bs).find({|b| b.name == nm }) {
|
|
||||||
none { parent.find(nm) }
|
|
||||||
some(b) { some(b) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fn resolve_anon() -> option<ty::region> {
|
|
||||||
// alt self.kind {
|
|
||||||
// rsk_root { none }
|
|
||||||
// rsk_body(_) { none }
|
|
||||||
// rsk_self(_) { none }
|
|
||||||
// rsk_binding(_, _) { ty::re_bound(ty::br_anon) }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn resolve_self_helper(bound: bool) -> option<ty::region> {
|
|
||||||
alt self.kind {
|
|
||||||
rsk_root { none }
|
|
||||||
rsk_self(_) if bound { some(ty::re_bound(ty::br_self)) }
|
|
||||||
rsk_self(_) { some(ty::re_free(self.node_id, ty::br_self)) }
|
|
||||||
rsk_binding(p, _) { p.resolve_self_helper(bound) }
|
|
||||||
rsk_body(p) { p.resolve_self_helper(false) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_self() -> option<ty::region> {
|
|
||||||
self.resolve_self_helper(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_ident(nm: str) -> option<ty::region> {
|
|
||||||
alt self.find(nm) {
|
|
||||||
some(b) if b.node_id == self.node_id {
|
|
||||||
some(ty::re_bound(b.br))
|
|
||||||
}
|
|
||||||
|
|
||||||
some(b) {
|
|
||||||
some(ty::re_free(b.node_id, b.br))
|
|
||||||
}
|
|
||||||
|
|
||||||
none {
|
|
||||||
alt self.kind {
|
|
||||||
rsk_self(_) | rsk_root | rsk_body(_) { none }
|
|
||||||
rsk_binding(_, bs) {
|
|
||||||
let idx = (*bs).len();
|
|
||||||
let br = ty::br_param(idx, nm);
|
|
||||||
vec::push(*bs, {node_id: self.node_id,
|
|
||||||
name: nm,
|
|
||||||
br: br});
|
|
||||||
some(ty::re_bound(br))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ctxt = {
|
type ctxt = {
|
||||||
|
@ -351,50 +285,6 @@ fn get_inferred_region(cx: ctxt, sp: syntax::codemap::span) -> ty::region {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_region_binding(cx: ctxt, span: span,
|
|
||||||
region: ast::region) -> ty::region {
|
|
||||||
alt region.node {
|
|
||||||
ast::re_inferred { ty::re_default }
|
|
||||||
ast::re_static { ty::re_static }
|
|
||||||
ast::re_named(ident) {
|
|
||||||
alt cx.scope.resolve_ident(ident) {
|
|
||||||
some(r) { r }
|
|
||||||
none {
|
|
||||||
cx.sess.span_fatal(
|
|
||||||
span,
|
|
||||||
#fmt["the region `%s` is not declared", ident]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ast::re_self {
|
|
||||||
alt cx.scope.resolve_self() {
|
|
||||||
some(r) { r }
|
|
||||||
none {
|
|
||||||
cx.sess.span_fatal(
|
|
||||||
span,
|
|
||||||
"the `self` region is not allowed here");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt<ctxt>) {
|
|
||||||
let inferred_region = get_inferred_region(cx, ty.span);
|
|
||||||
cx.region_map.ast_type_to_inferred_region.insert(ty.id, inferred_region);
|
|
||||||
|
|
||||||
alt ty.node {
|
|
||||||
ast::ty_vstore(_, ast::vstore_slice(r)) |
|
|
||||||
ast::ty_rptr(r, _) {
|
|
||||||
let region = resolve_region_binding(cx, ty.span, r);
|
|
||||||
cx.region_map.ast_type_to_region.insert(ty.id, region);
|
|
||||||
}
|
|
||||||
_ { /* nothing to do */ }
|
|
||||||
}
|
|
||||||
|
|
||||||
visit::visit_ty(ty, cx, visitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn opt_parent_id(cx: ctxt) -> option<ast::node_id> {
|
fn opt_parent_id(cx: ctxt) -> option<ast::node_id> {
|
||||||
alt cx.parent {
|
alt cx.parent {
|
||||||
pa_fn_item(parent_id) |
|
pa_fn_item(parent_id) |
|
||||||
|
@ -531,16 +421,12 @@ fn resolve_crate(sess: session, def_map: resolve::def_map, crate: @ast::crate)
|
||||||
let cx: ctxt = {sess: sess,
|
let cx: ctxt = {sess: sess,
|
||||||
def_map: def_map,
|
def_map: def_map,
|
||||||
region_map: @{parents: map::int_hash(),
|
region_map: @{parents: map::int_hash(),
|
||||||
ast_type_to_region: map::int_hash(),
|
local_blocks: map::int_hash()},
|
||||||
local_blocks: map::int_hash(),
|
|
||||||
ast_type_to_inferred_region:
|
|
||||||
map::int_hash()},
|
|
||||||
scope: root_scope(0),
|
scope: root_scope(0),
|
||||||
parent: pa_crate};
|
parent: pa_crate};
|
||||||
let visitor = visit::mk_vt(@{
|
let visitor = visit::mk_vt(@{
|
||||||
visit_block: resolve_block,
|
visit_block: resolve_block,
|
||||||
visit_item: resolve_item,
|
visit_item: resolve_item,
|
||||||
visit_ty: resolve_ty,
|
|
||||||
visit_arm: resolve_arm,
|
visit_arm: resolve_arm,
|
||||||
visit_pat: resolve_pat,
|
visit_pat: resolve_pat,
|
||||||
visit_expr: resolve_expr,
|
visit_expr: resolve_expr,
|
||||||
|
|
|
@ -15,12 +15,13 @@ fn check_expr(expr: @ast::expr,
|
||||||
visit::visit_expr(expr, tcx, visitor);
|
visit::visit_expr(expr, tcx, visitor);
|
||||||
|
|
||||||
let t = ty::expr_ty(tcx, expr);
|
let t = ty::expr_ty(tcx, expr);
|
||||||
if !ty::type_has_rptrs(t) { ret; }
|
if !ty::type_has_regions(t) { ret; }
|
||||||
ty::walk_ty(t) { |t|
|
ty::walk_ty(t) { |t|
|
||||||
alt ty::get(t).struct {
|
alt ty::get(t).struct {
|
||||||
ty::ty_rptr(region, _) {
|
ty::ty_rptr(region, _) {
|
||||||
alt region {
|
alt region {
|
||||||
ty::re_bound(_) | ty::re_free(_, _) | ty::re_static {
|
ty::re_bound(_) | ty::re_free(_, _) | ty::re_static |
|
||||||
|
ty::re_var(_) {
|
||||||
/* ok */
|
/* ok */
|
||||||
}
|
}
|
||||||
ty::re_scope(id) {
|
ty::re_scope(id) {
|
||||||
|
@ -31,9 +32,6 @@ fn check_expr(expr: @ast::expr,
|
||||||
ppaux::re_scope_id_to_str(tcx, id)]);
|
ppaux::re_scope_id_to_str(tcx, id)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::re_default | ty::re_var(_) {
|
|
||||||
tcx.sess.span_bug(expr.span, "unresolved region");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ { /* no-op */ }
|
_ { /* no-op */ }
|
||||||
|
|
|
@ -36,7 +36,7 @@ export expr_ty;
|
||||||
export expr_ty_params_and_ty;
|
export expr_ty_params_and_ty;
|
||||||
export expr_is_lval;
|
export expr_is_lval;
|
||||||
export field_ty;
|
export field_ty;
|
||||||
export fold_ty, fold_sty_to_ty, fold_region, fold_ty_var;
|
export fold_ty, fold_sty_to_ty, fold_region, fold_regions, fold_ty_var;
|
||||||
export field;
|
export field;
|
||||||
export field_idx;
|
export field_idx;
|
||||||
export get_field;
|
export get_field;
|
||||||
|
@ -99,7 +99,7 @@ export ty_uniq, mk_uniq, mk_imm_uniq, type_is_unique_box;
|
||||||
export ty_var, mk_var;
|
export ty_var, mk_var;
|
||||||
export ty_self, mk_self;
|
export ty_self, mk_self;
|
||||||
export region, bound_region;
|
export region, bound_region;
|
||||||
export get, type_has_params, type_has_vars, type_has_rptrs, type_id;
|
export get, type_has_params, type_has_vars, type_has_regions, type_id;
|
||||||
export ty_var_id;
|
export ty_var_id;
|
||||||
export ty_to_def_id;
|
export ty_to_def_id;
|
||||||
export ty_fn_args;
|
export ty_fn_args;
|
||||||
|
@ -230,7 +230,7 @@ type t_box = @{struct: sty,
|
||||||
id: uint,
|
id: uint,
|
||||||
has_params: bool,
|
has_params: bool,
|
||||||
has_vars: bool,
|
has_vars: bool,
|
||||||
has_rptrs: bool,
|
has_regions: bool,
|
||||||
o_def_id: option<ast::def_id>};
|
o_def_id: option<ast::def_id>};
|
||||||
|
|
||||||
// To reduce refcounting cost, we're representing types as unsafe pointers
|
// To reduce refcounting cost, we're representing types as unsafe pointers
|
||||||
|
@ -250,7 +250,7 @@ pure fn get(t: t) -> t_box unsafe {
|
||||||
|
|
||||||
fn type_has_params(t: t) -> bool { get(t).has_params }
|
fn type_has_params(t: t) -> bool { get(t).has_params }
|
||||||
fn type_has_vars(t: t) -> bool { get(t).has_vars }
|
fn type_has_vars(t: t) -> bool { get(t).has_vars }
|
||||||
fn type_has_rptrs(t: t) -> bool { get(t).has_rptrs }
|
fn type_has_regions(t: t) -> bool { get(t).has_regions }
|
||||||
fn type_def_id(t: t) -> option<ast::def_id> { get(t).o_def_id }
|
fn type_def_id(t: t) -> option<ast::def_id> { get(t).o_def_id }
|
||||||
fn type_id(t: t) -> uint { get(t).id }
|
fn type_id(t: t) -> uint { get(t).id }
|
||||||
|
|
||||||
|
@ -272,20 +272,13 @@ enum region {
|
||||||
re_free(node_id, bound_region),
|
re_free(node_id, bound_region),
|
||||||
re_scope(node_id),
|
re_scope(node_id),
|
||||||
re_var(region_vid),
|
re_var(region_vid),
|
||||||
re_static, // effectively `top` in the region lattice
|
re_static // effectively `top` in the region lattice
|
||||||
re_default
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum bound_region {
|
enum bound_region {
|
||||||
// The `self` region for a given class/impl/iface. The defining item may
|
br_self, // The self region for classes, impls
|
||||||
// appear in another crate.
|
br_anon, // The anonymous region parameter for a given function.
|
||||||
br_self,
|
br_named(str) // A named region parameter.
|
||||||
|
|
||||||
// The anonymous region parameter for a given function.
|
|
||||||
br_anon,
|
|
||||||
|
|
||||||
// A named region parameter.
|
|
||||||
br_param(uint, str)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB: If you change this, you'll probably want to change the corresponding
|
// NB: If you change this, you'll probably want to change the corresponding
|
||||||
|
@ -461,21 +454,21 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t {
|
||||||
some(t) { unsafe { ret unsafe::reinterpret_cast(t); } }
|
some(t) { unsafe { ret unsafe::reinterpret_cast(t); } }
|
||||||
_ {}
|
_ {}
|
||||||
}
|
}
|
||||||
let mut has_params = false, has_vars = false, has_rptrs = false;
|
let mut has_params = false, has_vars = false, has_regions = false;
|
||||||
fn derive_flags(&has_params: bool, &has_vars: bool, &has_rptrs: bool,
|
fn derive_flags(&has_params: bool, &has_vars: bool, &has_regions: bool,
|
||||||
tt: t) {
|
tt: t) {
|
||||||
let t = get(tt);
|
let t = get(tt);
|
||||||
has_params |= t.has_params;
|
has_params |= t.has_params;
|
||||||
has_vars |= t.has_vars;
|
has_vars |= t.has_vars;
|
||||||
has_rptrs |= t.has_rptrs;
|
has_regions |= t.has_regions;
|
||||||
}
|
}
|
||||||
alt st {
|
alt st {
|
||||||
ty_estr(vstore_slice(_)) {
|
ty_estr(vstore_slice(_)) {
|
||||||
has_rptrs = true;
|
has_regions = true;
|
||||||
}
|
}
|
||||||
ty_evec(mt, vstore_slice(_)) {
|
ty_evec(mt, vstore_slice(_)) {
|
||||||
has_rptrs = true;
|
has_regions = true;
|
||||||
derive_flags(has_params, has_vars, has_rptrs, mt.ty);
|
derive_flags(has_params, has_vars, has_regions, mt.ty);
|
||||||
}
|
}
|
||||||
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
|
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
|
||||||
ty_str | ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) |
|
ty_str | ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) |
|
||||||
|
@ -484,49 +477,50 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t {
|
||||||
ty_var(_) | ty_self(_) { has_vars = true; }
|
ty_var(_) | ty_self(_) { has_vars = true; }
|
||||||
ty_enum(_, tys) | ty_iface(_, tys) | ty_class(_, tys) {
|
ty_enum(_, tys) | ty_iface(_, tys) | ty_class(_, tys) {
|
||||||
for tys.each {|tt|
|
for tys.each {|tt|
|
||||||
derive_flags(has_params, has_vars, has_rptrs, tt);
|
derive_flags(has_params, has_vars, has_regions, tt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty_box(m) | ty_uniq(m) | ty_vec(m) | ty_evec(m, _) | ty_ptr(m) {
|
ty_box(m) | ty_uniq(m) | ty_vec(m) | ty_evec(m, _) | ty_ptr(m) {
|
||||||
derive_flags(has_params, has_vars, has_rptrs, m.ty);
|
derive_flags(has_params, has_vars, has_regions, m.ty);
|
||||||
}
|
}
|
||||||
ty_rptr(r, m) {
|
ty_rptr(r, m) {
|
||||||
alt r {
|
alt r {
|
||||||
ty::re_var(_) { has_vars = true; }
|
ty::re_var(_) { has_vars = true; }
|
||||||
_ { }
|
_ { }
|
||||||
}
|
}
|
||||||
has_rptrs = true;
|
has_regions = true;
|
||||||
derive_flags(has_params, has_vars, has_rptrs, m.ty);
|
derive_flags(has_params, has_vars, has_regions, m.ty);
|
||||||
}
|
}
|
||||||
ty_rec(flds) {
|
ty_rec(flds) {
|
||||||
for flds.each {|f|
|
for flds.each {|f|
|
||||||
derive_flags(has_params, has_vars, has_rptrs, f.mt.ty);
|
derive_flags(has_params, has_vars, has_regions, f.mt.ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty_tup(ts) {
|
ty_tup(ts) {
|
||||||
for ts.each {|tt| derive_flags(has_params, has_vars, has_rptrs, tt); }
|
for ts.each {|tt| derive_flags(has_params, has_vars,
|
||||||
|
has_regions, tt); }
|
||||||
}
|
}
|
||||||
ty_fn(f) {
|
ty_fn(f) {
|
||||||
for f.inputs.each {|a|
|
for f.inputs.each {|a|
|
||||||
derive_flags(has_params, has_vars, has_rptrs, a.ty);
|
derive_flags(has_params, has_vars, has_regions, a.ty);
|
||||||
}
|
}
|
||||||
derive_flags(has_params, has_vars, has_rptrs, f.output);
|
derive_flags(has_params, has_vars, has_regions, f.output);
|
||||||
}
|
}
|
||||||
ty_res(_, tt, tps) {
|
ty_res(_, tt, tps) {
|
||||||
derive_flags(has_params, has_vars, has_rptrs, tt);
|
derive_flags(has_params, has_vars, has_regions, tt);
|
||||||
for tps.each {|tt|
|
for tps.each {|tt|
|
||||||
derive_flags(has_params, has_vars, has_rptrs, tt);
|
derive_flags(has_params, has_vars, has_regions, tt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty_constr(tt, _) {
|
ty_constr(tt, _) {
|
||||||
derive_flags(has_params, has_vars, has_rptrs, tt);
|
derive_flags(has_params, has_vars, has_regions, tt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let t = @{struct: st,
|
let t = @{struct: st,
|
||||||
id: cx.next_id,
|
id: cx.next_id,
|
||||||
has_params: has_params,
|
has_params: has_params,
|
||||||
has_vars: has_vars,
|
has_vars: has_vars,
|
||||||
has_rptrs: has_rptrs,
|
has_regions: has_regions,
|
||||||
o_def_id: o_def_id};
|
o_def_id: o_def_id};
|
||||||
cx.interner.insert(key, t);
|
cx.interner.insert(key, t);
|
||||||
cx.next_id += 1u;
|
cx.next_id += 1u;
|
||||||
|
@ -771,11 +765,53 @@ fn fold_ty_var(cx: ctxt, t0: t, fldop: fn(ty_vid) -> t) -> t {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// n.b. this function is intended to eventually replace fold_region() below,
|
||||||
|
// that is why its name is so similar.
|
||||||
|
fn fold_regions(
|
||||||
|
cx: ctxt,
|
||||||
|
ty: t,
|
||||||
|
fldr: fn(r: region, in_fn: bool) -> region) -> t {
|
||||||
|
|
||||||
|
fn do_fold(cx: ctxt, ty: t, in_fn: bool,
|
||||||
|
fldr: fn(region, bool) -> region) -> t {
|
||||||
|
let tb = ty::get(ty);
|
||||||
|
if !tb.has_regions { ret ty; }
|
||||||
|
alt tb.struct {
|
||||||
|
ty::ty_rptr(r, mt) {
|
||||||
|
let m_r = fldr(r, in_fn);
|
||||||
|
let m_t = do_fold(cx, mt.ty, in_fn, fldr);
|
||||||
|
ty::mk_rptr(cx, m_r, {ty: m_t, mutbl: mt.mutbl})
|
||||||
|
}
|
||||||
|
ty_estr(vstore_slice(r)) {
|
||||||
|
let m_r = fldr(r, in_fn);
|
||||||
|
ty::mk_estr(cx, vstore_slice(m_r))
|
||||||
|
}
|
||||||
|
ty_evec(mt, vstore_slice(r)) {
|
||||||
|
let m_r = fldr(r, in_fn);
|
||||||
|
let m_t = do_fold(cx, mt.ty, in_fn, fldr);
|
||||||
|
ty::mk_evec(cx, {ty: m_t, mutbl: mt.mutbl}, vstore_slice(m_r))
|
||||||
|
}
|
||||||
|
sty @ ty_fn(_) {
|
||||||
|
fold_sty_to_ty(cx, sty) {|t|
|
||||||
|
do_fold(cx, t, true, fldr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sty {
|
||||||
|
fold_sty_to_ty(cx, sty) {|t|
|
||||||
|
do_fold(cx, t, in_fn, fldr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do_fold(cx, ty, false, fldr)
|
||||||
|
}
|
||||||
|
|
||||||
fn fold_region(cx: ctxt, t0: t, fldop: fn(region, bool) -> region) -> t {
|
fn fold_region(cx: ctxt, t0: t, fldop: fn(region, bool) -> region) -> t {
|
||||||
fn do_fold(cx: ctxt, t0: t, under_r: bool,
|
fn do_fold(cx: ctxt, t0: t, under_r: bool,
|
||||||
fldop: fn(region, bool) -> region) -> t {
|
fldop: fn(region, bool) -> region) -> t {
|
||||||
let tb = get(t0);
|
let tb = get(t0);
|
||||||
if !tb.has_rptrs { ret t0; }
|
if !tb.has_regions { ret t0; }
|
||||||
alt tb.struct {
|
alt tb.struct {
|
||||||
ty_rptr(r, {ty: t1, mutbl: m}) {
|
ty_rptr(r, {ty: t1, mutbl: m}) {
|
||||||
let m_r = fldop(r, under_r);
|
let m_r = fldop(r, under_r);
|
||||||
|
@ -1544,9 +1580,9 @@ fn type_autoderef(cx: ctxt, t: t) -> t {
|
||||||
|
|
||||||
fn hash_bound_region(br: bound_region) -> uint {
|
fn hash_bound_region(br: bound_region) -> uint {
|
||||||
alt br { // no idea if this is any good
|
alt br { // no idea if this is any good
|
||||||
br_self { 0u }
|
ty::br_self { 0u }
|
||||||
br_anon { 1u }
|
ty::br_anon { 1u }
|
||||||
br_param(id, _) { id }
|
ty::br_named(str) { str::hash(str) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1588,8 +1624,7 @@ fn hash_type_structure(st: sty) -> uint {
|
||||||
(hash_bound_region(br)) << 2u | 1u }
|
(hash_bound_region(br)) << 2u | 1u }
|
||||||
re_scope(id) { ((id as uint) << 2u) | 2u }
|
re_scope(id) { ((id as uint) << 2u) | 2u }
|
||||||
re_var(id) { (id.to_uint() << 2u) | 3u }
|
re_var(id) { (id.to_uint() << 2u) | 3u }
|
||||||
re_default { 4u }
|
re_bot { 4u }
|
||||||
re_bot { 5u }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
alt st {
|
alt st {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -13,7 +13,7 @@ import driver::session::session;
|
||||||
fn bound_region_to_str(_cx: ctxt, br: bound_region) -> str {
|
fn bound_region_to_str(_cx: ctxt, br: bound_region) -> str {
|
||||||
alt br {
|
alt br {
|
||||||
br_anon { "&" }
|
br_anon { "&" }
|
||||||
br_param(_, str) { #fmt["&%s", str] }
|
br_named(str) { #fmt["&%s", str] }
|
||||||
br_self { "&self" }
|
br_self { "&self" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,6 @@ fn region_to_str(cx: ctxt, region: region) -> str {
|
||||||
|
|
||||||
// These two should not be seen by end-users (very often, anyhow):
|
// These two should not be seen by end-users (very often, anyhow):
|
||||||
re_var(id) { #fmt("&%s", id.to_str()) }
|
re_var(id) { #fmt("&%s", id.to_str()) }
|
||||||
re_default { "&(default)" }
|
|
||||||
re_static { "&static" }
|
re_static { "&static" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
src/test/compile-fail/seq-args.rs
Normal file
13
src/test/compile-fail/seq-args.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
use std;
|
||||||
|
fn main() {
|
||||||
|
iface seq { }
|
||||||
|
|
||||||
|
impl <T> of seq<T> for [T] {
|
||||||
|
//!^ ERROR wrong number of type arguments for a polymorphic type
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
impl of seq<bool> for u32 {
|
||||||
|
/* Treat the integer as a sequence of bits */
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
// xfail-test
|
||||||
|
|
||||||
enum int_wrapper {
|
enum int_wrapper {
|
||||||
int_wrapper_ctor(&int)
|
int_wrapper_ctor(&int)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue