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:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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| {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
_ {}
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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}}
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
|
||||
Reference in New Issue
Block a user