infer when types are region parameterized rather than requiring /&

- removes various fields from various variants in the AST
- also update tests not to use this notation
This commit is contained in:
Niko Matsakis
2012-07-11 10:28:30 -07:00
parent 9b094c0baf
commit b9aa9def85
59 changed files with 602 additions and 387 deletions

View File

@@ -178,7 +178,11 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
let region_map = time(time_passes, "region resolution", ||
middle::region::resolve_crate(sess, def_map, crate));
let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars, region_map);
let rp_set = time(time_passes, "region paramerization inference", ||
middle::region::determine_rp_in_crate(sess, ast_map, def_map, crate));
let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
region_map, rp_set);
let (method_map, vtable_map) = time(time_passes, "typechecking", ||
typeck::check_crate(ty_cx,

View File

@@ -38,6 +38,7 @@ const no_rt: uint = 256u;
const coherence: uint = 512u;
const borrowck_stats: uint = 1024u;
const borrowck_note_pure: uint = 2048;
const borrowck_note_loan: uint = 4096;
fn debugging_opts_map() -> ~[(str, str, uint)] {
~[("ppregions", "prettyprint regions with \
@@ -46,7 +47,7 @@ fn debugging_opts_map() -> ~[(str, str, uint)] {
("count-llvm-insns", "count where LLVM \
instrs originate", count_llvm_insns),
("time-llvm-passes", "measure time of each LLVM pass", time_llvm_passes),
("stats", "gather trans statistics", stats),
("trans-stats", "gather trans statistics", trans_stats),
("no-asm-comments", "omit comments when using -S", no_asm_comments),
("no-verify", "skip LLVM verification", no_verify),
("trace", "emit trace logs", trace),
@@ -54,7 +55,9 @@ fn debugging_opts_map() -> ~[(str, str, uint)] {
("coherence", "perform coherence checking", coherence),
("borrowck-stats", "gather borrowck statistics", borrowck_stats),
("borrowck-note-pure", "note where purity is req'd",
borrowck_note_pure)
borrowck_note_pure),
("borrowck-note-loan", "note where loans are req'd",
borrowck_note_loan)
]
}
@@ -172,6 +175,7 @@ impl session for session {
fn coherence() -> bool { self.debugging_opt(coherence) }
fn borrowck_stats() -> bool { self.debugging_opt(borrowck_stats) }
fn borrowck_note_pure() -> bool { self.debugging_opt(borrowck_note_pure) }
fn borrowck_note_loan() -> bool { self.debugging_opt(borrowck_note_loan) }
}
/// Some reasonable defaults

View File

@@ -17,6 +17,7 @@ export get_class_fields;
export get_class_method;
export get_field_type;
export get_type_param_count;
export get_region_param;
export lookup_defs;
export lookup_method_purity;
export get_enum_variants;
@@ -151,6 +152,12 @@ fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty {
decoder::get_type(cdata, def.node, tcx)
}
fn get_region_param(cstore: metadata::cstore::cstore,
def: ast::def_id) -> bool {
let cdata = cstore::get_crate_data(cstore, def.crate);
ret decoder::get_region_param(cdata, def.node);
}
fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
def: ast::def_id) -> ty::ty_param_bounds_and_ty {
let cstore = tcx.cstore;
@@ -168,7 +175,7 @@ fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
class_id, def) );
#debug("got field data %?", the_field);
let ty = decoder::item_type(def, the_field, tcx, cdata);
ret {bounds: @~[], rp: ast::rp_none, ty: ty};
ret {bounds: @~[], rp: false, ty: ty};
}
// Given a def_id for an impl or class, return the trait it implements,

View File

@@ -21,6 +21,7 @@ export get_class_fields;
export get_symbol;
export get_enum_variants;
export get_type;
export get_region_param;
export get_type_param_count;
export get_impl_trait;
export get_class_method;
@@ -185,15 +186,10 @@ fn item_ty_param_bounds(item: ebml::doc, tcx: ty::ctxt, cdata: cmd)
@bounds
}
fn item_ty_region_param(item: ebml::doc) -> ast::region_param {
fn item_ty_region_param(item: ebml::doc) -> bool {
alt ebml::maybe_get_doc(item, tag_region_param) {
some(rp_doc) {
let dsr = ebml::ebml_deserializer(rp_doc);
ast::deserialize_region_param(dsr)
}
none { // not all families of items have region params
ast::rp_none
}
some(_) { true }
none { false }
}
}
@@ -325,6 +321,11 @@ fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
ret {bounds: tp_bounds, rp: rp, ty: t};
}
fn get_region_param(cdata: cmd, id: ast::node_id) -> bool {
let item = lookup_item(id, cdata.data);
ret item_ty_region_param(item);
}
fn get_type_param_count(data: @~[u8], id: ast::node_id) -> uint {
item_ty_param_count(lookup_item(id, data))
}

View File

@@ -86,10 +86,10 @@ fn encode_name_and_def_id(ebml_w: ebml::writer, nm: ident,
encode_def_id(ebml_w, local_def(id));
}
fn encode_region_param(ebml_w: ebml::writer, rp: region_param) {
do ebml_w.wr_tag(tag_region_param) {
serialize_region_param(ebml_w, rp)
}
fn encode_region_param(ecx: @encode_ctxt, ebml_w: ebml::writer,
it: @ast::item) {
let rp = ecx.tcx.region_paramd_items.contains_key(it.id);
if rp { do ebml_w.wr_tag(tag_region_param) { } }
}
fn encode_named_def_id(ebml_w: ebml::writer, name: ident, id: def_id) {
@@ -188,12 +188,12 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
vec::append_one(path, it.ident), index);
}
}
item_ty(_, tps, _) {
item_ty(_, tps) {
do ebml_w.wr_tag(tag_paths_data_item) {
encode_name_and_def_id(ebml_w, it.ident, it.id);
}
}
item_class(_, _, items, ctor, m_dtor, _) {
item_class(_, _, items, ctor, m_dtor) {
do ebml_w.wr_tag(tag_paths_data_item) {
encode_name_and_def_id(ebml_w, it.ident, it.id);
}
@@ -208,7 +208,7 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
index);
}
}
item_enum(variants, _, _) {
item_enum(variants, _) {
do ebml_w.wr_tag(tag_paths_data_item) {
encode_name_and_def_id(ebml_w, it.ident, it.id);
}
@@ -406,7 +406,7 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
ref, we need to map it to its parent class */
ebml_w.wr_str(def_to_str(local_def(it.id)));
}
some(ast_map::node_item(@{node: item_impl(_,_,
some(ast_map::node_item(@{node: item_impl(_,
some(ifce),_,_),_},_)) {
ebml_w.wr_str(def_to_str(did));
}
@@ -550,7 +550,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
let tcx = ecx.tcx;
let must_write =
alt item.node { item_enum(_, _, _) { true } _ { false } };
alt item.node { item_enum(_, _) { true } _ { false } };
if !must_write && !reachable(ecx, item.id) { ret; }
fn add_to_index_(item: @item, ebml_w: ebml::writer,
@@ -598,7 +598,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_path(ebml_w, path, ast_map::path_name(item.ident));
ebml_w.end_tag();
}
item_ty(_, tps, rp) {
item_ty(_, tps) {
add_to_index();
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
@@ -607,10 +607,10 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
encode_path(ebml_w, path, ast_map::path_name(item.ident));
encode_region_param(ebml_w, rp);
encode_region_param(ecx, ebml_w, item);
ebml_w.end_tag();
}
item_enum(variants, tps, rp) {
item_enum(variants, tps) {
add_to_index();
do ebml_w.wr_tag(tag_items_data_item) {
encode_def_id(ebml_w, local_def(item.id));
@@ -623,12 +623,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
}
ecx.encode_inlined_item(ecx, ebml_w, path, ii_item(item));
encode_path(ebml_w, path, ast_map::path_name(item.ident));
encode_region_param(ebml_w, rp);
encode_region_param(ecx, ebml_w, item);
}
encode_enum_variant_info(ecx, ebml_w, item.id, variants,
path, index, tps);
}
item_class(tps, traits, items, ctor, m_dtor, rp) {
item_class(tps, traits, items, ctor, m_dtor) {
/* First, encode the fields and methods
These come first because we need to write them to make
the index, and the index needs to be in the item for the
@@ -655,7 +655,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
encode_path(ebml_w, path, ast_map::path_name(item.ident));
encode_region_param(ebml_w, rp);
encode_region_param(ecx, ebml_w, item);
for traits.each |t| {
encode_trait_ref(ebml_w, ecx, t);
}
@@ -704,12 +704,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_index(ebml_w, bkts, write_int);
ebml_w.end_tag();
}
item_impl(tps, rp, ifce, _, methods) {
item_impl(tps, ifce, _, methods) {
add_to_index();
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'i');
encode_region_param(ebml_w, rp);
encode_region_param(ecx, ebml_w, item);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
@@ -733,12 +733,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
vec::append(tps, m.tps));
}
}
item_trait(tps, rp, ms) {
item_trait(tps, ms) {
add_to_index();
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'I');
encode_region_param(ebml_w, rp);
encode_region_param(ecx, ebml_w, item);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
@@ -801,7 +801,7 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
encode_info_for_item(ecx, ebml_w, i, index, *pt);
/* encode ctor, then encode items */
alt i.node {
item_class(tps, _, _, ctor, m_dtor, _) {
item_class(tps, _, _, ctor, m_dtor) {
#debug("encoding info for ctor %s %d", *i.ident,
ctor.node.id);
vec::push(*index,

View File

@@ -554,11 +554,11 @@ impl helpers for ebml::writer {
do self.emit_rec {
do self.emit_rec_field("bounds", 0u) {
do self.emit_from_vec(*tpbt.bounds) |bs| {
self.emit_bounds(ecx, bs)
self.emit_bounds(ecx, bs);
}
}
do self.emit_rec_field("rp", 1u) {
ast::serialize_region_param(self, tpbt.rp)
self.emit_bool(tpbt.rp);
}
do self.emit_rec_field("ty", 2u) {
self.emit_ty(ecx, tpbt.ty);
@@ -759,7 +759,7 @@ impl decoder for ebml::ebml_deserializer {
@self.read_to_vec(|| self.read_bounds(xcx) )
}),
rp: self.read_rec_field("rp", 1u, || {
ast::deserialize_region_param(self)
self.read_bool()
}),
ty: self.read_rec_field("ty", 2u, || {
self.read_ty(xcx)

View File

@@ -199,6 +199,12 @@ impl methods for gather_loan_ctxt {
if req_mutbl == m_imm && cmt.mutbl != m_imm {
self.bccx.loaned_paths_imm += 1;
if self.tcx().sess.borrowck_note_loan() {
self.bccx.span_note(
cmt.span,
#fmt["immutable loan required"]);
}
} else {
self.bccx.loaned_paths_same += 1;
}

View File

@@ -24,7 +24,7 @@ fn check_item(sess: session, ast_map: ast_map::map, def_map: resolve::def_map,
v.visit_expr(ex, true, v);
check_item_recursion(sess, ast_map, def_map, it);
}
item_enum(vs, _, _) {
item_enum(vs, _) {
for vs.each |var| {
do option::iter(var.node.disr_expr) |ex| {
v.visit_expr(ex, true, v);

View File

@@ -138,11 +138,13 @@ import syntax::{ast, visit};
import syntax::codemap::span;
import syntax::print::pprust;
import syntax::ast_util::new_def_hash;
import syntax::ast_map;
import dvec::{dvec, extensions};
import metadata::csearch;
import std::list;
import std::list::list;
import std::map;
import std::map::hashmap;
import std::map::{hashmap, int_hash};
type parent = option<ast::node_id>;
@@ -386,7 +388,7 @@ fn resolve_crate(sess: session, def_map: resolve::def_map, crate: @ast::crate)
-> region_map {
let cx: ctxt = {sess: sess,
def_map: def_map,
region_map: map::int_hash(),
region_map: int_hash(),
parent: none};
let visitor = visit::mk_vt(@{
visit_block: resolve_block,
@@ -402,3 +404,208 @@ fn resolve_crate(sess: session, def_map: resolve::def_map, crate: @ast::crate)
ret cx.region_map;
}
// ___________________________________________________________________________
// Determining region parameterization
//
// Infers which type defns must be region parameterized---this is done
// by scanning their contents to see whether they reference a region
// type, directly or indirectly. This is a fixed-point computation.
//
// We do it in two passes. First we walk the AST and construct a map
// from each type defn T1 to other defns which make use of it. For example,
// if we have a type like:
//
// type S = *int;
// type T = S;
//
// Then there would be a map entry from S to T. During the same walk,
// we also construct add any types that reference regions to a set and
// a worklist. We can then process the worklist, propagating indirect
// dependencies until a fixed point is reached.
type region_paramd_items = hashmap<ast::node_id, ()>;
type dep_map = hashmap<ast::node_id, @dvec<ast::node_id>>;
type determine_rp_ctxt = @{
sess: session,
ast_map: ast_map::map,
def_map: resolve::def_map,
region_paramd_items: region_paramd_items,
dep_map: dep_map,
worklist: dvec<ast::node_id>,
mut item_id: ast::node_id,
mut anon_implies_rp: bool
};
impl methods for determine_rp_ctxt {
fn add_rp(id: ast::node_id) {
assert id != 0;
if self.region_paramd_items.insert(id, ()) {
#debug["add region-parameterized item: %d (%s)",
id, ast_map::node_id_to_str(self.ast_map, id)];
self.worklist.push(id);
} else {
#debug["item %d already region-parameterized", id];
}
}
fn add_dep(from: ast::node_id, to: ast::node_id) {
#debug["add dependency from %d -> %d (%s -> %s)",
from, to,
ast_map::node_id_to_str(self.ast_map, from),
ast_map::node_id_to_str(self.ast_map, to)];
let vec = alt self.dep_map.find(from) {
some(vec) => {vec}
none => {
let vec = @dvec();
self.dep_map.insert(from, vec);
vec
}
};
if !vec.contains(to) { vec.push(to); }
}
fn region_is_relevant(r: @ast::region) -> bool {
alt r.node {
ast::re_anon {self.anon_implies_rp}
ast::re_named(@"self") {true}
ast::re_named(_) {false}
}
}
fn with(item_id: ast::node_id, anon_implies_rp: bool, f: fn()) {
let old_item_id = self.item_id;
let old_anon_implies_rp = self.anon_implies_rp;
self.item_id = item_id;
self.anon_implies_rp = anon_implies_rp;
#debug["with_item_id(%d, %b)", item_id, anon_implies_rp];
let _i = util::common::indenter();
f();
self.item_id = old_item_id;
self.anon_implies_rp = old_anon_implies_rp;
}
}
fn determine_rp_in_item(item: @ast::item,
&&cx: determine_rp_ctxt,
visitor: visit::vt<determine_rp_ctxt>) {
do cx.with(item.id, true) {
visit::visit_item(item, cx, visitor);
}
}
fn determine_rp_in_fn(fk: visit::fn_kind,
decl: ast::fn_decl,
body: ast::blk,
sp: span,
id: ast::node_id,
&&cx: determine_rp_ctxt,
visitor: visit::vt<determine_rp_ctxt>) {
do cx.with(cx.item_id, false) {
visit::visit_fn(fk, decl, body, sp, id, cx, visitor);
}
}
fn determine_rp_in_ty_method(ty_m: ast::ty_method,
&&cx: determine_rp_ctxt,
visitor: visit::vt<determine_rp_ctxt>) {
do cx.with(cx.item_id, false) {
visit::visit_ty_method(ty_m, cx, visitor);
}
}
fn determine_rp_in_ty(ty: @ast::ty,
&&cx: determine_rp_ctxt,
visitor: visit::vt<determine_rp_ctxt>) {
// we are only interesting in types that will require an item to
// be region-parameterized. if cx.item_id is zero, then this type
// is not a member of a type defn nor is it a constitutent of an
// impl etc. So we can ignore it and its components.
if cx.item_id == 0 { ret; }
// if this type directly references a region, either via a
// region pointer like &r.ty or a region-parameterized path
// like path/r, add to the worklist/set
alt ty.node {
ast::ty_rptr(r, _) |
ast::ty_path(@{rp: some(r), _}, _) |
ast::ty_vstore(_, ast::vstore_slice(r)) => {
#debug["referenced type with regions %s", pprust::ty_to_str(ty)];
if cx.region_is_relevant(r) {
cx.add_rp(cx.item_id);
}
}
_ => {}
}
// if this references another named type, add the dependency
// to the dep_map. If the type is not defined in this crate,
// then check whether it is region-parameterized and consider
// that as a direct dependency.
alt ty.node {
ast::ty_path(_, id) {
alt cx.def_map.get(id) {
ast::def_ty(did) | ast::def_class(did) {
if did.crate == ast::local_crate {
cx.add_dep(did.node, cx.item_id);
} else {
let cstore = cx.sess.cstore;
if csearch::get_region_param(cstore, did) {
#debug["reference to external, rp'd type %s",
pprust::ty_to_str(ty)];
cx.add_rp(cx.item_id);
}
}
}
_ {}
}
}
_ {}
}
visit::visit_ty(ty, cx, visitor);
}
fn determine_rp_in_crate(sess: session,
ast_map: ast_map::map,
def_map: resolve::def_map,
crate: @ast::crate) -> region_paramd_items {
let cx = @{sess: sess,
ast_map: ast_map,
def_map: def_map,
region_paramd_items: int_hash(),
dep_map: int_hash(),
worklist: dvec(),
mut item_id: 0,
mut anon_implies_rp: false};
// gather up the base set, worklist and dep_map:
let visitor = visit::mk_vt(@{
visit_fn: determine_rp_in_fn,
visit_item: determine_rp_in_item,
visit_ty: determine_rp_in_ty,
visit_ty_method: determine_rp_in_ty_method,
with *visit::default_visitor()
});
visit::visit_crate(*crate, cx, visitor);
// propagate indirect dependencies
while cx.worklist.len() != 0 {
let id = cx.worklist.pop();
#debug["popped %d from worklist", id];
alt cx.dep_map.find(id) {
none {}
some(vec) {
for vec.each |to_id| {
cx.add_rp(to_id);
}
}
}
}
// return final set
ret cx.region_paramd_items;
}

View File

@@ -439,10 +439,10 @@ fn resolve_names(e: @env, c: @ast::crate) {
/* At this point, the code knows what traits the trait refs
refer to, so it's possible to resolve them.
*/
ast::item_impl(_, _, ifce, _, _) {
ast::item_impl(_, ifce, _, _) {
ifce.iter(|p| resolve_trait_ref(p, sc, e))
}
ast::item_class(_, traits, _, _, _, _) {
ast::item_class(_, traits, _, _, _) {
for traits.each |p| {
resolve_trait_ref(p, sc, e);
}
@@ -552,7 +552,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item,
let sc = @cons(scope_item(i), sc);
alt i.node {
ast::item_impl(tps, _, ifce, sty, methods) {
ast::item_impl(tps, ifce, sty, methods) {
v.visit_ty_params(tps, sc, v);
option::iter(ifce, |p| visit::visit_path(p.path, sc, v));
v.visit_ty(sty, sc, v);
@@ -564,7 +564,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item,
m.decl, m.body, m.span, m.id, msc, v);
}
}
ast::item_trait(tps, _, methods) {
ast::item_trait(tps, methods) {
v.visit_ty_params(tps, sc, v);
let isc = @cons(scope_method(i.id, tps), sc);
for methods.each |m| {
@@ -574,7 +574,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item,
v.visit_ty(m.decl.output, msc, v);
}
}
ast::item_class(tps, traits, members, ctor, m_dtor, _) {
ast::item_class(tps, traits, members, ctor, m_dtor) {
v.visit_ty_params(tps, sc, v);
let class_scope = @cons(scope_item(i), sc);
/* visit the constructor... */
@@ -1042,13 +1042,13 @@ fn lookup_in_scope(e: env, &&sc: scopes, sp: span, name: ident, ns: namespace,
}
scope_item(it) {
alt it.node {
ast::item_impl(tps, _, _, _, _) {
ast::item_impl(tps, _, _, _) {
if ns == ns_type { ret lookup_in_ty_params(e, name, tps); }
}
ast::item_enum(_, tps, _) | ast::item_ty(_, tps, _) {
ast::item_enum(_, tps) | ast::item_ty(_, tps) {
if ns == ns_type { ret lookup_in_ty_params(e, name, tps); }
}
ast::item_trait(tps, _, _) {
ast::item_trait(tps, _) {
if ns == ns_type {
if *name == "self" {
ret some(def_self(it.id));
@@ -1062,7 +1062,7 @@ fn lookup_in_scope(e: env, &&sc: scopes, sp: span, name: ident, ns: namespace,
ast::item_foreign_mod(m) {
ret lookup_in_local_foreign_mod(e, it.id, sp, name, ns);
}
ast::item_class(tps, _, members, ctor, _, _) {
ast::item_class(tps, _, members, ctor, _) {
if ns == ns_type {
ret lookup_in_ty_params(e, name, tps);
}
@@ -1234,7 +1234,7 @@ fn lookup_in_block(e: env, name: ident, sp: span, b: ast::blk_, pos: uint,
}
ast::decl_item(it) {
alt it.node {
ast::item_enum(variants, _, _) {
ast::item_enum(variants, _) {
if ns == ns_type {
if str::eq(*it.ident, *name) {
ret some(ast::def_ty(local_def(it.id)));
@@ -1339,7 +1339,7 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option<def> {
ast::item_ty(*) | item_trait(*) | item_enum(*) {
if ns == ns_type { ret some(ast::def_ty(local_def(i.id))); }
}
ast::item_class(_, _, _members, ct, _, _) {
ast::item_class(_, _, _members, ct, _) {
alt ns {
ns_type {
ret some(ast::def_class(local_def(i.id)));
@@ -1641,11 +1641,11 @@ fn index_mod(md: ast::_mod) -> mod_index {
for md.items.each |it| {
alt it.node {
ast::item_const(_, _) | ast::item_fn(_, _, _) | ast::item_mod(_) |
ast::item_foreign_mod(_) | ast::item_ty(_, _, _) |
ast::item_foreign_mod(_) | ast::item_ty(_, _) |
ast::item_impl(*) | ast::item_trait(*) {
add_to_index(index, it.ident, mie_item(it));
}
ast::item_enum(variants, _, _) {
ast::item_enum(variants, _) {
add_to_index(index, it.ident, mie_item(it));
let mut variant_idx: uint = 0u;
for variants.each |v| {
@@ -1655,7 +1655,7 @@ fn index_mod(md: ast::_mod) -> mod_index {
variant_idx += 1u;
}
}
ast::item_class(tps, _, items, ctor, _, _) {
ast::item_class(tps, _, items, ctor, _) {
// add the class name itself
add_to_index(index, it.ident, mie_item(it));
}
@@ -1780,15 +1780,15 @@ fn check_item(e: @env, i: @ast::item, &&x: (), v: vt<()>) {
ensure_unique(*e, i.span, ty_params, |tp| tp.ident,
"type parameter");
}
ast::item_enum(_, ty_params, _) {
ast::item_enum(_, ty_params) {
ensure_unique(*e, i.span, ty_params, |tp| tp.ident,
"type parameter");
}
ast::item_trait(_, _, methods) {
ast::item_trait(_, methods) {
ensure_unique(*e, i.span, methods, |m| m.ident,
"method");
}
ast::item_impl(_, _, _, _, methods) {
ast::item_impl(_, _, _, methods) {
ensure_unique(*e, i.span, methods, |m| m.ident,
"method");
}
@@ -1854,7 +1854,7 @@ fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) {
}
ast::decl_item(it) {
alt it.node {
ast::item_enum(variants, _, _) {
ast::item_enum(variants, _) {
add_name(types, it.span, it.ident);
for variants.each |v| {
add_name(values, v.span, v.node.name);
@@ -2051,7 +2051,7 @@ fn check_exports(e: @env) {
some(ms) {
let maybe_id = do list_search(ms) |m| {
alt m {
mie_item(@{node: item_enum(_, _, _), id, _}) { some(id) }
mie_item(@{node: item_enum(_, _), id, _}) { some(id) }
_ { none }
}
};
@@ -2242,7 +2242,7 @@ fn find_impls_in_item(e: env, i: @ast::item, &impls: ~[@_impl],
name: option<ident>,
ck_exports: option<@indexed_mod>) {
alt i.node {
ast::item_impl(_, _, ifce, _, mthds) {
ast::item_impl(_, ifce, _, mthds) {
if alt name { some(n) { n == i.ident } _ { true } } &&
alt ck_exports {
some(m) { is_exported(e, i.ident, m) }
@@ -2257,7 +2257,7 @@ fn find_impls_in_item(e: env, i: @ast::item, &impls: ~[@_impl],
})});
}
}
ast::item_class(tps, ifces, items, _, _, _) {
ast::item_class(tps, ifces, items, _, _) {
let (_, mthds) = ast_util::split_class_items(items);
let n_tps = tps.len();
do vec::iter(ifces) |p| {

View File

@@ -847,7 +847,7 @@ class Resolver {
}
// These items live in both the type and value namespaces.
item_enum(variants, _, _) {
item_enum(variants, _) {
(*name_bindings).define_type(def_ty(local_def(item.id)));
for variants.each |variant| {
@@ -857,7 +857,7 @@ class Resolver {
visitor);
}
}
item_class(_, _, class_members, ctor, _, _) {
item_class(_, _, class_members, ctor, _) {
(*name_bindings).define_type(def_ty(local_def(item.id)));
let purity = ctor.node.dec.purity;
@@ -899,7 +899,7 @@ class Resolver {
visit_item(item, new_parent, visitor);
}
item_impl(_, _, _, _, methods) {
item_impl(_, _, _, methods) {
// Create the set of implementation information that the
// implementation scopes (ImplScopes) need and write it into
// the implementation definition list for this set of name
@@ -2884,8 +2884,8 @@ class Resolver {
}
alt item.node {
item_enum(_, type_parameters, _) |
item_ty(_, type_parameters, _) {
item_enum(_, type_parameters) |
item_ty(_, type_parameters) {
do self.with_type_parameter_rib
(HasTypeParameters(&type_parameters, item.id, 0u,
NormalRibKind))
@@ -2895,7 +2895,7 @@ class Resolver {
}
}
item_impl(type_parameters, _, interface_reference, self_type,
item_impl(type_parameters, interface_reference, self_type,
methods) {
self.resolve_implementation(item.id,
item.span,
@@ -2906,7 +2906,7 @@ class Resolver {
visitor);
}
item_trait(type_parameters, _, methods) {
item_trait(type_parameters, methods) {
// Create a new rib for the self type.
let self_type_rib = @Rib(NormalRibKind);
(*self.type_ribs).push(self_type_rib);
@@ -2948,7 +2948,7 @@ class Resolver {
}
item_class(ty_params, interfaces, class_members, constructor,
optional_destructor, _) {
optional_destructor) {
self.resolve_class(item.id,
@copy ty_params,

View File

@@ -2291,7 +2291,7 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
ccx.external.insert(parent_id, some(item.id));
let mut my_id = 0;
alt check item.node {
ast::item_enum(_, _, _) {
ast::item_enum(_, _) {
let vs_here = ty::enum_variants(ccx.tcx, local_def(item.id));
let vs_there = ty::enum_variants(ccx.tcx, parent_id);
do vec::iter2(*vs_here, *vs_there) |here, there| {
@@ -4886,13 +4886,13 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
}
}
}
ast::item_impl(tps, _rp, _, _, ms) {
ast::item_impl(tps, _, _, ms) {
impl::trans_impl(ccx, *path, item.ident, ms, tps);
}
ast::item_mod(m) {
trans_mod(ccx, m);
}
ast::item_enum(variants, tps, _) {
ast::item_enum(variants, tps) {
if tps.len() == 0u {
let degen = variants.len() == 1u;
let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
@@ -4916,7 +4916,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
};
foreign::trans_foreign_mod(ccx, foreign_mod, abi);
}
ast::item_class(tps, _traits, items, ctor, m_dtor, _) {
ast::item_class(tps, _traits, items, ctor, m_dtor) {
if tps.len() == 0u {
let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps),
vtables: none,
@@ -5199,7 +5199,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
~[path_name(enm.ident),
path_name(v.node.name)]);
let llfn = alt check enm.node {
ast::item_enum(_, _, _) {
ast::item_enum(_, _) {
register_fn(ccx, v.span, pth, id)
}
};
@@ -5220,7 +5220,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
fn trans_constant(ccx: @crate_ctxt, it: @ast::item) {
let _icx = ccx.insn_ctxt("trans_constant");
alt it.node {
ast::item_enum(variants, _, _) {
ast::item_enum(variants, _) {
let vi = ty::enum_variants(ccx.tcx, {crate: ast::local_crate,
node: it.id});
let mut i = 0;

View File

@@ -84,11 +84,11 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
name: ast::ident) -> ast::def_id {
if impl_id.crate == ast::local_crate {
alt check ccx.tcx.items.get(impl_id.node) {
ast_map::node_item(@{node: ast::item_impl(_, _, _, _, ms), _}, _) {
ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) {
method_from_methods(ms, name)
}
ast_map::node_item(@{node:
ast::item_class(_, _, items, _, _, _), _}, _) {
ast::item_class(_, _, items, _, _), _}, _) {
let (_,ms) = split_class_items(items);
method_from_methods(ms, name)
}

View File

@@ -112,7 +112,7 @@ fn traverse_public_item(cx: ctx, item: @item) {
traverse_inline_body(cx, blk);
}
}
item_impl(tps, _, _, _, ms) {
item_impl(tps, _, _, ms) {
for vec::each(ms) |m| {
if tps.len() > 0u || m.tps.len() > 0u ||
attr::find_inline_attr(m.attrs) != attr::ia_none {
@@ -121,7 +121,7 @@ fn traverse_public_item(cx: ctx, item: @item) {
}
}
}
item_class(tps, _traits, items, ctor, m_dtor, _) {
item_class(tps, _traits, items, ctor, m_dtor) {
cx.rmap.insert(ctor.node.id, ());
do option::iter(m_dtor) |dtor| {
cx.rmap.insert(dtor.node.id, ());
@@ -143,7 +143,7 @@ fn traverse_public_item(cx: ctx, item: @item) {
}
}
}
item_ty(t, _, _) {
item_ty(t, _) {
traverse_ty(t, cx, mk_ty_visitor());
}
item_const(*) |
@@ -218,7 +218,7 @@ fn traverse_all_resources(cx: ctx, crate_mod: _mod) {
visit_item: |i, cx, v| {
visit::visit_item(i, cx, v);
alt i.node {
item_class(_, _, _, _, some(_), _) {
item_class(_, _, _, _, some(_)) {
traverse_public_item(cx, i);
}
_ {}

View File

@@ -52,7 +52,7 @@ fn find_pre_post_item(ccx: crate_ctxt, i: item) {
item_class(*) {
fail "find_pre_post_item: shouldn't be called on item_class";
}
item_impl(_, _, _, _, ms) {
item_impl(_, _, _, ms) {
for ms.each |m| { find_pre_post_method(ccx, m); }
}
item_mac(*) { fail "item macros unimplemented" }

View File

@@ -233,7 +233,9 @@ type ctxt =
cstore: metadata::cstore::cstore,
sess: session::session,
def_map: resolve::def_map,
region_map: middle::region::region_map,
region_paramd_items: middle::region::region_paramd_items,
// Stores the types for various nodes in the AST. Note that this table
// is not guaranteed to be populated until after typeck. See
@@ -482,7 +484,7 @@ fn param_bounds_to_kind(bounds: param_bounds) -> kind {
}
type ty_param_bounds_and_ty = {bounds: @~[param_bounds],
rp: ast::region_param,
rp: bool,
ty: t};
type type_cache = hashmap<ast::def_id, ty_param_bounds_and_ty>;
@@ -505,9 +507,12 @@ fn new_ty_hash<V: copy>() -> map::hashmap<t, V> {
|&&a: t, &&b: t| type_id(a) == type_id(b))
}
fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
fn mk_ctxt(s: session::session,
dm: resolve::def_map,
amap: ast_map::map,
freevars: freevars::freevar_map,
region_map: middle::region::region_map) -> ctxt {
region_map: middle::region::region_map,
region_paramd_items: middle::region::region_paramd_items) -> ctxt {
let interner = map::hashmap(|&&k: intern_key| {
hash_type_structure(k.struct) +
option::map_default(k.o_def_id, 0u, ast_util::hash_def)
@@ -523,6 +528,7 @@ fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
sess: s,
def_map: dm,
region_map: region_map,
region_paramd_items: region_paramd_items,
node_types: @smallintmap::mk(),
node_type_substs: map::int_hash(),
items: amap,
@@ -2543,10 +2549,10 @@ fn impl_trait(cx: ctxt, id: ast::def_id) -> option<t> {
#debug("(impl_trait) searching for trait impl %?", id);
alt cx.items.find(id.node) {
some(ast_map::node_item(@{node: ast::item_impl(
_, _, some(@{id: id, _}), _, _), _}, _)) {
_, some(@{id: id, _}), _, _), _}, _)) {
some(node_id_to_type(cx, id))
}
some(ast_map::node_item(@{node: ast::item_class(_, _, _, _, _, _),
some(ast_map::node_item(@{node: ast::item_class(*),
_},_)) {
alt cx.def_map.find(id.node) {
some(def_ty(trait_id)) {
@@ -2606,7 +2612,7 @@ fn ty_dtor(cx: ctxt, class_id: def_id) -> option<def_id> {
if is_local(class_id) {
alt cx.items.find(class_id.node) {
some(ast_map::node_item(@{node: ast::item_class(_, _, _, _,
some(dtor), _), _}, _))
some(dtor)), _}, _))
{ some(local_def(dtor.node.id)) }
_ { none }
}
@@ -2687,7 +2693,7 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[variant_info] {
expr, since check_enum_variants also updates the enum_var_cache
*/
alt cx.items.get(id.node) {
ast_map::node_item(@{node: ast::item_enum(variants, _, _), _}, _) {
ast_map::node_item(@{node: ast::item_enum(variants, _), _}, _) {
let mut disr_val = -1;
@vec::map(variants, |variant| {
let ctor_ty = node_id_to_type(cx, variant.node.id);
@@ -2780,7 +2786,7 @@ fn lookup_class_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] {
alt cx.items.find(did.node) {
some(ast_map::node_item(i,_)) {
alt i.node {
ast::item_class(_, _, items, _, _, _) {
ast::item_class(_, _, items, _, _) {
class_field_tys(items)
}
_ { cx.sess.bug("class ID bound to non-class"); }
@@ -2822,7 +2828,7 @@ pure fn is_public(f: field_ty) -> bool {
fn lookup_class_method_ids(cx: ctxt, did: ast::def_id)
: is_local(did) -> ~[{name: ident, id: node_id, vis: visibility}] {
alt cx.items.find(did.node) {
some(ast_map::node_item(@{node: item_class(_,_,items,_,_,_), _}, _)) {
some(ast_map::node_item(@{node: item_class(_,_,items,_,_), _}, _)) {
let (_,ms) = split_class_items(items);
vec::map(ms, |m| {name: m.ident, id: m.id,
vis: m.vis})

View File

@@ -185,7 +185,7 @@ fn lookup_def_ccx(ccx: @crate_ctxt, sp: span, id: ast::node_id) -> ast::def {
}
fn no_params(t: ty::t) -> ty::ty_param_bounds_and_ty {
{bounds: @~[], rp: ast::rp_none, ty: t}
{bounds: @~[], rp: false, ty: t}
}
fn require_same_types(

View File

@@ -87,14 +87,17 @@ fn ast_path_to_substs_and_ty<AC: ast_conv, RS: region_scope copy>(
let {bounds: decl_bounds, rp: decl_rp, ty: decl_ty} =
self.get_item_ty(did);
#debug["ast_path_to_substs_and_ty: did=%? decl_rp=%b",
did, decl_rp];
// If the type is parameterized by the self region, then replace self
// region with the current anon region binding (in other words,
// whatever & would get replaced with).
let self_r = alt (decl_rp, path.rp) {
(ast::rp_none, none) {
(false, none) {
none
}
(ast::rp_none, some(_)) {
(false, some(_)) {
tcx.sess.span_err(
path.span,
#fmt["no region bound is permitted on %s, \
@@ -102,12 +105,12 @@ fn ast_path_to_substs_and_ty<AC: ast_conv, RS: region_scope copy>(
ty::item_path_str(tcx, did)]);
none
}
(ast::rp_self, none) {
(true, none) {
let res = rscope.anon_region();
let r = get_region_reporting_err(self.tcx(), path.span, res);
some(r)
}
(ast::rp_self, some(r)) {
(true, some(r)) {
some(ast_region_to_region(self, rscope, path.span, r))
}
};

View File

@@ -66,7 +66,7 @@ type parameter).
*/
import astconv::{ast_conv, ast_ty_to_ty};
import astconv::{ast_conv, ast_ty_to_ty, ast_region_to_region};
import collect::{methods}; // ccx.to_ty()
import middle::ty::{tv_vid, vid};
import regionmanip::{replace_bound_regions_in_fn_ty, region_of};
@@ -348,17 +348,20 @@ fn check_class_member(ccx: @crate_ctxt, class_t: ty::t,
fn check_item(ccx: @crate_ctxt, it: @ast::item) {
alt it.node {
ast::item_const(_, e) { check_const(ccx, it.span, e, it.id); }
ast::item_enum(vs, _, _) {
ast::item_enum(vs, _) {
check_enum_variants(ccx, it.span, vs, it.id);
}
ast::item_fn(decl, tps, body) {
check_bare_fn(ccx, decl, body, it.id, none);
}
ast::item_impl(tps, rp, _, ty, ms) {
ast::item_impl(tps, _, ty, ms) {
let rp = ccx.tcx.region_paramd_items.contains_key(it.id);
#debug["item_impl %s with id %d rp %b",
*it.ident, it.id, rp];
let self_ty = ccx.to_ty(rscope::type_rscope(rp), ty);
for ms.each |m| { check_method(ccx, m, self_ty);}
}
ast::item_class(tps, traits, members, ctor, m_dtor, rp) {
ast::item_class(tps, traits, members, ctor, m_dtor) {
let tcx = ccx.tcx;
let class_t = ty::node_id_to_type(tcx, it.id);
// typecheck the ctor
@@ -387,9 +390,9 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
// Check that the class is instantiable
check_instantiable(ccx.tcx, it.span, it.id);
}
ast::item_ty(t, tps, rp) {
ast::item_ty(t, tps) {
let tpt_ty = ty::node_id_to_type(ccx.tcx, it.id);
check_bounds_are_used(ccx, t.span, tps, rp, tpt_ty);
check_bounds_are_used(ccx, t.span, tps, tpt_ty);
}
ast::item_foreign_mod(m) {
if syntax::attr::foreign_abi(it.attrs) ==
@@ -647,15 +650,16 @@ fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id) -> ty_param_substs_and_ty {
let tcx = fcx.ccx.tcx;
let {n_tps, rp, raw_ty} = if did.crate == ast::local_crate {
let rp = fcx.tcx().region_paramd_items.contains_key(did.node);
alt check tcx.items.find(did.node) {
some(ast_map::node_item(@{node: ast::item_impl(ts, rp, _, st, _),
some(ast_map::node_item(@{node: ast::item_impl(ts, _, st, _),
_}, _)) {
{n_tps: ts.len(),
rp: rp,
raw_ty: fcx.ccx.to_ty(rscope::type_rscope(rp), st)}
}
some(ast_map::node_item(@{node: ast::item_class(ts,
_,_,_,_,rp), id: class_id, _},_)) {
_,_,_,_), id: class_id, _},_)) {
/* If the impl is a class, the self ty is just the class ty
(doing a no-op subst for the ty params; in the next step,
we substitute in fresh vars for them)
@@ -663,9 +667,8 @@ fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id) -> ty_param_substs_and_ty {
{n_tps: ts.len(),
rp: rp,
raw_ty: ty::mk_class(tcx, local_def(class_id),
{self_r: alt rp {
ast::rp_self { some(fcx.infcx.next_region_var()) }
ast::rp_none { none }},
{self_r: if rp {some(ty::re_bound(ty::br_self))}
else {none},
self_ty: none,
tps: ty::ty_params_to_tys(tcx, ts)})}
}
@@ -679,10 +682,7 @@ fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id) -> ty_param_substs_and_ty {
raw_ty: ity.ty}
};
let self_r = alt rp {
ast::rp_none { none }
ast::rp_self { some(fcx.infcx.next_region_var()) }
};
let self_r = if rp {some(fcx.infcx.next_region_var())} else {none};
let tps = fcx.infcx.next_ty_vars(n_tps);
let substs = {self_r: self_r, self_ty: none, tps: tps};
@@ -2053,7 +2053,7 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
// extern functions are just u8 pointers
ret {
bounds: @~[],
rp: ast::rp_none,
rp: false,
ty: ty::mk_ptr(
fcx.ccx.tcx,
{
@@ -2109,13 +2109,27 @@ fn instantiate_path(fcx: @fn_ctxt,
let ty_param_count = vec::len(*tpt.bounds);
let ty_substs_len = vec::len(pth.types);
// For now, there is no way to explicitly specify the region bound.
// This will have to change eventually.
let self_r = alt tpt.rp {
ast::rp_self { some(fcx.infcx.next_region_var()) }
ast::rp_none { none }
// determine the region bound, using the value given by the user
// (if any) and otherwise using a fresh region variable
let self_r = alt pth.rp {
some(r) if !tpt.rp => {
fcx.ccx.tcx.sess.span_err
(sp, "this item is not region-parameterized");
none
}
some(r) => {
some(ast_region_to_region(fcx, fcx, sp, r))
}
none if tpt.rp => {
some(fcx.infcx.next_region_var())
}
none => {
none
}
};
// determine values for type parameters, using the values given by
// the user (if any) and otherwise using fresh type variables
let tps = if ty_substs_len == 0u {
fcx.infcx.next_ty_vars(ty_param_count)
} else if ty_param_count == 0u {
@@ -2203,24 +2217,14 @@ fn ast_expr_vstore_to_vstore(fcx: @fn_ctxt, e: @ast::expr, n: uint,
fn check_bounds_are_used(ccx: @crate_ctxt,
span: span,
tps: ~[ast::ty_param],
rp: ast::region_param,
ty: ty::t) {
let mut r_used = alt rp {
ast::rp_self { false }
ast::rp_none { true }
};
if tps.len() == 0u && r_used { ret; }
// make a vector of booleans initially false, set to true when used
if tps.len() == 0u { ret; }
let tps_used = vec::to_mut(vec::from_elem(tps.len(), false));
ty::walk_regions_and_ty(
ccx.tcx, ty,
|r| {
alt r {
ty::re_bound(_) { r_used = true; }
_ { }
}
},
|_r| {},
|t| {
alt ty::get(t).struct {
ty::ty_param(idx, _) { tps_used[idx] = true; }
@@ -2229,12 +2233,6 @@ fn check_bounds_are_used(ccx: @crate_ctxt,
true
});
if !r_used {
ccx.tcx.sess.span_err(
span, "lifetime `self` unused inside \
reference-parameterized type");
}
for tps_used.eachi |i, b| {
if !b {
ccx.tcx.sess.span_err(

View File

@@ -15,7 +15,7 @@ import middle::typeck::infer::{infer_ctxt, mk_subty, new_infer_ctxt};
import syntax::ast::{crate, def_id, item, item_class, item_const, item_enum};
import syntax::ast::{item_fn, item_foreign_mod, item_impl, item_mac};
import syntax::ast::{item_mod, item_trait, item_ty, local_crate, method};
import syntax::ast::{node_id, region_param, rp_none, rp_self, trait_ref};
import syntax::ast::{node_id, trait_ref};
import syntax::ast_util::{def_id_of_def, new_def_hash};
import syntax::visit::{default_simple_visitor, default_visitor};
import syntax::visit::{mk_simple_visitor, mk_vt, visit_crate, visit_item};
@@ -76,7 +76,7 @@ class CoherenceChecker {
visit_crate(*crate, (), mk_simple_visitor(@{
visit_item: |item| {
alt item.node {
item_impl(_, _, associated_trait, self_type, _) {
item_impl(_, associated_trait, self_type, _) {
self.check_implementation(item, associated_trait);
}
_ {
@@ -239,15 +239,9 @@ class CoherenceChecker {
// Converts a polytype to a monotype by replacing all parameters with
// type variables.
fn universally_quantify_polytype(polytype: ty_param_bounds_and_ty) -> t {
let self_region;
alt polytype.rp {
rp_none {
self_region = none;
}
rp_self {
self_region = some(self.inference_context.next_region_var())
}
};
let self_region =
if polytype.rp {none}
else {some(self.inference_context.next_region_var())};
let bounds_count = polytype.bounds.len();
let type_parameters =
@@ -304,7 +298,7 @@ class CoherenceChecker {
self.privileged_types.remove(privileged_type);
}
}
item_impl(_, _, optional_trait_ref, _, _) {
item_impl(_, optional_trait_ref, _, _) {
alt self.base_type_def_ids.find(item.id) {
none {
// Nothing to do.

View File

@@ -39,13 +39,13 @@ fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) {
alt intrinsic_item.node {
ast::item_trait(_, _, _) {
ast::item_trait(_, _) {
let ty = ty::mk_trait(ccx.tcx, def_id, substs);
ccx.tcx.intrinsic_defs.insert
(intrinsic_item.ident, (def_id, ty));
}
ast::item_enum(_, _, _) {
ast::item_enum(_, _) {
let ty = ty::mk_enum(ccx.tcx, def_id, substs);
ccx.tcx.intrinsic_defs.insert
(intrinsic_item.ident, (def_id, ty));
@@ -107,7 +107,7 @@ fn get_enum_variant_types(ccx: @crate_ctxt,
enum_ty: ty::t,
variants: ~[ast::variant],
ty_params: ~[ast::ty_param],
rp: ast::region_param) {
rp: bool) {
let tcx = ccx.tcx;
// Create a set of parameter types shared among all the variants.
@@ -144,13 +144,14 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id) {
}
let tcx = ccx.tcx;
let rp = tcx.region_paramd_items.contains_key(id);
alt check tcx.items.get(id) {
ast_map::node_item(@{node: ast::item_trait(_, rp, ms), _}, _) {
ast_map::node_item(@{node: ast::item_trait(_, ms), _}, _) {
store_methods::<ast::ty_method>(ccx, id, ms, |m| {
ty_of_ty_method(ccx, m, rp)
});
}
ast_map::node_item(@{node: ast::item_class(_,_,its,_,_,rp), _}, _) {
ast_map::node_item(@{node: ast::item_class(_,_,its,_,_), _}, _) {
let (_,ms) = split_class_items(its);
// All methods need to be stored, since lookup_method
// relies on the same method cache for self-calls
@@ -234,7 +235,7 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span,
fn check_methods_against_trait(ccx: @crate_ctxt,
tps: ~[ast::ty_param],
rp: ast::region_param,
rp: bool,
selfty: ty::t,
a_trait_ty: @ast::trait_ref,
ms: ~[converted_method]) {
@@ -267,7 +268,7 @@ fn check_methods_against_trait(ccx: @crate_ctxt,
} // fn
fn convert_class_item(ccx: @crate_ctxt,
rp: ast::region_param,
rp: bool,
bounds: @~[ty::param_bounds],
v: ast_util::ivar) {
let tt = ccx.to_ty(type_rscope(rp), v.ty);
@@ -280,7 +281,7 @@ type converted_method = {mty: ty::method, id: ast::node_id, span: span};
fn convert_methods(ccx: @crate_ctxt,
ms: ~[@ast::method],
rp: ast::region_param,
rp: bool,
rcvr_bounds: @~[ty::param_bounds],
self_ty: ty::t) -> ~[converted_method] {
@@ -303,16 +304,17 @@ fn convert_methods(ccx: @crate_ctxt,
fn convert(ccx: @crate_ctxt, it: @ast::item) {
let tcx = ccx.tcx;
let rp = tcx.region_paramd_items.contains_key(it.id);
#debug["convert: item %s with id %d rp %b", *it.ident, it.id, rp];
alt it.node {
// These don't define types.
ast::item_foreign_mod(_) | ast::item_mod(_) {}
ast::item_enum(variants, ty_params, rp) {
ast::item_enum(variants, ty_params) {
let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty);
get_enum_variant_types(ccx, tpt.ty, variants,
ty_params, rp);
get_enum_variant_types(ccx, tpt.ty, variants, ty_params, rp);
}
ast::item_impl(tps, rp, ifce, selfty, ms) {
ast::item_impl(tps, ifce, selfty, ms) {
let i_bounds = ty_param_bounds(ccx, tps);
let selfty = ccx.to_ty(type_rscope(rp), selfty);
write_ty_to_tcx(tcx, it.id, selfty);
@@ -333,7 +335,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
write_ty_to_tcx(tcx, it.id, tpt.ty);
ensure_trait_methods(ccx, it.id);
}
ast::item_class(tps, traits, members, ctor, m_dtor, rp) {
ast::item_class(tps, traits, members, ctor, m_dtor) {
// Write the class type
let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty);
@@ -341,20 +343,19 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
// Write the ctor type
let t_args = ctor.node.dec.inputs.map(
|a| ty_of_arg(ccx, type_rscope(rp), a, none) );
let t_res = ty::mk_class(tcx, local_def(it.id),
{self_r: alt rp {
ast::rp_none { none }
ast::rp_self { some(ty::re_bound(ty::br_self)) }
},
self_ty: none,
tps: ty::ty_params_to_tys(tcx, tps)});
let t_ctor = ty::mk_fn(tcx, {purity: ast::impure_fn,
proto: ast::proto_any,
inputs: t_args,
output: t_res,
ret_style: ast::return_val,
constraints: ~[]}); // FIXME (#2813): allow ctors to have
// constraints, or remove constraints from the language
let t_res = ty::mk_class(
tcx, local_def(it.id),
{self_r: if rp {some(ty::re_bound(ty::br_self))} else {none},
self_ty: none,
tps: ty::ty_params_to_tys(tcx, tps)});
let t_ctor = ty::mk_fn(
tcx, {purity: ast::impure_fn,
proto: ast::proto_any,
inputs: t_args,
output: t_res,
ret_style: ast::return_val,
constraints: ~[]}); // FIXME (#2813): allow ctors to have
// constraints, or remove constraints from the language
write_ty_to_tcx(tcx, ctor.node.id, t_ctor);
tcx.tcache.insert(local_def(ctor.node.id),
{bounds: tpt.bounds,
@@ -421,18 +422,18 @@ fn convert_foreign(ccx: @crate_ctxt, i: @ast::foreign_item) {
fn ty_of_method(ccx: @crate_ctxt,
m: @ast::method,
rp: ast::region_param) -> ty::method {
rp: bool) -> ty::method {
{ident: m.ident,
tps: ty_param_bounds(ccx, m.tps),
fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_bare,
m.decl, none),
m.decl, none),
purity: m.decl.purity,
vis: m.vis}
}
fn ty_of_ty_method(self: @crate_ctxt,
m: ast::ty_method,
rp: ast::region_param) -> ty::method {
rp: bool) -> ty::method {
{ident: m.ident,
tps: ty_param_bounds(self, m.tps),
fty: ty_of_fn_decl(self, type_rscope(rp), ast::proto_bare,
@@ -446,8 +447,7 @@ fn ty_of_ty_method(self: @crate_ctxt,
it's bound to a valid trait type. Returns the def_id for the defining
trait. Fails if the type is a type other than an trait type.
*/
fn instantiate_trait_ref(ccx: @crate_ctxt, t: @ast::trait_ref,
rp: ast::region_param)
fn instantiate_trait_ref(ccx: @crate_ctxt, t: @ast::trait_ref, rp: bool)
-> (ast::def_id, ty_param_substs_and_ty) {
let sp = t.path.span, err = "can only implement interface types",
@@ -480,6 +480,7 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
some(tpt) { ret tpt; }
_ {}
}
let rp = tcx.region_paramd_items.contains_key(it.id);
alt it.node {
ast::item_const(t, _) {
let typ = ccx.to_ty(empty_rscope, t);
@@ -492,19 +493,20 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
let tofd = ty_of_fn_decl(ccx, empty_rscope, ast::proto_bare,
decl, none);
let tpt = {bounds: bounds,
rp: ast::rp_none, // functions do not have a self
rp: false, // functions do not have a self
ty: ty::mk_fn(ccx.tcx, tofd)};
#debug["type of %s (id %d) is %s",
*it.ident, it.id, ty_to_str(tcx, tpt.ty)];
ccx.tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
ast::item_ty(t, tps, rp) {
ast::item_ty(t, tps) {
alt tcx.tcache.find(local_def(it.id)) {
some(tpt) { ret tpt; }
none { }
}
let rp = tcx.region_paramd_items.contains_key(it.id);
let tpt = {
let ty = {
let t0 = ccx.to_ty(type_rscope(rp), t);
@@ -522,7 +524,7 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
ast::item_enum(_, tps, rp) {
ast::item_enum(_, tps) {
// Create a new generic polytype.
let {bounds, substs} = mk_substs(ccx, tps, rp);
let t = ty::mk_enum(tcx, local_def(it.id), substs);
@@ -530,14 +532,14 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
ast::item_trait(tps, rp, ms) {
ast::item_trait(tps, ms) {
let {bounds, substs} = mk_substs(ccx, tps, rp);
let t = ty::mk_trait(tcx, local_def(it.id), substs);
let tpt = {bounds: bounds, rp: rp, ty: t};
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
ast::item_class(tps, _, _, _, _, rp) {
ast::item_class(tps, _, _, _, _) {
let {bounds,substs} = mk_substs(ccx, tps, rp);
let t = ty::mk_class(tcx, local_def(it.id), substs);
let tpt = {bounds: bounds, rp: rp, ty: t};
@@ -555,7 +557,7 @@ fn ty_of_foreign_item(ccx: @crate_ctxt, it: @ast::foreign_item)
alt it.node {
ast::foreign_item_fn(fn_decl, params) {
ret ty_of_foreign_fn_decl(ccx, fn_decl, params,
local_def(it.id));
local_def(it.id));
}
}
}
@@ -615,7 +617,7 @@ fn ty_of_foreign_fn_decl(ccx: @crate_ctxt,
output: output_ty,
ret_style: ast::return_val,
constraints: ~[]});
let tpt = {bounds: bounds, rp: ast::rp_none, ty: t_fn};
let tpt = {bounds: bounds, rp: false, ty: t_fn};
ccx.tcx.tcache.insert(def_id, tpt);
ret tpt;
}
@@ -633,13 +635,10 @@ fn mk_ty_params(ccx: @crate_ctxt, atps: ~[ast::ty_param])
})}
}
fn mk_substs(ccx: @crate_ctxt, atps: ~[ast::ty_param], rp: ast::region_param)
fn mk_substs(ccx: @crate_ctxt, atps: ~[ast::ty_param], rp: bool)
-> {bounds: @~[ty::param_bounds], substs: ty::substs} {
let {bounds, params} = mk_ty_params(ccx, atps);
let self_r = alt rp {
ast::rp_self { some(ty::re_bound(ty::br_self)) }
ast::rp_none { none }
};
let self_r = if rp {some(ty::re_bound(ty::br_self))} else {none};
{bounds: bounds, substs: {self_r: self_r, self_ty: none, tps: params}}
}

View File

@@ -16,15 +16,14 @@ impl of region_scope for empty_rscope {
}
}
enum type_rscope = ast::region_param;
enum type_rscope = bool;
impl of region_scope for type_rscope {
fn anon_region() -> result<ty::region, str> {
alt *self {
ast::rp_self { result::ok(ty::re_bound(ty::br_self)) }
ast::rp_none {
if *self {
result::ok(ty::re_bound(ty::br_self))
} else {
result::err("to use region types here, the containing type \
must be declared with a region bound")
}
}
}
fn named_region(id: ast::ident) -> result<ty::region, str> {