auto merge of #5676 : nikomatsakis/rust/issue-4183-trait_ref, r=nikomatsakis

These are a number of incremental steps towards #4183 and #4646.
This commit is contained in:
bors 2013-04-05 18:00:52 -07:00
commit 08e2cf846a
60 changed files with 1898 additions and 1425 deletions

View file

@ -1394,7 +1394,7 @@ pub mod funcs {
use libc::types::common::posix88::{DIR, dirent_t};
use libc::types::os::arch::c95::{c_char, c_int, c_long};
// NOTE: On OS X opendir and readdir have two versions,
// NB: On OS X opendir and readdir have two versions,
// one for 32-bit kernelspace and one for 64.
// We should be linking to the 64-bit ones, called
// opendir$INODE64, etc. but for some reason rustc

View file

@ -46,7 +46,8 @@ use ops::Add;
use kinds::Copy;
use util;
use num::Zero;
use iter::{BaseIter, MutableIter};
use iter::{BaseIter, MutableIter, ExtendedIter};
use iter;
#[cfg(test)] use ptr;
#[cfg(test)] use str;
@ -118,6 +119,31 @@ impl<T> MutableIter<T> for Option<T> {
}
}
impl<A> ExtendedIter<A> for Option<A> {
pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) {
iter::eachi(self, blk)
}
pub fn all(&self, blk: &fn(&A) -> bool) -> bool {
iter::all(self, blk)
}
pub fn any(&self, blk: &fn(&A) -> bool) -> bool {
iter::any(self, blk)
}
pub fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B {
iter::foldl(self, b0, blk)
}
pub fn position(&self, f: &fn(&A) -> bool) -> Option<uint> {
iter::position(self, f)
}
fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B] {
iter::map_to_vec(self, op)
}
fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: &fn(&A) -> IB)
-> ~[B] {
iter::flat_map_to_vec(self, op)
}
}
pub impl<T> Option<T> {
/// Returns true if the option equals `none`
fn is_none(&const self) -> bool {

View file

@ -443,9 +443,9 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
}
fn visit_trait(&self) -> bool {
self.align_to::<TyVisitor>();
self.align_to::<@TyVisitor>();
if ! self.inner.visit_trait() { return false; }
self.bump_past::<TyVisitor>();
self.bump_past::<@TyVisitor>();
true
}

View file

@ -298,7 +298,7 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program {
@ProgRes(repr) as @Program
}
fn read_all(rd: io::Reader) -> ~str {
fn read_all(rd: @io::Reader) -> ~str {
let buf = io::with_bytes_writer(|wr| {
let mut bytes = [0, ..4096];
while !rd.eof() {

View file

@ -308,7 +308,7 @@ pub fn compile_rest(sess: Session, cfg: ast::crate_cfg,
};
// NOTE: Android hack
// NB: Android hack
if sess.targ_cfg.arch == abi::Arm &&
(sess.opts.output_type == link::output_type_object ||
sess.opts.output_type == link::output_type_exe) {

View file

@ -74,7 +74,9 @@ pub static tag_crate_dep_vers: uint = 0x2cu;
pub static tag_mod_impl: uint = 0x30u;
pub static tag_item_trait_method: uint = 0x31u;
pub static tag_impl_trait: uint = 0x32u;
pub static tag_item_trait_ref: uint = 0x32u;
pub static tag_item_super_trait_ref: uint = 0x33u;
// discriminator value for variants
pub static tag_disr_val: uint = 0x34u;
@ -102,6 +104,7 @@ pub static tag_item_dtor: uint = 0x49u;
pub static tag_item_trait_method_self_ty: uint = 0x4b;
pub static tag_item_trait_method_self_ty_region: uint = 0x4c;
// Reexports are found within module tags. Each reexport contains def_ids
// and names.
pub static tag_items_data_item_reexport: uint = 0x4d;
@ -159,6 +162,10 @@ pub static tag_items_data_item_visibility: uint = 0x78;
pub static tag_link_args: uint = 0x79;
pub static tag_link_args_arg: uint = 0x7a;
pub static tag_item_method_tps: uint = 0x7b;
pub static tag_item_method_fty: uint = 0x7c;
pub static tag_item_method_transformed_self_ty: uint = 0x7d;
pub struct LinkMeta {
name: @str,
vers: @str,

View file

@ -111,12 +111,24 @@ pub fn get_impls_for_mod(cstore: @mut cstore::CStore, def: ast::def_id,
}
}
pub fn get_trait_methods(tcx: ty::ctxt,
def: ast::def_id)
-> @~[ty::method] {
let cstore = tcx.cstore;
pub fn get_method(tcx: ty::ctxt,
def: ast::def_id) -> ty::method
{
let cdata = cstore::get_crate_data(tcx.cstore, def.crate);
decoder::get_method(tcx.cstore.intr, cdata, def.node, tcx)
}
pub fn get_method_name_and_self_ty(cstore: @mut cstore::CStore,
def: ast::def_id) -> (ast::ident, ast::self_ty_)
{
let cdata = cstore::get_crate_data(cstore, def.crate);
decoder::get_trait_methods(cstore.intr, cdata, def.node, tcx)
decoder::get_method_name_and_self_ty(cstore.intr, cdata, def.node)
}
pub fn get_trait_method_def_ids(cstore: @mut cstore::CStore,
def: ast::def_id) -> ~[ast::def_id] {
let cdata = cstore::get_crate_data(cstore, def.crate);
decoder::get_trait_method_def_ids(cdata, def.node)
}
pub fn get_provided_trait_methods(tcx: ty::ctxt,
@ -127,19 +139,12 @@ pub fn get_provided_trait_methods(tcx: ty::ctxt,
decoder::get_provided_trait_methods(cstore.intr, cdata, def.node, tcx)
}
pub fn get_supertraits(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::t] {
pub fn get_supertraits(tcx: ty::ctxt, def: ast::def_id) -> ~[@ty::TraitRef] {
let cstore = tcx.cstore;
let cdata = cstore::get_crate_data(cstore, def.crate);
decoder::get_supertraits(cdata, def.node, tcx)
}
pub fn get_method_names_if_trait(cstore: @mut cstore::CStore,
def: ast::def_id)
-> Option<~[(ast::ident, ast::self_ty_)]> {
let cdata = cstore::get_crate_data(cstore, def.crate);
return decoder::get_method_names_if_trait(cstore.intr, cdata, def.node);
}
pub fn get_type_name_if_impl(cstore: @mut cstore::CStore, def: ast::def_id)
-> Option<ast::ident> {
let cdata = cstore::get_crate_data(cstore, def.crate);
@ -175,6 +180,12 @@ pub fn get_type(tcx: ty::ctxt,
decoder::get_type(cdata, def.node, tcx)
}
pub fn get_trait_def(tcx: ty::ctxt, def: ast::def_id) -> ty::TraitDef {
let cstore = tcx.cstore;
let cdata = cstore::get_crate_data(cstore, def.crate);
decoder::get_trait_def(cdata, def.node, tcx)
}
pub fn get_region_param(cstore: @mut metadata::cstore::CStore,
def: ast::def_id) -> Option<ty::region_variance> {
let cdata = cstore::get_crate_data(cstore, def.crate);
@ -199,8 +210,8 @@ pub fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
debug!("got field data %?", the_field);
let ty = decoder::item_type(def, the_field, tcx, cdata);
ty::ty_param_bounds_and_ty {
bounds: @~[],
region_param: None,
generics: ty::Generics {bounds: @~[],
region_param: None},
ty: ty
}
}
@ -208,7 +219,8 @@ pub fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
// Given a def_id for an impl or class, return the traits it implements,
// or the empty vector if it's not for an impl or for a class that implements
// traits
pub fn get_impl_traits(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::t] {
pub fn get_impl_traits(tcx: ty::ctxt,
def: ast::def_id) -> ~[@ty::TraitRef] {
let cstore = tcx.cstore;
let cdata = cstore::get_crate_data(cstore, def.crate);
decoder::get_impl_traits(cdata, def.node, tcx)

View file

@ -19,7 +19,8 @@ use metadata::csearch::{ProvidedTraitMethodInfo, StaticMethodInfo};
use metadata::csearch;
use metadata::cstore;
use metadata::decoder;
use metadata::tydecode::{parse_ty_data, parse_def_id, parse_bounds_data};
use metadata::tydecode::{parse_ty_data, parse_def_id, parse_bounds_data,
parse_bare_fn_ty_data, parse_trait_ref_data};
use middle::{ty, resolve};
use core::hash::HashUtil;
@ -229,6 +230,22 @@ fn doc_type(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t {
|_, did| translate_def_id(cdata, did))
}
fn doc_method_fty(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::BareFnTy {
let tp = reader::get_doc(doc, tag_item_method_fty);
parse_bare_fn_ty_data(tp.data, cdata.cnum, tp.start, tcx,
|_, did| translate_def_id(cdata, did))
}
fn doc_transformed_self_ty(doc: ebml::Doc,
tcx: ty::ctxt,
cdata: cmd) -> Option<ty::t>
{
do reader::maybe_get_doc(doc, tag_item_method_transformed_self_ty).map |tp| {
parse_ty_data(tp.data, cdata.cnum, tp.start, tcx,
|_, did| translate_def_id(cdata, did))
}
}
pub fn item_type(item_id: ast::def_id, item: ebml::Doc,
tcx: ty::ctxt, cdata: cmd) -> ty::t {
let t = doc_type(item, tcx, cdata);
@ -239,18 +256,21 @@ pub fn item_type(item_id: ast::def_id, item: ebml::Doc,
}
}
fn item_impl_traits(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ~[ty::t] {
let mut results = ~[];
for reader::tagged_docs(item, tag_impl_trait) |ity| {
results.push(doc_type(ity, tcx, cdata));
};
results
fn doc_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::TraitRef {
parse_trait_ref_data(doc.data, cdata.cnum, doc.start, tcx,
|_, did| translate_def_id(cdata, did))
}
fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd)
fn item_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::TraitRef {
let tp = reader::get_doc(doc, tag_item_trait_ref);
doc_trait_ref(tp, tcx, cdata)
}
fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd,
tag: uint)
-> @~[ty::param_bounds] {
let mut bounds = ~[];
for reader::tagged_docs(item, tag_items_data_item_ty_param_bounds) |p| {
for reader::tagged_docs(item, tag) |p| {
let bd = parse_bounds_data(p.data, p.start, cdata.cnum, tcx,
|_, did| translate_def_id(cdata, did));
bounds.push(bd);
@ -338,7 +358,8 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num)
let enum_did = item_reqd_and_translated_parent_item(cnum, item);
dl_def(ast::def_variant(enum_did, did))
}
Trait | Enum => dl_def(ast::def_ty(did)),
Trait => dl_def(ast::def_trait(did)),
Enum => dl_def(ast::def_ty(did)),
Impl => dl_impl(did),
PublicField | PrivateField | InheritedField => dl_field,
}
@ -352,6 +373,21 @@ pub fn lookup_def(cnum: ast::crate_num, data: @~[u8], did_: ast::def_id) ->
return def_like_to_def(item_to_def_like(item, did, cnum));
}
pub fn get_trait_def(cdata: cmd,
item_id: ast::node_id,
tcx: ty::ctxt) -> ty::TraitDef
{
let item_doc = lookup_item(item_id, cdata.data);
let tp_bounds = item_ty_param_bounds(item_doc, tcx, cdata,
tag_items_data_item_ty_param_bounds);
let rp = item_ty_region_param(item_doc);
ty::TraitDef {
generics: ty::Generics {bounds: tp_bounds,
region_param: rp},
trait_ref: @item_trait_ref(item_doc, tcx, cdata)
}
}
pub fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
-> ty::ty_param_bounds_and_ty {
@ -359,12 +395,12 @@ pub fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
let t = item_type(ast::def_id { crate: cdata.cnum, node: id }, item, tcx,
cdata);
let tp_bounds = if family_has_type_params(item_family(item)) {
item_ty_param_bounds(item, tcx, cdata)
item_ty_param_bounds(item, tcx, cdata, tag_items_data_item_ty_param_bounds)
} else { @~[] };
let rp = item_ty_region_param(item);
ty::ty_param_bounds_and_ty {
bounds: tp_bounds,
region_param: rp,
generics: ty::Generics {bounds: tp_bounds,
region_param: rp},
ty: t
}
}
@ -380,9 +416,19 @@ pub fn get_type_param_count(data: @~[u8], id: ast::node_id) -> uint {
item_ty_param_count(lookup_item(id, data))
}
pub fn get_impl_traits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
-> ~[ty::t] {
item_impl_traits(lookup_item(id, cdata.data), tcx, cdata)
pub fn get_impl_traits(cdata: cmd,
id: ast::node_id,
tcx: ty::ctxt) -> ~[@ty::TraitRef]
{
let item_doc = lookup_item(id, cdata.data);
let mut results = ~[];
for reader::tagged_docs(item_doc, tag_item_trait_ref) |tp| {
let trait_ref =
@parse_trait_ref_data(tp.data, cdata.cnum, tp.start, tcx,
|_, did| translate_def_id(cdata, did));
results.push(trait_ref);
};
results
}
pub fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
@ -690,36 +736,53 @@ pub fn get_impls_for_mod(intr: @ident_interner,
@result
}
/* Works for both classes and traits */
pub fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id,
tcx: ty::ctxt) -> @~[ty::method] {
pub fn get_method_name_and_self_ty(
intr: @ident_interner,
cdata: cmd,
id: ast::node_id) -> (ast::ident, ast::self_ty_)
{
let method_doc = lookup_item(id, cdata.data);
let name = item_name(intr, method_doc);
let self_ty = get_self_ty(method_doc);
(name, self_ty)
}
pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
tcx: ty::ctxt) -> ty::method
{
let method_doc = lookup_item(id, cdata.data);
let def_id = item_def_id(method_doc, cdata);
let name = item_name(intr, method_doc);
let bounds =
item_ty_param_bounds(method_doc, tcx, cdata,
tag_item_method_tps);
let transformed_self_ty = doc_transformed_self_ty(method_doc, tcx, cdata);
let fty = doc_method_fty(method_doc, tcx, cdata);
let vis = item_visibility(method_doc);
let self_ty = get_self_ty(method_doc);
ty::method {
ident: name,
generics: ty::Generics {
bounds: bounds,
region_param: None
},
transformed_self_ty: transformed_self_ty,
fty: fty,
self_ty: self_ty,
vis: vis,
def_id: def_id
}
}
pub fn get_trait_method_def_ids(cdata: cmd,
id: ast::node_id) -> ~[ast::def_id] {
let data = cdata.data;
let item = lookup_item(id, data);
let mut result = ~[];
for reader::tagged_docs(item, tag_item_trait_method) |mth| {
let bounds = item_ty_param_bounds(mth, tcx, cdata);
let name = item_name(intr, mth);
let ty = doc_type(mth, tcx, cdata);
let def_id = item_def_id(mth, cdata);
let fty = match ty::get(ty).sty {
ty::ty_bare_fn(ref f) => copy *f,
_ => {
tcx.diag.handler().bug(
~"get_trait_methods: id has non-function type");
}
};
let self_ty = get_self_ty(mth);
result.push(ty::method {
ident: name,
tps: bounds,
fty: fty,
self_ty: self_ty,
vis: ast::public,
def_id: def_id
});
result.push(item_def_id(mth, cdata));
}
debug!("get_trait_methods: }");
@result
result
}
pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
@ -734,7 +797,8 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
let did = item_def_id(mth, cdata);
let bounds = item_ty_param_bounds(mth, tcx, cdata);
let bounds = item_ty_param_bounds(mth, tcx, cdata,
tag_items_data_item_ty_param_bounds);
let name = item_name(intr, mth);
let ty = doc_type(mth, tcx, cdata);
@ -746,10 +810,15 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
}
};
let transformed_self_ty = doc_transformed_self_ty(mth, tcx, cdata);
let self_ty = get_self_ty(mth);
let ty_method = ty::method {
ident: name,
tps: bounds,
generics: ty::Generics {
bounds: bounds,
region_param: None
},
transformed_self_ty: transformed_self_ty,
fty: fty,
self_ty: self_ty,
vis: ast::public,
@ -768,35 +837,15 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
/// Returns the supertraits of the given trait.
pub fn get_supertraits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
-> ~[ty::t] {
-> ~[@ty::TraitRef] {
let mut results = ~[];
let item_doc = lookup_item(id, cdata.data);
for reader::tagged_docs(item_doc, tag_impl_trait) |trait_doc| {
results.push(doc_type(trait_doc, tcx, cdata));
for reader::tagged_docs(item_doc, tag_item_super_trait_ref) |trait_doc| {
results.push(@doc_trait_ref(trait_doc, tcx, cdata));
}
return results;
}
// If the item in question is a trait, returns its set of methods and
// their self types. Otherwise, returns none. This overlaps in an
// annoying way with get_trait_methods.
pub fn get_method_names_if_trait(intr: @ident_interner, cdata: cmd,
node_id: ast::node_id)
-> Option<~[(ast::ident, ast::self_ty_)]> {
let item = lookup_item(node_id, cdata.data);
if item_family(item) != Trait {
return None;
}
let mut resulting_methods = ~[];
for reader::tagged_docs(item, tag_item_trait_method) |method| {
resulting_methods.push(
(item_name(intr, method), get_self_ty(method)));
}
return Some(resulting_methods);
}
pub fn get_type_name_if_impl(intr: @ident_interner,
cdata: cmd,
node_id: ast::node_id) -> Option<ast::ident> {
@ -821,8 +870,8 @@ pub fn get_static_methods_if_impl(intr: @ident_interner,
return None;
}
// If this impl has a trait ref, don't consider it.
for reader::tagged_docs(item, tag_impl_trait) |_doc| {
// If this impl implements a trait, don't consider it.
for reader::tagged_docs(item, tag_item_trait_ref) |_doc| {
return None;
}

View file

@ -153,14 +153,23 @@ fn add_to_index(ecx: @EncodeContext, ebml_w: writer::Encoder, path: &[ident],
});
}
fn encode_trait_ref(ebml_w: writer::Encoder, ecx: @EncodeContext,
t: @trait_ref) {
ebml_w.start_tag(tag_impl_trait);
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, t.ref_id));
fn encode_trait_ref(ebml_w: writer::Encoder,
ecx: @EncodeContext,
trait_ref: &ty::TraitRef,
tag: uint)
{
let ty_str_ctxt = @tyencode::ctxt {
diag: ecx.diag,
ds: def_to_str,
tcx: ecx.tcx,
reachable: |a| reachable(ecx, a),
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
ebml_w.start_tag(tag);
tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
ebml_w.end_tag();
}
// Item info table encoding
fn encode_family(ebml_w: writer::Encoder, c: char) {
ebml_w.start_tag(tag_items_data_item_family);
@ -170,8 +179,10 @@ fn encode_family(ebml_w: writer::Encoder, c: char) {
pub fn def_to_str(did: def_id) -> ~str { fmt!("%d:%d", did.crate, did.node) }
fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, ecx: @EncodeContext,
params: @~[ty::param_bounds]) {
fn encode_ty_type_param_bounds(ebml_w: writer::Encoder,
ecx: @EncodeContext,
params: @~[ty::param_bounds],
tag: uint) {
let ty_str_ctxt = @tyencode::ctxt {
diag: ecx.diag,
ds: def_to_str,
@ -179,7 +190,7 @@ fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, ecx: @EncodeContext,
reachable: |a| reachable(ecx, a),
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
for params.each |param| {
ebml_w.start_tag(tag_items_data_item_ty_param_bounds);
ebml_w.start_tag(tag);
tyencode::enc_bounds(ebml_w.writer, ty_str_ctxt, *param);
ebml_w.end_tag();
}
@ -190,7 +201,8 @@ fn encode_type_param_bounds(ebml_w: writer::Encoder,
params: &OptVec<TyParam>) {
let ty_param_bounds =
@params.map_to_vec(|param| *ecx.tcx.ty_param_bounds.get(&param.id));
encode_ty_type_param_bounds(ebml_w, ecx, ty_param_bounds);
encode_ty_type_param_bounds(ebml_w, ecx, ty_param_bounds,
tag_items_data_item_ty_param_bounds);
}
@ -227,6 +239,34 @@ fn encode_type(ecx: @EncodeContext, ebml_w: writer::Encoder, typ: ty::t) {
ebml_w.end_tag();
}
fn encode_transformed_self_ty(ecx: @EncodeContext,
ebml_w: writer::Encoder,
opt_typ: Option<ty::t>)
{
for opt_typ.each |&typ| {
ebml_w.start_tag(tag_item_method_transformed_self_ty);
write_type(ecx, ebml_w, typ);
ebml_w.end_tag();
}
}
fn encode_method_fty(ecx: @EncodeContext,
ebml_w: writer::Encoder,
typ: &ty::BareFnTy)
{
ebml_w.start_tag(tag_item_method_fty);
let ty_str_ctxt = @tyencode::ctxt {
diag: ecx.diag,
ds: def_to_str,
tcx: ecx.tcx,
reachable: |a| reachable(ecx, a),
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
ebml_w.end_tag();
}
fn encode_symbol(ecx: @EncodeContext, ebml_w: writer::Encoder, id: node_id) {
ebml_w.start_tag(tag_items_data_item_symbol);
match ecx.item_symbols.find(&id) {
@ -542,13 +582,26 @@ fn encode_info_for_struct_ctor(ecx: @EncodeContext,
ebml_w.end_tag();
}
fn encode_method_ty_fields(ecx: @EncodeContext,
ebml_w: writer::Encoder,
method_ty: &ty::method)
{
encode_def_id(ebml_w, method_ty.def_id);
encode_name(ecx, ebml_w, method_ty.ident);
encode_ty_type_param_bounds(ebml_w, ecx, method_ty.generics.bounds,
tag_item_method_tps);
encode_transformed_self_ty(ecx, ebml_w, method_ty.transformed_self_ty);
encode_method_fty(ecx, ebml_w, &method_ty.fty);
encode_visibility(ebml_w, method_ty.vis);
encode_self_type(ebml_w, method_ty.self_ty);
}
fn encode_info_for_method(ecx: @EncodeContext,
ebml_w: writer::Encoder,
impl_path: &[ast_map::path_elt],
should_inline: bool,
parent_id: node_id,
m: @method,
parent_visibility: ast::visibility,
owner_generics: &ast::Generics,
method_generics: &ast::Generics) {
debug!("encode_info_for_method: %d %s %u %u", m.id,
@ -556,7 +609,10 @@ fn encode_info_for_method(ecx: @EncodeContext,
owner_generics.ty_params.len(),
method_generics.ty_params.len());
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(m.id));
let method_def_id = local_def(m.id);
let method_ty: @ty::method = ty::method(ecx.tcx, method_def_id);
encode_method_ty_fields(ecx, ebml_w, method_ty);
match m.self_ty.node {
ast::sty_static => {
@ -572,16 +628,7 @@ fn encode_info_for_method(ecx: @EncodeContext,
encode_type_param_bounds(ebml_w, ecx, &combined_ty_params);
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id));
encode_name(ecx, ebml_w, m.ident);
encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident));
encode_self_type(ebml_w, m.self_ty.node);
// Combine parent visibility and this visibility.
let visibility = match m.vis {
ast::inherited => parent_visibility,
vis => vis,
};
encode_visibility(ebml_w, visibility);
if len > 0u || should_inline {
(ecx.encode_inlined_item)(
@ -590,6 +637,7 @@ fn encode_info_for_method(ecx: @EncodeContext,
} else {
encode_symbol(ecx, ebml_w, m.id);
}
ebml_w.end_tag();
}
@ -833,8 +881,9 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
ebml_w.writer.write(str::to_bytes(def_to_str(method_def_id)));
ebml_w.end_tag();
}
for opt_trait.each |associated_trait| {
encode_trait_ref(ebml_w, ecx, *associated_trait);
for opt_trait.each |ast_trait_ref| {
let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref);
}
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
ebml_w.end_tag();
@ -843,17 +892,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
let mut impl_path = vec::append(~[], path);
impl_path += ~[ast_map::path_name(item.ident)];
// If there is a trait reference, treat the methods as always public.
// This is to work around some incorrect behavior in privacy checking:
// when the method belongs to a trait, it should acquire the privacy
// from the trait, not the impl. Forcing the visibility to be public
// makes things sorta work.
let parent_visibility = if opt_trait.is_some() {
ast::public
} else {
item.vis
};
for methods.each |m| {
index.push(entry {val: m.id, pos: ebml_w.writer.tell()});
encode_info_for_method(ecx,
@ -862,113 +900,95 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
should_inline(m.attrs),
item.id,
*m,
parent_visibility,
generics,
&m.generics);
}
}
item_trait(ref generics, ref traits, ref ms) => {
let mut provided_methods = ~[];
item_trait(ref generics, ref super_traits, ref 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(ecx, ebml_w, item);
encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
let trait_def = ty::lookup_trait_def(tcx, local_def(item.id));
encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
encode_name(ecx, ebml_w, item.ident);
encode_attributes(ebml_w, item.attrs);
let mut i = 0u;
for vec::each(*ty::trait_methods(tcx, local_def(item.id))) |mty| {
match (*ms)[i] {
required(ref ty_m) => {
ebml_w.start_tag(tag_item_trait_method);
encode_def_id(ebml_w, local_def((*ty_m).id));
encode_name(ecx, ebml_w, mty.ident);
encode_type_param_bounds(ebml_w, ecx,
&ty_m.generics.ty_params);
encode_type(ecx, ebml_w,
ty::mk_bare_fn(tcx, copy mty.fty));
encode_family(ebml_w, purity_fn_family(mty.fty.purity));
encode_self_type(ebml_w, mty.self_ty);
encode_method_sort(ebml_w, 'r');
encode_visibility(ebml_w, ast::public);
ebml_w.end_tag();
}
provided(m) => {
provided_methods.push(m);
ebml_w.start_tag(tag_item_trait_method);
encode_def_id(ebml_w, local_def(m.id));
encode_name(ecx, ebml_w, mty.ident);
encode_type_param_bounds(ebml_w, ecx,
&m.generics.ty_params);
encode_type(ecx, ebml_w,
ty::mk_bare_fn(tcx, copy mty.fty));
encode_family(ebml_w, purity_fn_family(mty.fty.purity));
encode_self_type(ebml_w, mty.self_ty);
encode_method_sort(ebml_w, 'p');
encode_visibility(ebml_w, m.vis);
ebml_w.end_tag();
}
}
i += 1;
}
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
for traits.each |associated_trait| {
encode_trait_ref(ebml_w, ecx, *associated_trait)
}
ebml_w.end_tag();
// Now, output all of the static methods as items. Note that for the
// method info, we output static methods with type signatures as
// written. Here, we output the *real* type signatures. I feel like
// maybe we should only ever handle the real type signatures.
for ms.each |m| {
let ty_m = ast_util::trait_method_to_ty_method(m);
if ty_m.self_ty.node != ast::sty_static { loop; }
index.push(entry { val: ty_m.id, pos: ebml_w.writer.tell() });
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(ty_m.id));
encode_parent_item(ebml_w, local_def(item.id));
encode_name(ecx, ebml_w, ty_m.ident);
encode_family(ebml_w,
purity_static_method_family(ty_m.purity));
let polyty = ecx.tcx.tcache.get(&local_def(ty_m.id));
encode_ty_type_param_bounds(ebml_w, ecx, polyty.bounds);
encode_type(ecx, ebml_w, polyty.ty);
let mut m_path = vec::append(~[], path); // :-(
m_path += [ast_map::path_name(item.ident)];
encode_path(ecx, ebml_w, m_path, ast_map::path_name(ty_m.ident));
// For now, use the item visibility until trait methods can have
// real visibility in the AST.
encode_visibility(ebml_w, item.vis);
for ty::trait_method_def_ids(tcx, local_def(item.id)).each |&method_def_id| {
ebml_w.start_tag(tag_item_trait_method);
encode_def_id(ebml_w, method_def_id);
ebml_w.end_tag();
}
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
for super_traits.each |ast_trait_ref| {
let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref);
}
ebml_w.end_tag();
// Finally, output all the provided methods as items.
for provided_methods.each |m| {
index.push(entry { val: m.id, pos: ebml_w.writer.tell() });
// Now output the method info for each method.
for ty::trait_method_def_ids(tcx, local_def(item.id)).eachi |i, &method_def_id| {
assert!(method_def_id.crate == ast::local_crate);
// We do not concatenate the generics of the owning impl and that
// of provided methods. I am not sure why this is. -ndm
let owner_generics = ast_util::empty_generics();
let method_ty: @ty::method = ty::method(tcx, method_def_id);
encode_info_for_method(ecx,
ebml_w,
/*bad*/copy path,
true,
item.id,
*m,
item.vis,
&owner_generics,
&m.generics);
index.push(entry {val: method_def_id.node, pos: ebml_w.writer.tell()});
ebml_w.start_tag(tag_items_data_item);
encode_method_ty_fields(ecx, ebml_w, method_ty);
encode_parent_item(ebml_w, local_def(item.id));
let mut trait_path = vec::append(~[], path);
trait_path.push(ast_map::path_name(item.ident));
encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident));
match method_ty.self_ty {
sty_static => {
encode_family(ebml_w,
purity_static_method_family(
method_ty.fty.purity));
let tpt = ty::lookup_item_type(tcx, method_def_id);
encode_ty_type_param_bounds(ebml_w, ecx, tpt.generics.bounds,
tag_items_data_item_ty_param_bounds);
encode_type(ecx, ebml_w, tpt.ty);
}
_ => {
encode_family(ebml_w,
purity_fn_family(
method_ty.fty.purity));
}
}
match ms[i] {
required(_) => {
encode_method_sort(ebml_w, 'r');
}
provided(m) => {
// This is obviously a bogus assert but I don't think this
// ever worked before anyhow...near as I can tell, before
// we would emit two items.
if method_ty.self_ty == sty_static {
tcx.sess.span_unimpl(
item.span,
fmt!("Method %s is both provided and static",
*tcx.sess.intr().get(method_ty.ident)));
}
encode_type_param_bounds(ebml_w, ecx,
&m.generics.ty_params);
encode_method_sort(ebml_w, 'p');
(ecx.encode_inlined_item)(
ecx, ebml_w, path,
ii_method(local_def(item.id), m));
}
}
ebml_w.end_tag();
}
}
item_mac(*) => fail!(~"item macros unimplemented")

View file

@ -119,6 +119,18 @@ pub fn parse_ty_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
parse_ty(st, conv)
}
pub fn parse_bare_fn_ty_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
conv: conv_did) -> ty::BareFnTy {
let st = parse_state_from_data(data, crate_num, pos, tcx);
parse_bare_fn_ty(st, conv)
}
pub fn parse_trait_ref_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
conv: conv_did) -> ty::TraitRef {
let st = parse_state_from_data(data, crate_num, pos, tcx);
parse_trait_ref(st, conv)
}
pub fn parse_arg_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
conv: conv_did) -> ty::arg {
let st = parse_state_from_data(data, crate_num, pos, tcx);
@ -177,7 +189,6 @@ fn parse_trait_store(st: @mut PState) -> ty::TraitStore {
'~' => ty::UniqTraitStore,
'@' => ty::BoxTraitStore,
'&' => ty::RegionTraitStore(parse_region(st)),
'.' => ty::BareTraitStore,
c => st.tcx.sess.bug(fmt!("parse_trait_store(): bad input '%c'", c))
}
}
@ -259,6 +270,12 @@ fn parse_str(st: @mut PState, term: char) -> ~str {
return result;
}
fn parse_trait_ref(st: @mut PState, conv: conv_did) -> ty::TraitRef {
let def = parse_def(st, NominalType, conv);
let substs = parse_substs(st, conv);
ty::TraitRef {def_id: def, substs: substs}
}
fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t {
match next(st) {
'n' => return ty::mk_nil(st.tcx),
@ -545,7 +562,7 @@ fn parse_bounds(st: @mut PState, conv: conv_did) -> @~[ty::param_bound] {
'C' => ty::bound_copy,
'K' => ty::bound_const,
'O' => ty::bound_durable,
'I' => ty::bound_trait(parse_ty(st, conv)),
'I' => ty::bound_trait(@parse_trait_ref(st, conv)),
'.' => break,
_ => fail!(~"parse_bounds: bad bounds")
});

View file

@ -214,11 +214,16 @@ pub fn enc_vstore(w: @io::Writer, cx: @ctxt, v: ty::vstore) {
}
}
pub fn enc_trait_ref(w: @io::Writer, cx: @ctxt, s: &ty::TraitRef) {
w.write_str((cx.ds)(s.def_id));
w.write_char('|');
enc_substs(w, cx, s.substs);
}
pub fn enc_trait_store(w: @io::Writer, cx: @ctxt, s: ty::TraitStore) {
match s {
ty::UniqTraitStore => w.write_char('~'),
ty::BoxTraitStore => w.write_char('@'),
ty::BareTraitStore => w.write_char('.'),
ty::RegionTraitStore(re) => {
w.write_char('&');
enc_region(w, cx, re);
@ -384,7 +389,7 @@ fn enc_onceness(w: @io::Writer, o: Onceness) {
}
}
fn enc_bare_fn_ty(w: @io::Writer, cx: @ctxt, ft: &ty::BareFnTy) {
pub fn enc_bare_fn_ty(w: @io::Writer, cx: @ctxt, ft: &ty::BareFnTy) {
enc_purity(w, ft.purity);
enc_abi_set(w, ft.abis);
enc_fn_sig(w, cx, &ft.sig);
@ -415,8 +420,8 @@ pub fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: @~[ty::param_bound]) {
ty::bound_const => w.write_char('K'),
ty::bound_durable => w.write_char('O'),
ty::bound_trait(tp) => {
w.write_char('I');
enc_ty(w, cx, tp);
w.write_char('I');
enc_trait_ref(w, cx, tp);
}
}
}

View file

@ -417,6 +417,7 @@ impl tr for ast::def {
ast::def_variant(e_did, v_did) => {
ast::def_variant(e_did.tr(xcx), v_did.tr(xcx))
}
ast::def_trait(did) => ast::def_trait(did.tr(xcx)),
ast::def_ty(did) => ast::def_ty(did.tr(xcx)),
ast::def_prim_ty(p) => ast::def_prim_ty(p),
ast::def_ty_param(did, v) => ast::def_ty_param(did.tr(xcx), v),
@ -778,16 +779,20 @@ impl ebml_writer_helpers for writer::Encoder {
fn emit_tpbt(&self, ecx: @e::EncodeContext,
tpbt: ty::ty_param_bounds_and_ty) {
do self.emit_struct("ty_param_bounds_and_ty", 3) {
do self.emit_field(~"bounds", 0) {
do self.emit_from_vec(*tpbt.bounds) |bs| {
self.emit_bounds(ecx, *bs);
do self.emit_struct("ty_param_bounds_and_ty", 2) {
do self.emit_field(~"generics", 0) {
do self.emit_struct("Generics", 2) {
do self.emit_field(~"bounds", 0) {
do self.emit_from_vec(*tpbt.generics.bounds) |bs| {
self.emit_bounds(ecx, *bs);
}
}
do self.emit_field(~"region_param", 1) {
tpbt.generics.region_param.encode(self);
}
}
}
do self.emit_field(~"region_param", 1u) {
tpbt.region_param.encode(self);
}
do self.emit_field(~"ty", 2u) {
do self.emit_field(~"ty", 1) {
self.emit_ty(ecx, tpbt.ty);
}
}
@ -1045,15 +1050,19 @@ impl ebml_decoder_decoder_helpers for reader::Decoder {
fn read_ty_param_bounds_and_ty(&self, xcx: @ExtendedDecodeContext)
-> ty::ty_param_bounds_and_ty
{
do self.read_struct("ty_param_bounds_and_ty", 3) {
do self.read_struct("ty_param_bounds_and_ty", 2) {
ty::ty_param_bounds_and_ty {
bounds: self.read_field(~"bounds", 0u, || {
@self.read_to_vec(|| self.read_bounds(xcx) )
}),
region_param: self.read_field(~"region_param", 1u, || {
Decodable::decode(self)
}),
ty: self.read_field(~"ty", 2u, || {
generics: do self.read_struct("Generics", 2) {
ty::Generics {
bounds: self.read_field(~"bounds", 0, || {
@self.read_to_vec(|| self.read_bounds(xcx) )
}),
region_param: self.read_field(~"region_param", 1, || {
Decodable::decode(self)
})
}
},
ty: self.read_field(~"ty", 1, || {
self.read_ty(xcx)
})
}

View file

@ -91,7 +91,7 @@ fn check_struct_safe_for_destructor(cx: Context,
span: span,
struct_did: def_id) {
let struct_tpt = ty::lookup_item_type(cx.tcx, struct_did);
if struct_tpt.bounds.len() == 0 {
if struct_tpt.generics.bounds.len() == 0 {
let struct_ty = ty::mk_struct(cx.tcx, struct_did, ty::substs {
self_r: None,
self_ty: None,
@ -279,7 +279,7 @@ pub fn check_expr(e: @expr, cx: Context, v: visit::vt<Context>) {
let bounds = match e.node {
expr_path(_) => {
let did = ast_util::def_id_of_def(*cx.tcx.def_map.get(&e.id));
ty::lookup_item_type(cx.tcx, did).bounds
ty::lookup_item_type(cx.tcx, did).generics.bounds
}
_ => {
// Type substitutions should only occur on paths and
@ -340,7 +340,7 @@ fn check_ty(aty: @Ty, cx: Context, v: visit::vt<Context>) {
// FIXME(#5562): removing this copy causes a segfault before stage2
let ts = /*bad*/ copy **ts;
let did = ast_util::def_id_of_def(*cx.tcx.def_map.get(&id));
let bounds = ty::lookup_item_type(cx.tcx, did).bounds;
let bounds = ty::lookup_item_type(cx.tcx, did).generics.bounds;
for vec::each2(ts, *bounds) |ty, bound| {
check_bounds(cx, aty.id, aty.span, *ty, *bound)
}

View file

@ -825,8 +825,7 @@ fn check_item_heap(cx: ty::ctxt, it: @ast::item) {
ast::item_fn(*) |
ast::item_ty(*) |
ast::item_enum(*) |
ast::item_struct(*) |
ast::item_trait(*) => check_type(cx, it.id, it.id, it.span,
ast::item_struct(*) => check_type(cx, it.id, it.id, it.span,
ty::node_id_to_type(cx, it.id)),
_ => ()
}

View file

@ -462,7 +462,7 @@ pub impl mem_categorization_ctxt {
ast::def_fn(*) | ast::def_static_method(*) | ast::def_mod(_) |
ast::def_foreign_mod(_) | ast::def_const(_) |
ast::def_use(_) | ast::def_variant(*) |
ast::def_ty(_) | ast::def_prim_ty(_) |
ast::def_trait(_) | ast::def_ty(_) | ast::def_prim_ty(_) |
ast::def_ty_param(*) | ast::def_struct(*) |
ast::def_typaram_binder(*) | ast::def_region(_) |
ast::def_label(_) | ast::def_self_ty(*) => {

View file

@ -211,7 +211,7 @@ use core::prelude::*;
use middle::pat_util::{pat_bindings};
use middle::freevars;
use middle::ty;
use middle::typeck::method_map;
use middle::typeck::{method_map};
use util::ppaux;
use util::common::indenter;
@ -463,7 +463,7 @@ pub impl VisitContext {
expr_method_call(callee, _, _, ref args, _) => { // callee.m(args)
// Implicit self is equivalent to & mode, but every
// other kind should be + mode.
self.use_receiver(expr.id, expr.span, callee, visitor);
self.use_receiver(callee, visitor);
self.use_fn_args(expr.callee_id, *args, visitor);
}
@ -665,7 +665,7 @@ pub impl VisitContext {
return false;
}
self.use_receiver(expr.id, expr.span, receiver_expr, visitor);
self.use_receiver(receiver_expr, visitor);
// for overloaded operatrs, we are always passing in a
// borrowed pointer, so it's always read mode:
@ -718,8 +718,6 @@ pub impl VisitContext {
}
fn use_receiver(&self,
_expr_id: node_id,
_span: span,
receiver_expr: @expr,
visitor: vt<VisitContext>)
{

View file

@ -690,7 +690,9 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
match ty.node {
ast::ty_path(path, id) => {
match cx.def_map.find(&id) {
Some(&ast::def_ty(did)) | Some(&ast::def_struct(did)) => {
Some(&ast::def_ty(did)) |
Some(&ast::def_trait(did)) |
Some(&ast::def_struct(did)) => {
if did.crate == ast::local_crate {
if cx.region_is_relevant(path.rp) {
cx.add_dep(did.node);

View file

@ -12,7 +12,8 @@ use core::prelude::*;
use driver::session;
use driver::session::Session;
use metadata::csearch::{each_path, get_method_names_if_trait};
use metadata::csearch::{each_path, get_trait_method_def_ids};
use metadata::csearch::get_method_name_and_self_ty;
use metadata::csearch::get_static_methods_if_impl;
use metadata::csearch::get_type_name_if_impl;
use metadata::cstore::find_extern_mod_stmt_cnum;
@ -31,7 +32,7 @@ use syntax::ast::{crate, decl_item, def, def_arg, def_binding};
use syntax::ast::{def_const, def_foreign_mod, def_fn, def_id, def_label};
use syntax::ast::{def_local, def_mod, def_prim_ty, def_region, def_self};
use syntax::ast::{def_self_ty, def_static_method, def_struct, def_ty};
use syntax::ast::{def_ty_param, def_typaram_binder};
use syntax::ast::{def_ty_param, def_typaram_binder, def_trait};
use syntax::ast::{def_upvar, def_use, def_variant, expr, expr_assign_op};
use syntax::ast::{expr_binary, expr_break, expr_field};
use syntax::ast::{expr_fn_block, expr_index, expr_method_call, expr_path};
@ -78,6 +79,7 @@ use syntax::opt_vec::OptVec;
use core::option::Some;
use core::str::each_split_str;
use core::hashmap::{HashMap, HashSet};
use core::util;
// Definition mapping
pub type DefMap = @mut HashMap<node_id,def>;
@ -1341,7 +1343,7 @@ pub impl Resolver {
let def_id = local_def(item.id);
self.trait_info.insert(def_id, method_names);
name_bindings.define_type(privacy, def_ty(def_id), sp);
name_bindings.define_type(privacy, def_trait(def_id), sp);
visit_item(item, new_parent, visitor);
}
@ -1611,36 +1613,40 @@ pub impl Resolver {
crate) building value %s", final_ident);
child_name_bindings.define_value(Public, def, dummy_sp());
}
def_ty(def_id) => {
debug!("(building reduced graph for external \
crate) building type %s", final_ident);
def_trait(def_id) => {
debug!("(building reduced graph for external \
crate) building type %s", final_ident);
// If this is a trait, add all the method names
// to the trait info.
// If this is a trait, add all the method names
// to the trait info.
match get_method_names_if_trait(self.session.cstore, def_id) {
None => {
// Nothing to do.
let method_def_ids = get_trait_method_def_ids(self.session.cstore,
def_id);
let mut interned_method_names = HashSet::new();
for method_def_ids.each |&method_def_id| {
let (method_name, self_ty) =
get_method_name_and_self_ty(self.session.cstore,
method_def_id);
debug!("(building reduced graph for \
external crate) ... adding \
trait method '%s'",
*self.session.str_of(method_name));
// Add it to the trait info if not static.
if self_ty != sty_static {
interned_method_names.insert(method_name);
}
}
Some(method_names) => {
let mut interned_method_names = HashSet::new();
for method_names.each |method_data| {
let (method_name, self_ty) = *method_data;
debug!("(building reduced graph for \
external crate) ... adding \
trait method '%s'",
*self.session.str_of(method_name));
self.trait_info.insert(def_id, interned_method_names);
// Add it to the trait info if not static.
if self_ty != sty_static {
interned_method_names.insert(method_name);
}
}
self.trait_info.insert(def_id, interned_method_names);
}
}
child_name_bindings.define_type(Public, def, dummy_sp());
}
def_ty(_) => {
debug!("(building reduced graph for external \
crate) building type %s", final_ident);
child_name_bindings.define_type(Public, def, dummy_sp());
child_name_bindings.define_type(Public, def, dummy_sp());
}
def_struct(def_id) => {
debug!("(building reduced graph for external \
@ -3409,7 +3415,6 @@ pub impl Resolver {
self_type,
ref methods) => {
self.resolve_implementation(item.id,
item.span,
generics,
implemented_traits,
self_type,
@ -3718,13 +3723,30 @@ pub impl Resolver {
for type_parameters.each |type_parameter| {
for type_parameter.bounds.each |&bound| {
match bound {
TraitTyParamBound(ty) => self.resolve_type(ty, visitor),
TraitTyParamBound(tref) => {
self.resolve_trait_reference(tref, visitor)
}
RegionTyParamBound => {}
}
}
}
}
fn resolve_trait_reference(@mut self,
trait_reference: &trait_ref,
visitor: ResolveVisitor) {
match self.resolve_path(trait_reference.path, TypeNS, true, visitor) {
None => {
self.session.span_err(trait_reference.path.span,
~"attempt to implement an \
unknown trait");
}
Some(def) => {
self.record_def(trait_reference.ref_id, def);
}
}
}
fn resolve_struct(@mut self,
id: node_id,
generics: &Generics,
@ -3792,7 +3814,6 @@ pub impl Resolver {
fn resolve_implementation(@mut self,
id: node_id,
span: span,
generics: &Generics,
opt_trait_reference: Option<@trait_ref>,
self_type: @Ty,
@ -3811,25 +3832,16 @@ pub impl Resolver {
let original_trait_refs;
match opt_trait_reference {
Some(trait_reference) => {
let mut new_trait_refs = ~[];
match self.resolve_path(
trait_reference.path, TypeNS, true, visitor) {
None => {
self.session.span_err(span,
~"attempt to implement an \
unknown trait");
}
Some(def) => {
self.record_def(trait_reference.ref_id, def);
self.resolve_trait_reference(trait_reference, visitor);
// Record the current trait reference.
new_trait_refs.push(def_id_of_def(def));
}
}
// Record the current set of trait references.
let mut old = Some(new_trait_refs);
self.current_trait_refs <-> old;
original_trait_refs = Some(old);
let mut new_trait_refs = ~[];
for self.def_map.find(&trait_reference.ref_id).each |&def| {
new_trait_refs.push(def_id_of_def(*def));
}
original_trait_refs = Some(util::replace(
&mut self.current_trait_refs,
Some(new_trait_refs)));
}
None => {
original_trait_refs = None;
@ -4952,7 +4964,7 @@ pub impl Resolver {
match child_name_bindings.def_for_namespace(TypeNS) {
Some(def) => {
match def {
def_ty(trait_def_id) => {
def_trait(trait_def_id) => {
self.add_trait_info_if_containing_method(
&mut found_traits, trait_def_id, name);
}
@ -4979,7 +4991,7 @@ pub impl Resolver {
match target.bindings.def_for_namespace(TypeNS) {
Some(def) => {
match def {
def_ty(trait_def_id) => {
def_trait(trait_def_id) => {
let added = self.
add_trait_info_if_containing_method(
&mut found_traits,

View file

@ -148,7 +148,7 @@ pub fn trans(bcx: block, expr: @ast::expr) -> Callee {
ast::def_self(*) => {
datum_callee(bcx, ref_expr)
}
ast::def_mod(*) | ast::def_foreign_mod(*) |
ast::def_mod(*) | ast::def_foreign_mod(*) | ast::def_trait(*) |
ast::def_const(*) | ast::def_ty(*) | ast::def_prim_ty(*) |
ast::def_use(*) | ast::def_typaram_binder(*) |
ast::def_region(*) | ast::def_label(*) | ast::def_ty_param(*) |
@ -238,8 +238,7 @@ pub fn trans_fn_ref_with_vtables(
// Modify the def_id if this is a default method; we want to be
// monomorphizing the trait's code.
let (def_id, opt_impl_did) =
match tcx.provided_method_sources.find(&def_id) {
let (def_id, opt_impl_did) = match tcx.provided_method_sources.find(&def_id) {
None => (def_id, None),
Some(source) => (source.method_id, Some(source.impl_id))
};

View file

@ -1062,9 +1062,6 @@ pub fn T_opaque_trait(cx: @CrateContext, store: ty::TraitStore) -> TypeRef {
ty::RegionTraitStore(_) => {
T_struct(~[T_ptr(cx.tydesc_type), T_ptr(T_i8())])
}
ty::BareTraitStore => {
cx.sess.bug(~"can't make T_opaque_trait with bare trait store")
}
}
}

View file

@ -1714,7 +1714,6 @@ fn trans_assign_op(bcx: block,
return result_datum.copy_to_datum(bcx, DROP_EXISTING, dst_datum);
}
// NOTE: Mode neccessary here?
fn shorten(+x: ~str) -> ~str {
if x.len() > 60 { x.substr(0, 60).to_owned() } else { x }
}

View file

@ -40,7 +40,6 @@ use core::libc::c_uint;
use core::str;
use std::time;
use syntax::ast;
use syntax::parse::token::special_idents;
pub fn trans_free(cx: block, v: ValueRef) -> block {
let _icx = cx.insn_ctxt("trans_free");
@ -400,11 +399,9 @@ pub fn call_tydesc_glue(++cx: block, v: ValueRef, t: ty::t, field: uint)
pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) {
let _icx = bcx.insn_ctxt("make_visit_glue");
let mut bcx = bcx;
let ty_visitor_name = special_idents::ty_visitor;
assert!(bcx.ccx().tcx.intrinsic_defs.contains_key(&ty_visitor_name));
let (trait_id, ty) = *bcx.ccx().tcx.intrinsic_defs.get(&ty_visitor_name);
let v = PointerCast(bcx, v, T_ptr(type_of::type_of(bcx.ccx(), ty)));
bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, trait_id);
let (visitor_trait, object_ty) = ty::visitor_object_ty(bcx.tcx());
let v = PointerCast(bcx, v, T_ptr(type_of::type_of(bcx.ccx(), object_ty)));
bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, visitor_trait.def_id);
build_return(bcx);
}
@ -554,8 +551,7 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
ty::ty_closure(_) => {
closure::make_closure_glue(bcx, v0, t, drop_ty)
}
ty::ty_trait(_, _, ty::BoxTraitStore) |
ty::ty_trait(_, _, ty::BareTraitStore) => {
ty::ty_trait(_, _, ty::BoxTraitStore) => {
let llbox = Load(bcx, GEPi(bcx, v0, [0u, 1u]));
decr_refcnt_maybe_free(bcx, llbox, ty::mk_opaque_box(ccx.tcx))
}
@ -621,8 +617,7 @@ pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) {
ty::ty_closure(_) => {
closure::make_closure_glue(bcx, v, t, take_ty)
}
ty::ty_trait(_, _, ty::BoxTraitStore) |
ty::ty_trait(_, _, ty::BareTraitStore) => {
ty::ty_trait(_, _, ty::BoxTraitStore) => {
let llbox = Load(bcx, GEPi(bcx, v, [0u, 1u]));
incr_refcnt_of_boxed(bcx, llbox);
bcx

View file

@ -87,8 +87,7 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::def_id,
ccx.stats.n_inlines += 1;
ccx.external.insert(fn_id, Some(mth.id));
let ty::ty_param_bounds_and_ty {
bounds: impl_bnds,
region_param: _,
generics: ty::Generics { bounds: impl_bnds, _ },
ty: _
} = ty::lookup_item_type(ccx.tcx, impl_did);
if translate &&

View file

@ -11,7 +11,6 @@
use core::prelude::*;
use back::abi;
use driver;
use lib::llvm::llvm;
use lib::llvm::ValueRef;
use lib;
@ -174,6 +173,7 @@ pub fn trans_method_callee(bcx: block,
mentry: typeck::method_map_entry)
-> Callee {
let _icx = bcx.insn_ctxt("impl::trans_method_callee");
let tcx = bcx.tcx();
debug!("trans_method_callee(callee_id=%?, self=%s, mentry=%?)",
callee_id, bcx.expr_to_str(self), mentry);
@ -189,33 +189,33 @@ pub fn trans_method_callee(bcx: block,
// Get the ID of the method we're calling.
let method_name =
ty::trait_methods(bcx.tcx(), trait_id)[method_index].ident;
let method_id = method_with_name(bcx.ccx(), impl_def_id,
method_name);
ty::trait_method(tcx, trait_id, method_index).ident;
let method_id =
method_with_name(bcx.ccx(), impl_def_id, method_name);
origin = typeck::method_static(method_id);
}
typeck::method_super(trait_id, method_index) => {
// <self_ty> is the self type for this method call
let self_ty = node_id_type(bcx, self.id);
let tcx = bcx.tcx();
// <impl_id> is the ID of the implementation of
// trait <trait_id> for type <self_ty>
let impl_id = ty::get_impl_id(tcx, trait_id, self_ty);
// Get the supertrait's methods
let supertrait_methods = ty::trait_methods(tcx, trait_id);
let supertrait_method_def_ids = ty::trait_method_def_ids(tcx, trait_id);
// Make sure to fail with a readable error message if
// there's some internal error here
if !(method_index < supertrait_methods.len()) {
if !(method_index < supertrait_method_def_ids.len()) {
tcx.sess.bug(~"trans_method_callee: supertrait method \
index is out of bounds");
}
// Get the method name using the method index in the origin
let method_name = supertrait_methods[method_index].ident;
let method_name =
ty::method(tcx, supertrait_method_def_ids[method_index]).ident;
// Now that we know the impl ID, we can look up the method
// ID from its name
origin = typeck::method_static(method_with_name(bcx.ccx(),
impl_id,
method_name));
impl_id,
method_name));
}
typeck::method_static(*) | typeck::method_param(*) |
typeck::method_trait(*) => {}
@ -301,8 +301,8 @@ pub fn trans_static_method_callee(bcx: block,
// found on the type parametesr T1...Tn to find the index of the
// one we are interested in.
let bound_index = {
let trait_polyty = ty::lookup_item_type(bcx.tcx(), trait_id);
ty::count_traits_and_supertraits(bcx.tcx(), *trait_polyty.bounds)
let trait_def = ty::lookup_trait_def(bcx.tcx(), trait_id);
ty::count_traits_and_supertraits(bcx.tcx(), *trait_def.generics.bounds)
};
let mname = if method_id.crate == ast::local_crate {
@ -375,7 +375,8 @@ pub fn method_with_name(ccx: @CrateContext, impl_id: ast::def_id,
}
}
pub fn method_with_name_or_default(ccx: @CrateContext, impl_id: ast::def_id,
pub fn method_with_name_or_default(ccx: @CrateContext,
impl_id: ast::def_id,
name: ast::ident) -> ast::def_id {
if impl_id.crate == ast::local_crate {
match *ccx.tcx.items.get(&impl_id.node) {
@ -448,7 +449,7 @@ pub fn trans_monomorphized_callee(bcx: block,
return match vtbl {
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
let ccx = bcx.ccx();
let mname = ty::trait_methods(ccx.tcx, trait_id)[n_method].ident;
let mname = ty::trait_method(ccx.tcx, trait_id, n_method).ident;
let mth_id = method_with_name_or_default(
bcx.ccx(), impl_did, mname);
@ -550,8 +551,10 @@ pub fn combine_impl_and_methods_origins(bcx: block,
// rcvr + method bounds.
let ccx = bcx.ccx(), tcx = bcx.tcx();
let n_m_tps = method_ty_param_count(ccx, mth_did, impl_did);
let ty::ty_param_bounds_and_ty {bounds: r_m_bounds, _}
= ty::lookup_item_type(tcx, mth_did);
let ty::ty_param_bounds_and_ty {
generics: ty::Generics {bounds: r_m_bounds, _},
_
} = ty::lookup_item_type(tcx, mth_did);
let n_r_m_tps = r_m_bounds.len(); // rcvr + method tps
let m_boundss = vec::slice(*r_m_bounds, n_r_m_tps - n_m_tps, n_r_m_tps);
@ -654,7 +657,6 @@ pub fn trans_trait_callee_from_llval(bcx: block,
// payload.
match store {
ty::BoxTraitStore |
ty::BareTraitStore |
ty::UniqTraitStore => {
llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
}
@ -677,7 +679,7 @@ pub fn trans_trait_callee_from_llval(bcx: block,
// Pass a pointer to the box.
match store {
ty::BoxTraitStore | ty::BareTraitStore => llself = llbox,
ty::BoxTraitStore => llself = llbox,
_ => bcx.tcx().sess.bug(~"@self receiver with non-@Trait")
}
@ -783,18 +785,14 @@ pub fn make_impl_vtable(ccx: @CrateContext,
let tcx = ccx.tcx;
// XXX: This should support multiple traits.
let trt_id = driver::session::expect(
tcx.sess,
ty::ty_to_def_id(ty::impl_traits(tcx,
impl_id,
ty::BoxTraitStore)[0]),
|| ~"make_impl_vtable: non-trait-type implemented");
let trt_id = ty::impl_trait_refs(tcx, impl_id)[0].def_id;
let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u;
make_vtable(ccx, vec::map(*ty::trait_methods(tcx, trt_id), |im| {
let has_tps = ty::lookup_item_type(ccx.tcx, impl_id).generics.bounds.len() > 0u;
make_vtable(ccx, ty::trait_method_def_ids(tcx, trt_id).map(|method_def_id| {
let im = ty::method(tcx, *method_def_id);
let fty = ty::subst_tps(tcx, substs, None,
ty::mk_bare_fn(tcx, copy im.fty));
if (*im.tps).len() > 0u || ty::type_has_self(fty) {
if im.generics.bounds.len() > 0u || ty::type_has_self(fty) {
debug!("(making impl vtable) method has self or type params: %s",
*tcx.sess.str_of(im.ident));
C_null(T_ptr(T_nil()))
@ -841,7 +839,7 @@ pub fn trans_trait_cast(bcx: block,
let v_ty = expr_ty(bcx, val);
match store {
ty::RegionTraitStore(_) | ty::BoxTraitStore | ty::BareTraitStore => {
ty::RegionTraitStore(_) | ty::BoxTraitStore => {
let mut llboxdest = GEPi(bcx, lldest, [0u, 1u]);
// Just store the pointer into the pair.
llboxdest = PointerCast(bcx,

View file

@ -169,7 +169,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
let psubsts = Some(@param_substs {
tys: substs,
vtables: vtables,
bounds: tpt.bounds,
bounds: tpt.generics.bounds,
self_ty: impl_ty_opt
});
@ -291,7 +291,7 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt,
ty::ty_trait(_, _, ref store) => {
let sigil = match *store {
ty::UniqTraitStore => ast::OwnedSigil,
ty::BoxTraitStore | ty::BareTraitStore => ast::ManagedSigil,
ty::BoxTraitStore => ast::ManagedSigil,
ty::RegionTraitStore(_) => ast::BorrowedSigil,
};
@ -328,7 +328,7 @@ pub fn make_mono_id(ccx: @CrateContext, item: ast::def_id, substs: &[ty::t],
+param_uses: Option<~[type_use::type_uses]>) -> mono_id {
let precise_param_ids = match vtables {
Some(vts) => {
let bounds = ty::lookup_item_type(ccx.tcx, item).bounds;
let bounds = ty::lookup_item_type(ccx.tcx, item).generics.bounds;
let mut i = 0;
vec::map2(*bounds, substs, |bounds, subst| {
let mut v = ~[];

View file

@ -31,7 +31,7 @@ use syntax::ast;
pub struct Reflector {
visitor_val: ValueRef,
visitor_methods: @~[ty::method],
visitor_methods: @~[@ty::method],
final_bcx: block,
tydesc_ty: TypeRef,
bcx: block

View file

@ -25,8 +25,10 @@ use middle;
use util::ppaux::{note_and_explain_region, bound_region_to_str};
use util::ppaux::{region_to_str, vstore_to_str};
use util::ppaux::{trait_store_to_str, ty_to_str, tys_to_str};
use util::ppaux::{trait_ref_to_str};
use util::common::{indenter};
use core;
use core::cast;
use core::cmp;
use core::ops;
@ -44,6 +46,7 @@ use syntax::ast_util;
use syntax::codemap::span;
use syntax::codemap;
use syntax::print::pprust;
use syntax::parse::token::special_idents;
use syntax::{ast, ast_map};
use syntax::opt_vec::OptVec;
use syntax::opt_vec;
@ -70,7 +73,8 @@ pub type param_bounds = @~[param_bound];
pub struct method {
ident: ast::ident,
tps: @~[param_bounds],
generics: ty::Generics,
transformed_self_ty: Option<ty::t>,
fty: BareFnTy,
self_ty: ast::self_ty_,
vis: ast::visibility,
@ -95,9 +99,8 @@ pub enum vstore {
#[auto_encode]
#[auto_decode]
#[deriving(Eq)]
#[deriving(Eq, IterBytes)]
pub enum TraitStore {
BareTraitStore, // a plain trait without a sigil
BoxTraitStore, // @Trait
UniqTraitStore, // ~Trait
RegionTraitStore(Region), // &Trait
@ -224,11 +227,6 @@ pub struct ProvidedMethodSource {
impl_id: ast::def_id
}
pub struct InstantiatedTraitRef {
def_id: ast::def_id,
tpt: ty_param_substs_and_ty
}
pub type ctxt = @ctxt_;
struct ctxt_ {
@ -255,8 +253,21 @@ struct ctxt_ {
// other items.
node_type_substs: @mut HashMap<node_id, ~[t]>,
// Maps from a method to the method "descriptor"
methods: @mut HashMap<def_id, @method>,
// Maps from a trait def-id to a list of the def-ids of its methods
trait_method_def_ids: @mut HashMap<def_id, @~[def_id]>,
// A cache for the trait_methods() routine
trait_methods_cache: @mut HashMap<def_id, @~[@method]>,
trait_refs: @mut HashMap<node_id, @TraitRef>,
trait_defs: @mut HashMap<def_id, @TraitDef>,
items: ast_map::map,
intrinsic_defs: @mut HashMap<ast::ident, (ast::def_id, t)>,
intrinsic_traits: @mut HashMap<ast::ident, @TraitRef>,
freevars: freevars::freevar_map,
tcache: type_cache,
rcache: creader_cache,
@ -266,7 +277,6 @@ struct ctxt_ {
tc_cache: @mut HashMap<uint, TypeContents>,
ast_ty_to_ty_cache: @mut HashMap<node_id, ast_ty_to_ty_cache_entry>,
enum_var_cache: @mut HashMap<def_id, @~[VariantInfo]>,
trait_method_cache: @mut HashMap<def_id, @~[method]>,
ty_param_bounds: @mut HashMap<ast::node_id, param_bounds>,
inferred_modes: @mut HashMap<ast::node_id, ast::mode>,
adjustments: @mut HashMap<ast::node_id, @AutoAdjustment>,
@ -277,7 +287,7 @@ struct ctxt_ {
// that implementation implements.
provided_methods: ProvidedMethodsMap,
provided_method_sources: @mut HashMap<ast::def_id, ProvidedMethodSource>,
supertraits: @mut HashMap<ast::def_id, @~[InstantiatedTraitRef]>,
supertraits: @mut HashMap<ast::def_id, @~[@TraitRef]>,
// A mapping from the def ID of an enum or struct type to the def ID
// of the method that implements its destructor. If the type is not
@ -527,6 +537,12 @@ pub enum sty {
ty_unboxed_vec(mt),
}
#[deriving(Eq, IterBytes)]
pub struct TraitRef {
def_id: def_id,
substs: substs
}
#[deriving(Eq)]
pub enum IntVarValue {
IntType(ast::int_ty),
@ -573,16 +589,17 @@ pub enum type_err {
terr_self_substs,
terr_integer_as_char,
terr_int_mismatch(expected_found<IntVarValue>),
terr_float_mismatch(expected_found<ast::float_ty>)
terr_float_mismatch(expected_found<ast::float_ty>),
terr_traits(expected_found<ast::def_id>),
}
#[deriving(Eq)]
#[deriving(Eq, IterBytes)]
pub enum param_bound {
bound_copy,
bound_durable,
bound_owned,
bound_const,
bound_trait(t),
bound_trait(@TraitRef),
}
#[deriving(Eq)]
@ -651,19 +668,6 @@ impl cmp::Eq for InferRegion {
}
}
impl to_bytes::IterBytes for param_bound {
fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
match *self {
bound_copy => 0u8.iter_bytes(lsb0, f),
bound_durable => 1u8.iter_bytes(lsb0, f),
bound_owned => 2u8.iter_bytes(lsb0, f),
bound_const => 3u8.iter_bytes(lsb0, f),
bound_trait(ref t) =>
to_bytes::iter_bytes_2(&4u8, t, lsb0, f)
}
}
}
pub trait Vid {
fn to_uint(&self) -> uint;
}
@ -750,6 +754,13 @@ impl to_bytes::IterBytes for RegionVid {
}
}
/// Information about the type/lifetime parametesr associated with an item.
/// Analogous to ast::Generics.
pub struct Generics {
bounds: @~[param_bounds],
region_param: Option<region_variance>,
}
/// A polytype.
///
/// - `bounds`: The list of bounds for each type parameter. The length of the
@ -761,11 +772,16 @@ impl to_bytes::IterBytes for RegionVid {
/// - `ty`: the base type. May have reference to the (unsubstituted) bound
/// region `&self` or to (unsubstituted) ty_param types
pub struct ty_param_bounds_and_ty {
bounds: @~[param_bounds],
region_param: Option<region_variance>,
generics: Generics,
ty: t
}
/// As `ty_param_bounds_and_ty` but for a trait ref.
pub struct TraitDef {
generics: Generics,
trait_ref: @ty::TraitRef,
}
pub struct ty_param_substs_and_ty {
substs: ty::substs,
ty: ty::t
@ -820,6 +836,9 @@ pub fn mk_ctxt(s: session::Session,
region_paramd_items: region_paramd_items,
node_types: @mut SmallIntMap::new(),
node_type_substs: @mut HashMap::new(),
trait_refs: @mut HashMap::new(),
trait_defs: @mut HashMap::new(),
intrinsic_traits: @mut HashMap::new(),
items: amap,
intrinsic_defs: @mut HashMap::new(),
freevars: freevars,
@ -831,7 +850,9 @@ pub fn mk_ctxt(s: session::Session,
tc_cache: @mut HashMap::new(),
ast_ty_to_ty_cache: @mut HashMap::new(),
enum_var_cache: @mut HashMap::new(),
trait_method_cache: @mut HashMap::new(),
methods: @mut HashMap::new(),
trait_method_def_ids: @mut HashMap::new(),
trait_methods_cache: @mut HashMap::new(),
ty_param_bounds: @mut HashMap::new(),
inferred_modes: @mut HashMap::new(),
adjustments: @mut HashMap::new(),
@ -1401,7 +1422,7 @@ pub fn param_bound_to_str(cx: ctxt, pb: &param_bound) -> ~str {
bound_durable => ~"'static",
bound_owned => ~"owned",
bound_const => ~"const",
bound_trait(t) => ::util::ppaux::ty_to_str(cx, t)
bound_trait(t) => ::util::ppaux::trait_ref_to_str(cx, t)
}
}
@ -1455,13 +1476,26 @@ pub fn subst(cx: ctxt,
}
}
pub fn subst_in_trait_ref(cx: ctxt,
substs: &substs,
trait_ref: &ty::TraitRef) -> ty::TraitRef
{
ty::TraitRef {
def_id: trait_ref.def_id,
substs: subst_in_substs(cx, substs, &trait_ref.substs)
}
}
// Performs substitutions on a set of substitutions (result = sup(sub)) to
// yield a new set of substitutions. This is used in trait inheritance.
pub fn subst_substs(cx: ctxt, sup: &substs, sub: &substs) -> substs {
pub fn subst_in_substs(cx: ctxt,
substs: &substs,
in_substs: &substs) -> substs
{
substs {
self_r: sup.self_r,
self_ty: sup.self_ty.map(|typ| subst(cx, sub, *typ)),
tps: sup.tps.map(|typ| subst(cx, sub, *typ))
self_r: in_substs.self_r,
self_ty: in_substs.self_ty.map(|&typ| subst(cx, substs, typ)),
tps: in_substs.tps.map(|&typ| subst(cx, substs, typ))
}
}
@ -1477,6 +1511,11 @@ pub fn type_is_error(ty: t) -> bool {
(get(ty).flags & (has_ty_err as uint)) != 0
}
pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
tref.substs.self_ty.any(|&t| type_is_error(t)) ||
tref.substs.tps.any(|&t| type_is_error(t))
}
pub fn type_is_ty_var(ty: t) -> bool {
match get(ty).sty {
ty_infer(TyVar(_)) => true,
@ -1921,8 +1960,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
TC_OWNED_CLOSURE
}
ty_trait(_, _, BoxTraitStore) |
ty_trait(_, _, BareTraitStore) => {
ty_trait(_, _, BoxTraitStore) => {
TC_MANAGED
}
@ -2581,17 +2619,6 @@ impl to_bytes::IterBytes for vstore {
}
}
impl to_bytes::IterBytes for TraitStore {
fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
match *self {
BareTraitStore => 0u8.iter_bytes(lsb0, f),
UniqTraitStore => 1u8.iter_bytes(lsb0, f),
BoxTraitStore => 2u8.iter_bytes(lsb0, f),
RegionTraitStore(ref r) => to_bytes::iter_bytes_2(&3u8, r, lsb0, f),
}
}
}
impl to_bytes::IterBytes for substs {
fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_3(&self.self_r,
@ -2704,6 +2731,16 @@ impl to_bytes::IterBytes for sty {
}
}
pub fn node_id_to_trait_ref(cx: ctxt, id: ast::node_id) -> @ty::TraitRef {
match cx.trait_refs.find(&id) {
Some(&t) => t,
None => cx.sess.bug(
fmt!("node_id_to_trait_ref: no trait ref for node `%s`",
ast_map::node_id_to_str(cx.items, id,
cx.sess.parse_sess.interner)))
}
}
pub fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t {
//io::println(fmt!("%?/%?", id, cx.node_types.len()));
match cx.node_types.find(&(id as uint)) {
@ -2726,6 +2763,16 @@ fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool {
cx.node_type_substs.contains_key(&id)
}
pub fn ty_fn_sig(fty: t) -> FnSig {
match get(fty).sty {
ty_bare_fn(ref f) => copy f.sig,
ty_closure(ref f) => copy f.sig,
ref s => {
fail!(fmt!("ty_fn_sig() called on non-fn type: %?", s))
}
}
}
// Type accessors for substructures of types
pub fn ty_fn_args(fty: t) -> ~[arg] {
match get(fty).sty {
@ -3004,7 +3051,7 @@ pub fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map,
// n.b.: When we encode impl methods, the bounds
// that we encode include both the impl bounds
// and then the method bounds themselves...
ty::lookup_item_type(tcx, did).bounds
ty::lookup_item_type(tcx, did).generics.bounds
}
typeck::method_param(typeck::method_param {
trait_id: trt_id,
@ -3015,10 +3062,9 @@ pub fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map,
// ...trait methods bounds, in contrast, include only the
// method bounds, so we must preprend the tps from the
// trait itself. This ought to be harmonized.
let trt_bounds =
ty::lookup_item_type(tcx, trt_id).bounds;
let trt_bounds = ty::lookup_trait_def(tcx, trt_id).generics.bounds;
@(vec::append(/*bad*/copy *trt_bounds,
*ty::trait_methods(tcx, trt_id)[n_mth].tps))
*ty::trait_method(tcx, trt_id, n_mth).generics.bounds))
}
}
}
@ -3203,10 +3249,8 @@ pub fn field_idx_strict(tcx: ty::ctxt, id: ast::ident, fields: &[field])
fields.map(|f| tcx.sess.str_of(f.ident))));
}
pub fn method_idx(id: ast::ident, meths: &[method]) -> Option<uint> {
let mut i = 0u;
for meths.each |m| { if m.ident == id { return Some(i); } i += 1u; }
return None;
pub fn method_idx(id: ast::ident, meths: &[@method]) -> Option<uint> {
vec::position(meths, |m| m.ident == id)
}
/// Returns a vector containing the indices of all type parameters that appear
@ -3469,6 +3513,11 @@ pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
ty_sort_str(cx, values.expected),
ty_sort_str(cx, values.found))
}
terr_traits(values) => {
fmt!("expected trait %s but found trait %s",
item_path_str(cx, values.expected),
item_path_str(cx, values.found))
}
terr_self_substs => {
~"inconsistent self substitution" // XXX this is more of a bug
}
@ -3527,10 +3576,6 @@ pub fn def_has_ty_params(def: ast::def) -> bool {
}
}
pub fn store_trait_methods(cx: ctxt, id: ast::node_id, ms: @~[method]) {
cx.trait_method_cache.insert(ast_util::local_def(id), ms);
}
pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
if is_local(id) {
match cx.items.find(&id.node) {
@ -3550,11 +3595,11 @@ pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
}
pub fn trait_supertraits(cx: ctxt,
id: ast::def_id)
-> @~[InstantiatedTraitRef] {
id: ast::def_id) -> @~[@TraitRef]
{
// Check the cache.
match cx.supertraits.find(&id) {
Some(&instantiated_trait_info) => { return instantiated_trait_info; }
Some(&trait_refs) => { return trait_refs; }
None => {} // Continue.
}
@ -3563,63 +3608,73 @@ pub fn trait_supertraits(cx: ctxt,
assert!(!is_local(id));
// Get the supertraits out of the metadata and create the
// InstantiatedTraitRef for each.
let mut result = ~[];
for csearch::get_supertraits(cx, id).each |trait_type| {
match get(*trait_type).sty {
ty_trait(def_id, ref substs, _) => {
result.push(InstantiatedTraitRef {
def_id: def_id,
tpt: ty_param_substs_and_ty {
substs: (/*bad*/copy *substs),
ty: *trait_type
}
});
}
_ => cx.sess.bug(~"trait_supertraits: trait ref wasn't a trait")
}
}
// Unwrap and return the result.
return @result;
// TraitRef for each.
let result = @csearch::get_supertraits(cx, id);
cx.supertraits.insert(id, result);
return result;
}
pub fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
match cx.trait_method_cache.find(&id) {
// Local traits are supposed to have been added explicitly.
Some(&ms) => ms,
_ => {
// If the lookup in trait_method_cache fails, assume that the trait
// method we're trying to look up is in a different crate, and look
// for it there.
assert!(id.crate != ast::local_crate);
let result = csearch::get_trait_methods(cx, id);
fn lookup_locally_or_in_crate_store<V:Copy>(
descr: &str,
def_id: ast::def_id,
map: &mut HashMap<ast::def_id, V>,
load_external: &fn() -> V) -> V
{
/*!
*
* Helper for looking things up in the various maps
* that are populated during typeck::collect (e.g.,
* `cx.methods`, `cx.tcache`, etc). All of these share
* the pattern that if the id is local, it should have
* been loaded into the map by the `typeck::collect` phase.
* If the def-id is external, then we have to go consult
* the crate loading code (and cache the result for the future).
*/
// Store the trait method in the local trait_method_cache so that
// future lookups succeed.
cx.trait_method_cache.insert(id, result);
result
}
match map.find(&def_id) {
Some(&v) => { return v; }
None => { }
}
if def_id.crate == ast::local_crate {
fail!(fmt!("No def'n found for %? in tcx.%s",
def_id, descr));
}
let v = load_external();
map.insert(def_id, v);
return v;
}
pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @method {
let method_def_id = ty::trait_method_def_ids(cx, trait_did)[idx];
ty::method(cx, method_def_id)
}
pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@method] {
match cx.trait_methods_cache.find(&trait_did) {
Some(&methods) => methods,
None => {
let def_ids = ty::trait_method_def_ids(cx, trait_did);
let methods = @def_ids.map(|d| ty::method(cx, *d));
cx.trait_methods_cache.insert(trait_did, methods);
methods
}
}
}
/*
Could this return a list of (def_id, substs) pairs?
*/
pub fn impl_traits(cx: ctxt, id: ast::def_id, store: TraitStore) -> ~[t] {
fn storeify(cx: ctxt, ty: t, store: TraitStore) -> t {
match ty::get(ty).sty {
ty::ty_trait(did, ref substs, trait_store) => {
if store == trait_store {
ty
} else {
mk_trait(cx, did, (/*bad*/copy *substs), store)
}
}
_ => cx.sess.bug(~"impl_traits: not a trait")
}
}
pub fn method(cx: ctxt, id: ast::def_id) -> @method {
lookup_locally_or_in_crate_store(
"methods", id, cx.methods,
|| @csearch::get_method(cx, id))
}
pub fn trait_method_def_ids(cx: ctxt, id: ast::def_id) -> @~[def_id] {
lookup_locally_or_in_crate_store(
"methods", id, cx.trait_method_def_ids,
|| @csearch::get_trait_method_def_ids(cx.cstore, id))
}
pub fn impl_trait_refs(cx: ctxt, id: ast::def_id) -> ~[@TraitRef] {
if id.crate == ast::local_crate {
debug!("(impl_traits) searching for trait impl %?", id);
match cx.items.find(&id.node) {
@ -3627,17 +3682,15 @@ pub fn impl_traits(cx: ctxt, id: ast::def_id, store: TraitStore) -> ~[t] {
node: ast::item_impl(_, opt_trait, _, _),
_},
_)) => {
do opt_trait.map_default(~[]) |trait_ref| {
~[storeify(cx, node_id_to_type(cx, trait_ref.ref_id),
store)]
match opt_trait {
Some(t) => ~[ty::node_id_to_trait_ref(cx, t.ref_id)],
None => ~[]
}
}
_ => ~[]
}
} else {
vec::map(csearch::get_impl_traits(cx, id),
|x| storeify(cx, *x, store))
csearch::get_impl_traits(cx, id)
}
}
@ -3906,18 +3959,25 @@ pub fn enum_variant_with_id(cx: ctxt,
pub fn lookup_item_type(cx: ctxt,
did: ast::def_id)
-> ty_param_bounds_and_ty {
match cx.tcache.find(&did) {
Some(&tpt) => {
// The item is in this crate. The caller should have added it to the
// type cache already
return tpt;
}
None => {
assert!(did.crate != ast::local_crate);
let tyt = csearch::get_type(cx, did);
cx.tcache.insert(did, tyt);
return tyt;
}
lookup_locally_or_in_crate_store(
"tcache", did, cx.tcache,
|| csearch::get_type(cx, did))
}
/// Given the did of a trait, returns its canonical trait ref.
pub fn lookup_trait_def(cx: ctxt, did: ast::def_id) -> @ty::TraitDef {
match cx.trait_defs.find(&did) {
Some(&trait_def) => {
// The item is in this crate. The caller should have added it to the
// type cache already
return trait_def;
}
None => {
assert!(did.crate != ast::local_crate);
let trait_def = @csearch::get_trait_def(cx, did);
cx.trait_defs.insert(did, trait_def);
return trait_def;
}
}
}
@ -4204,9 +4264,6 @@ pub fn normalize_ty(cx: ctxt, t: t) -> t {
t
},
ty_trait(did, ref substs, BareTraitStore) =>
mk_trait(cx, did, copy *substs, BoxTraitStore),
_ =>
t
};
@ -4272,12 +4329,11 @@ pub fn determine_inherited_purity(parent_purity: ast::purity,
// list.
pub fn iter_bound_traits_and_supertraits(tcx: ctxt,
bounds: param_bounds,
f: &fn(t) -> bool) {
f: &fn(&TraitRef) -> bool) {
let mut fin = false;
for bounds.each |bound| {
let bound_trait_ty = match *bound {
let bound_trait_ref = match *bound {
ty::bound_trait(bound_t) => bound_t,
ty::bound_copy | ty::bound_owned |
@ -4286,39 +4342,38 @@ pub fn iter_bound_traits_and_supertraits(tcx: ctxt,
}
};
let mut supertrait_map = HashMap::new();
let mut supertrait_set = HashMap::new();
let mut seen_def_ids = ~[];
let mut i = 0;
let trait_ty_id = ty_to_def_id(bound_trait_ty).expect(
~"iter_trait_ty_supertraits got a non-trait type");
let mut trait_ty = bound_trait_ty;
let trait_ty_id = bound_trait_ref.def_id;
let mut trait_ref = bound_trait_ref;
debug!("iter_bound_traits_and_supertraits: trait_ty = %s",
ty_to_str(tcx, trait_ty));
debug!("iter_bound_traits_and_supertraits: trait_ref = %s",
trait_ref_to_str(tcx, trait_ref));
// Add the given trait ty to the hash map
supertrait_map.insert(trait_ty_id, trait_ty);
supertrait_set.insert(trait_ty_id, ());
seen_def_ids.push(trait_ty_id);
if f(trait_ty) {
if f(trait_ref) {
// Add all the supertraits to the hash map,
// executing <f> on each of them
while i < supertrait_map.len() && !fin {
while i < supertrait_set.len() && !fin {
let init_trait_id = seen_def_ids[i];
i += 1;
// Add supertraits to supertrait_map
let supertraits = trait_supertraits(tcx, init_trait_id);
for supertraits.each |supertrait| {
let super_t = supertrait.tpt.ty;
let d_id = ty_to_def_id(super_t).expect("supertrait \
should be a trait ty");
if !supertrait_map.contains_key(&d_id) {
supertrait_map.insert(d_id, super_t);
trait_ty = super_t;
// Add supertraits to supertrait_set
let supertrait_refs = trait_supertraits(tcx, init_trait_id);
for supertrait_refs.each |&supertrait_ref| {
let d_id = supertrait_ref.def_id;
if !supertrait_set.contains_key(&d_id) {
// FIXME(#5527) Could have same trait multiple times
supertrait_set.insert(d_id, ());
trait_ref = supertrait_ref;
seen_def_ids.push(d_id);
}
debug!("A super_t = %s", ty_to_str(tcx, trait_ty));
if !f(trait_ty) {
debug!("A super_t = %s", trait_ref_to_str(tcx, trait_ref));
if !f(trait_ref) {
fin = true;
}
}
@ -4355,6 +4410,14 @@ pub fn get_impl_id(tcx: ctxt, trait_id: def_id, self_ty: t) -> def_id {
}
}
pub fn visitor_object_ty(tcx: ctxt) -> (@TraitRef, t) {
let ty_visitor_name = special_idents::ty_visitor;
assert!(tcx.intrinsic_traits.contains_key(&ty_visitor_name));
let trait_ref = *tcx.intrinsic_traits.get(&ty_visitor_name);
(trait_ref,
mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs, BoxTraitStore))
}
// Local Variables:
// mode: rust
// fill-column: 78;

View file

@ -14,14 +14,14 @@
* is parameterized by an instance of `AstConv` and a `region_scope`.
*
* The parameterization of `ast_ty_to_ty()` is because it behaves
* somewhat differently during the collect and check phases, particularly
* with respect to looking up the types of top-level items. In the
* collect phase, the crate context is used as the `AstConv` instance;
* in this phase, the `get_item_ty()` function triggers a recursive call
* to `ty_of_item()` (note that `ast_ty_to_ty()` will detect recursive
* types and report an error). In the check phase, when the @FnCtxt is
* used as the `AstConv`, `get_item_ty()` just looks up the item type in
* `tcx.tcache`.
* somewhat differently during the collect and check phases,
* particularly with respect to looking up the types of top-level
* items. In the collect phase, the crate context is used as the
* `AstConv` instance; in this phase, the `get_item_ty()` function
* triggers a recursive call to `ty_of_item()` (note that
* `ast_ty_to_ty()` will detect recursive types and report an error).
* In the check phase, when the @FnCtxt is used as the `AstConv`,
* `get_item_ty()` just looks up the item type in `tcx.tcache`.
*
* The `region_scope` trait controls how region references are
* handled. It has two methods which are used to resolve anonymous
@ -76,6 +76,7 @@ use util::common::indenter;
pub trait AstConv {
fn tcx(&self) -> ty::ctxt;
fn get_item_ty(&self, id: ast::def_id) -> ty::ty_param_bounds_and_ty;
fn get_trait_def(&self, id: ast::def_id) -> @ty::TraitDef;
// what type should we use when a type is omitted?
fn ty_infer(&self, span: span) -> ty::t;
@ -129,62 +130,96 @@ pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Copy + Durable>(
get_region_reporting_err(self.tcx(), span, opt_lifetime, res)
}
pub fn ast_path_to_substs_and_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
did: ast::def_id,
path: @ast::path)
-> ty_param_substs_and_ty {
let tcx = self.tcx();
let ty::ty_param_bounds_and_ty {
bounds: decl_bounds,
region_param: decl_rp,
ty: decl_ty
} = self.get_item_ty(did);
fn ast_path_substs<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
def_id: ast::def_id,
decl_generics: &ty::Generics,
path: @ast::path) -> ty::substs
{
/*!
*
* Given a path `path` that refers to an item `I` with the
* declared generics `decl_generics`, returns an appropriate
* set of substitutions for this particular reference to `I`.
*/
debug!("ast_path_to_substs_and_ty: did=%? decl_rp=%?",
did, decl_rp);
let tcx = self.tcx();
// 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 = match (decl_rp, path.rp) {
(None, None) => {
let self_r = match (&decl_generics.region_param, &path.rp) {
(&None, &None) => {
None
}
(None, Some(_)) => {
(&None, &Some(_)) => {
tcx.sess.span_err(
path.span,
fmt!("no region bound is allowed on `%s`, \
which is not declared as containing region pointers",
ty::item_path_str(tcx, did)));
ty::item_path_str(tcx, def_id)));
None
}
(Some(_), None) => {
(&Some(_), &None) => {
let res = rscope.anon_region(path.span);
let r = get_region_reporting_err(self.tcx(), path.span, None, res);
Some(r)
}
(Some(_), Some(_)) => {
(&Some(_), &Some(_)) => {
Some(ast_region_to_region(self, rscope, path.span, path.rp))
}
};
// Convert the type parameters supplied by the user.
if !vec::same_length(*decl_bounds, path.types) {
if !vec::same_length(*decl_generics.bounds, path.types) {
self.tcx().sess.span_fatal(
path.span,
fmt!("wrong number of type arguments: expected %u but found %u",
(*decl_bounds).len(), path.types.len()));
decl_generics.bounds.len(), path.types.len()));
}
let tps = path.types.map(|a_t| ast_ty_to_ty(self, rscope, *a_t));
let substs = substs {self_r:self_r, self_ty:None, tps:tps};
let ty = ty::subst(tcx, &substs, decl_ty);
substs {self_r:self_r, self_ty:None, tps:tps}
}
pub fn ast_path_to_substs_and_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
did: ast::def_id,
path: @ast::path) -> ty_param_substs_and_ty
{
let tcx = self.tcx();
let ty::ty_param_bounds_and_ty {
generics: generics,
ty: decl_ty
} = self.get_item_ty(did);
let substs = ast_path_substs(self, rscope, did, &generics, path);
let ty = ty::subst(tcx, &substs, decl_ty);
ty_param_substs_and_ty { substs: substs, ty: ty }
}
pub fn ast_path_to_trait_ref<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
trait_def_id: ast::def_id,
path: @ast::path) -> @ty::TraitRef
{
let trait_def =
self.get_trait_def(trait_def_id);
let substs =
ast_path_substs(
self, rscope,
trait_def.trait_ref.def_id, &trait_def.generics,
path);
let trait_ref =
@ty::TraitRef {def_id: trait_def_id,
substs: substs};
return trait_ref;
}
pub fn ast_path_to_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
@ -243,36 +278,29 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + Durable>(
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
return ty::mk_estr(tcx, vst);
}
Some(&ast::def_ty(type_def_id)) => {
let result = ast_path_to_substs_and_ty(
self, rscope,
type_def_id, path);
match ty::get(result.ty).sty {
ty::ty_trait(trait_def_id, ref substs, _) => {
let trait_store = match vst {
ty::vstore_box => ty::BoxTraitStore,
ty::vstore_uniq => ty::UniqTraitStore,
ty::vstore_slice(r) => {
ty::RegionTraitStore(r)
}
ty::vstore_fixed(*) => {
tcx.sess.span_err(
path.span,
~"@trait, ~trait or &trait \
are the only supported \
forms of casting-to-\
trait");
ty::BoxTraitStore
}
};
return ty::mk_trait(tcx,
trait_def_id,
/*bad*/copy *substs,
trait_store);
Some(&ast::def_trait(trait_def_id)) => {
let result = ast_path_to_trait_ref(
self, rscope, trait_def_id, path);
let trait_store = match vst {
ty::vstore_box => ty::BoxTraitStore,
ty::vstore_uniq => ty::UniqTraitStore,
ty::vstore_slice(r) => {
ty::RegionTraitStore(r)
}
_ => {}
}
ty::vstore_fixed(*) => {
tcx.sess.span_err(
path.span,
~"@trait, ~trait or &trait \
are the only supported \
forms of casting-to-\
trait");
ty::BoxTraitStore
}
};
return ty::mk_trait(tcx,
result.def_id,
copy result.substs,
trait_store);
}
_ => {}
}
@ -372,6 +400,15 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + Durable>(
Some(&d) => d
};
match a_def {
ast::def_trait(_) => {
let path_str = path_to_str(path, tcx.sess.intr());
tcx.sess.span_err(
ast_ty.span,
fmt!("reference to trait `%s` where a type is expected; \
try `@%s`, `~%s`, or `&%s`",
path_str, path_str, path_str, path_str));
ty::mk_err(tcx)
}
ast::def_ty(did) | ast::def_struct(did) => {
ast_path_to_ty(self, rscope, did, path).ty
}
@ -540,6 +577,29 @@ pub fn bound_lifetimes<AC:AstConv>(
bound_lifetime_names
}
struct SelfInfo {
untransformed_self_ty: ty::t,
self_transform: ast::self_ty
}
pub fn ty_of_method<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
purity: ast::purity,
lifetimes: &OptVec<ast::Lifetime>,
untransformed_self_ty: ty::t,
self_transform: ast::self_ty,
decl: &ast::fn_decl) -> (Option<ty::t>, ty::BareFnTy)
{
let self_info = SelfInfo {
untransformed_self_ty: untransformed_self_ty,
self_transform: self_transform
};
let (a, b) = ty_of_method_or_bare_fn(
self, rscope, purity, AbiSet::Rust(), lifetimes, Some(&self_info), decl);
(a.get(), b)
}
pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
@ -547,6 +607,20 @@ pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + Durable>(
abi: AbiSet,
lifetimes: &OptVec<ast::Lifetime>,
decl: &ast::fn_decl) -> ty::BareFnTy
{
let (_, b) = ty_of_method_or_bare_fn(
self, rscope, purity, abi, lifetimes, None, decl);
b
}
fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
purity: ast::purity,
abi: AbiSet,
lifetimes: &OptVec<ast::Lifetime>,
opt_self_info: Option<&SelfInfo>,
decl: &ast::fn_decl) -> (Option<Option<ty::t>>, ty::BareFnTy)
{
debug!("ty_of_bare_fn");
@ -555,18 +629,56 @@ pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + Durable>(
let bound_lifetime_names = bound_lifetimes(self, lifetimes);
let rb = in_binding_rscope(rscope, RegionParamNames(copy bound_lifetime_names));
let opt_transformed_self_ty = opt_self_info.map(|&self_info| {
transform_self_ty(self, &rb, self_info)
});
let input_tys = decl.inputs.map(|a| ty_of_arg(self, &rb, *a, None));
let output_ty = match decl.output.node {
ast::ty_infer => self.ty_infer(decl.output.span),
_ => ast_ty_to_ty(self, &rb, decl.output)
};
ty::BareFnTy {
purity: purity,
abis: abi,
sig: ty::FnSig {bound_lifetime_names: bound_lifetime_names,
inputs: input_tys,
output: output_ty}
return (opt_transformed_self_ty,
ty::BareFnTy {
purity: purity,
abis: abi,
sig: ty::FnSig {bound_lifetime_names: bound_lifetime_names,
inputs: input_tys,
output: output_ty}
});
fn transform_self_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
self_info: &SelfInfo) -> Option<ty::t>
{
match self_info.self_transform.node {
ast::sty_static => None,
ast::sty_value => {
Some(self_info.untransformed_self_ty)
}
ast::sty_region(lifetime, mutability) => {
let region =
ast_region_to_region(self, rscope,
self_info.self_transform.span,
lifetime);
Some(ty::mk_rptr(self.tcx(), region,
ty::mt {ty: self_info.untransformed_self_ty,
mutbl: mutability}))
}
ast::sty_box(mutability) => {
Some(ty::mk_box(self.tcx(),
ty::mt {ty: self_info.untransformed_self_ty,
mutbl: mutability}))
}
ast::sty_uniq(mutability) => {
Some(ty::mk_uniq(self.tcx(),
ty::mt {ty: self_info.untransformed_self_ty,
mutbl: mutability}))
}
}
}
}

View file

@ -135,7 +135,7 @@ pub fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
ty::enum_variant_with_id(tcx, enm, var);
let var_tpt = ty::lookup_item_type(tcx, var);
vinfo.args.map(|t| {
if var_tpt.bounds.len() == expected_substs.tps.len() {
if var_tpt.generics.bounds.len() == expected_substs.tps.len() {
ty::subst(tcx, expected_substs, *t)
}
else {

View file

@ -92,6 +92,7 @@ use middle::typeck::check;
use middle::typeck::infer;
use middle::typeck::{method_map_entry, method_origin, method_param};
use middle::typeck::{method_self, method_static, method_trait, method_super};
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
use util::common::indenter;
use util::ppaux::expr_repr;
@ -99,6 +100,7 @@ use core::hashmap::HashSet;
use core::result;
use core::uint;
use core::vec;
use std::list::Nil;
use syntax::ast::{def_id, sty_value, sty_region, sty_box};
use syntax::ast::{sty_uniq, sty_static, node_id, by_copy, by_ref};
use syntax::ast::{m_const, m_mutbl, m_imm};
@ -121,7 +123,7 @@ pub fn lookup(
fcx: @mut FnCtxt,
// In a call `a.b::<X, Y, ...>(...)`:
expr: @ast::expr, // The expression `a.b`.
expr: @ast::expr, // The expression `a.b(...)`.
self_expr: @ast::expr, // The expression `a`.
callee_id: node_id, // Where to store `a.b`'s type
m_name: ast::ident, // The ident `b`.
@ -174,13 +176,7 @@ pub struct LookupContext<'self> {
pub struct Candidate {
rcvr_ty: ty::t,
rcvr_substs: ty::substs,
explicit_self: ast::self_ty_,
// FIXME #3446---these two fields should be easily derived from
// origin, yet are not
num_method_tps: uint,
self_mode: ast::rmode,
method_ty: @ty::method,
origin: method_origin,
}
@ -386,7 +382,7 @@ pub impl<'self> LookupContext<'self> {
let bounds = tcx.ty_param_bounds.get(&param_ty.def_id.node);
for bounds.each |bound| {
let bound_trait_ty = match *bound {
let bound_trait_ref = match *bound {
ty::bound_trait(bound_t) => bound_t,
ty::bound_copy | ty::bound_owned |
@ -395,22 +391,10 @@ pub impl<'self> LookupContext<'self> {
}
};
let bound_substs = match ty::get(bound_trait_ty).sty {
ty::ty_trait(_, ref substs, _) => (/*bad*/copy *substs),
_ => {
self.bug(fmt!("add_candidates_from_param: \
non-trait bound %s",
self.ty_to_str(bound_trait_ty)));
}
};
// Loop over the trait and all of its supertraits.
let mut worklist = ~[];
let init_trait_ty = bound_trait_ty;
let init_substs = bound_substs;
let init_trait_ref = bound_trait_ref;
// Replace any appearance of `self` with the type of the
// generic parameter itself. Note that this is the only
@ -421,29 +405,26 @@ pub impl<'self> LookupContext<'self> {
// to self are not permitted).
let init_substs = substs {
self_ty: Some(rcvr_ty),
..init_substs
..copy bound_trait_ref.substs
};
worklist.push((init_trait_ty, init_substs));
worklist.push((init_trait_ref.def_id, init_substs));
let mut i = 0;
while i < worklist.len() {
let (init_trait_ty, init_substs) = /*bad*/copy worklist[i];
let (init_trait_id, init_substs) = /*bad*/copy worklist[i];
i += 1;
let init_trait_id = ty::ty_to_def_id(init_trait_ty).get();
// Add all the supertraits of this trait to the worklist.
let supertraits = ty::trait_supertraits(tcx,
init_trait_id);
for supertraits.each |supertrait| {
let supertraits = ty::trait_supertraits(tcx, init_trait_id);
for supertraits.each |supertrait_ref| {
debug!("adding supertrait: %?",
supertrait.def_id);
supertrait_ref.def_id);
let new_substs = ty::subst_substs(
let new_substs = ty::subst_in_substs(
tcx,
&supertrait.tpt.substs,
&init_substs);
&init_substs,
&supertrait_ref.substs);
// Again replacing the self type
let new_substs = substs {
@ -451,7 +432,7 @@ pub impl<'self> LookupContext<'self> {
..new_substs
};
worklist.push((supertrait.tpt.ty, new_substs));
worklist.push((supertrait_ref.def_id, new_substs));
}
@ -472,7 +453,7 @@ pub impl<'self> LookupContext<'self> {
}
}
};
let method = &trait_methods[pos];
let method = trait_methods[pos];
let (rcvr_ty, rcvr_substs) =
self.create_rcvr_ty_and_substs_for_method(
@ -484,9 +465,7 @@ pub impl<'self> LookupContext<'self> {
let cand = Candidate {
rcvr_ty: rcvr_ty,
rcvr_substs: rcvr_substs,
explicit_self: method.self_ty,
num_method_tps: method.tps.len(),
self_mode: get_mode_from_self_type(method.self_ty),
method_ty: method,
origin: method_param(
method_param {
trait_id: init_trait_id,
@ -518,7 +497,7 @@ pub impl<'self> LookupContext<'self> {
Some(i) => i,
None => { return; } // no method with the right name
};
let method = &ms[index];
let method = ms[index];
/* FIXME(#3157) we should transform the vstore in accordance
with the self type
@ -552,9 +531,7 @@ pub impl<'self> LookupContext<'self> {
self.inherent_candidates.push(Candidate {
rcvr_ty: rcvr_ty,
rcvr_substs: rcvr_substs,
explicit_self: method.self_ty,
num_method_tps: method.tps.len(),
self_mode: get_mode_from_self_type(method.self_ty),
method_ty: method,
origin: method_trait(did, index, store)
});
}
@ -563,63 +540,65 @@ pub impl<'self> LookupContext<'self> {
self_ty: ty::t,
did: def_id,
substs: &ty::substs) {
struct MethodInfo {
method_ty: @ty::method,
trait_def_id: ast::def_id,
index: uint
}
let tcx = self.tcx();
// First, try self methods
let mut method = None;
let mut method_info: Option<MethodInfo> = None;
let methods = ty::trait_methods(tcx, did);
let mut index = None;
let mut trait_did = None;
match vec::position(*methods, |m| m.ident == self.m_name) {
Some(i) => {
index = Some(i);
trait_did = Some(did);
method = Some((methods[i].self_ty, methods[i].tps.len()));
method_info = Some(MethodInfo {
method_ty: methods[i],
index: i,
trait_def_id: did
});
}
None => ()
}
// No method found yet? Check each supertrait
if method.is_none() {
if method_info.is_none() {
for ty::trait_supertraits(tcx, did).each() |trait_ref| {
let supertrait_methods =
ty::trait_methods(tcx, trait_ref.def_id);
match vec::position(*supertrait_methods,
|m| m.ident == self.m_name) {
Some(i) => {
index = Some(i);
trait_did = Some(trait_ref.def_id);
method = Some((supertrait_methods[i].self_ty,
supertrait_methods[i].tps.len()));
method_info = Some(MethodInfo {
method_ty: supertrait_methods[i],
index: i,
trait_def_id: trait_ref.def_id
});
break;
}
None => ()
}
}
}
match (method, index, trait_did) {
(Some((method_self_ty, method_num_tps)),
Some(index), Some(trait_did)) => {
match method_info {
Some(ref info) => {
// We've found a method -- return it
let rcvr_substs = substs { self_ty: Some(self_ty),
let rcvr_substs = substs {self_ty: Some(self_ty),
..copy *substs };
let (rcvr_ty, rcvr_substs) =
self.create_rcvr_ty_and_substs_for_method(
method_self_ty,
info.method_ty.self_ty,
self_ty,
rcvr_substs,
TransformTypeNormally);
let origin = if trait_did == did {
method_self(trait_did, index)
}
else {
method_super(trait_did, index)
let origin = if did == info.trait_def_id {
method_self(info.trait_def_id, info.index)
} else {
method_super(info.trait_def_id, info.index)
};
self.inherent_candidates.push(Candidate {
rcvr_ty: rcvr_ty,
rcvr_substs: rcvr_substs,
explicit_self: method_self_ty,
num_method_tps: method_num_tps,
self_mode: get_mode_from_self_type(method_self_ty),
method_ty: info.method_ty,
origin: origin
});
}
@ -651,7 +630,7 @@ pub impl<'self> LookupContext<'self> {
}
};
let method = &impl_info.methods[idx];
let method = ty::method(self.tcx(), impl_info.methods[idx].did);
// determine the `self` of the impl with fresh
// variables for each parameter:
@ -667,7 +646,7 @@ pub impl<'self> LookupContext<'self> {
let (impl_ty, impl_substs) =
self.create_rcvr_ty_and_substs_for_method(
method.self_type,
method.self_ty,
impl_ty,
impl_substs,
TransformTypeNormally);
@ -675,10 +654,8 @@ pub impl<'self> LookupContext<'self> {
candidates.push(Candidate {
rcvr_ty: impl_ty,
rcvr_substs: impl_substs,
explicit_self: method.self_type,
num_method_tps: method.n_tps,
self_mode: get_mode_from_self_type(method.self_type),
origin: method_static(method.did)
method_ty: method,
origin: method_static(method.def_id)
});
}
@ -699,6 +676,9 @@ pub impl<'self> LookupContext<'self> {
debug!("(pushing candidates from provided methods) adding \
candidate");
let method = ty::method(self.tcx(),
provided_method_info.method_info.did);
// XXX: Needs to support generics.
let dummy_substs = substs {
self_r: None,
@ -707,7 +687,7 @@ pub impl<'self> LookupContext<'self> {
};
let (impl_ty, impl_substs) =
self.create_rcvr_ty_and_substs_for_method(
provided_method_info.method_info.self_type,
method.self_ty,
self_ty,
dummy_substs,
TransformTypeNormally);
@ -715,10 +695,7 @@ pub impl<'self> LookupContext<'self> {
candidates.push(Candidate {
rcvr_ty: impl_ty,
rcvr_substs: impl_substs,
explicit_self: provided_method_info.method_info.self_type,
num_method_tps: provided_method_info.method_info.n_tps,
self_mode: get_mode_from_self_type(
provided_method_info.method_info.self_type),
method_ty: method,
origin: method_static(provided_method_info.method_info.did)
});
}
@ -1092,10 +1069,16 @@ pub impl<'self> LookupContext<'self> {
fn confirm_candidate(&self,
self_ty: ty::t,
candidate: &Candidate)
-> method_map_entry {
-> method_map_entry
{
let tcx = self.tcx();
let fty = self.fn_ty_from_origin(&candidate.origin);
debug!("confirm_candidate(expr=%s, candidate=%s, fty=%s)",
expr_repr(tcx, self.expr),
self.cand_to_str(candidate),
self.ty_to_str(fty));
self.enforce_trait_instance_limitations(fty, candidate);
self.enforce_drop_trait_limitations(candidate);
@ -1118,20 +1101,21 @@ pub impl<'self> LookupContext<'self> {
// If they were not explicitly supplied, just construct fresh
// type variables.
let num_supplied_tps = self.supplied_tps.len();
let num_method_tps = candidate.method_ty.generics.bounds.len();
let m_substs = {
if num_supplied_tps == 0u {
self.fcx.infcx().next_ty_vars(candidate.num_method_tps)
} else if candidate.num_method_tps == 0u {
self.fcx.infcx().next_ty_vars(num_method_tps)
} else if num_method_tps == 0u {
tcx.sess.span_err(
self.expr.span,
~"this method does not take type parameters");
self.fcx.infcx().next_ty_vars(candidate.num_method_tps)
} else if num_supplied_tps != candidate.num_method_tps {
self.fcx.infcx().next_ty_vars(num_method_tps)
} else if num_supplied_tps != num_method_tps {
tcx.sess.span_err(
self.expr.span,
~"incorrect number of type \
parameters given for this method");
self.fcx.infcx().next_ty_vars(candidate.num_method_tps)
self.fcx.infcx().next_ty_vars(num_method_tps)
} else {
self.supplied_tps.to_vec()
}
@ -1145,13 +1129,41 @@ pub impl<'self> LookupContext<'self> {
../*bad*/copy candidate.rcvr_substs
};
self.fcx.write_ty_substs(self.callee_id, fty, all_substs);
// Compute the method type with type parameters substituted
debug!("fty=%s all_substs=%s",
self.ty_to_str(fty),
ty::substs_to_str(tcx, &all_substs));
let fty = ty::subst(tcx, &all_substs, fty);
debug!("after subst, fty=%s", self.ty_to_str(fty));
// Replace any bound regions that appear in the function
// signature with region variables
let bare_fn_ty = match ty::get(fty).sty {
ty::ty_bare_fn(ref f) => copy *f,
ref s => {
tcx.sess.span_bug(
self.expr.span,
fmt!("Invoking method with non-bare-fn ty: %?", s));
}
};
let (_, _, fn_sig) =
replace_bound_regions_in_fn_sig(
tcx, @Nil, None, &bare_fn_ty.sig,
|_br| self.fcx.infcx().next_region_var(
self.expr.span, self.expr.id));
let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {sig: fn_sig, ..bare_fn_ty});
debug!("after replacing bound regions, fty=%s", self.ty_to_str(fty));
let self_mode = get_mode_from_self_type(candidate.method_ty.self_ty);
self.fcx.write_ty(self.callee_id, fty);
self.fcx.write_substs(self.callee_id, all_substs);
method_map_entry {
self_arg: arg {
mode: ast::expl(candidate.self_mode),
mode: ast::expl(self_mode),
ty: candidate.rcvr_ty,
},
explicit_self: candidate.explicit_self,
explicit_self: candidate.method_ty.self_ty,
origin: candidate.origin,
}
}
@ -1183,7 +1195,7 @@ pub impl<'self> LookupContext<'self> {
self-type through a boxed trait");
}
if candidate.num_method_tps > 0 {
if candidate.method_ty.generics.bounds.len() > 0 {
self.tcx().sess.span_err(
self.expr.span,
~"cannot call a generic method through a boxed trait");
@ -1300,10 +1312,9 @@ pub impl<'self> LookupContext<'self> {
}
fn cand_to_str(&self, cand: &Candidate) -> ~str {
fmt!("Candidate(rcvr_ty=%s, rcvr_substs=%s, self_mode=%?, origin=%?)",
fmt!("Candidate(rcvr_ty=%s, rcvr_substs=%s, origin=%?)",
self.ty_to_str(cand.rcvr_ty),
ty::substs_to_str(self.tcx(), &cand.rcvr_substs),
cand.self_mode,
cand.origin)
}

View file

@ -610,7 +610,7 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
} else {
for m.items.each |item| {
let tpt = ty::lookup_item_type(ccx.tcx, local_def(item.id));
if !tpt.bounds.is_empty() {
if !tpt.generics.bounds.is_empty() {
ccx.tcx.sess.span_err(
item.span,
fmt!("foreign items may not have type parameters"));
@ -629,6 +629,10 @@ impl AstConv for FnCtxt {
ty::lookup_item_type(self.tcx(), id)
}
fn get_trait_def(&self, id: ast::def_id) -> @ty::TraitDef {
ty::lookup_trait_def(self.tcx(), id)
}
fn ty_infer(&self, _span: span) -> ty::t {
self.infcx().next_ty_var()
}
@ -1064,7 +1068,7 @@ pub fn impl_self_ty(vcx: &VtableContext,
let (n_tps, region_param, raw_ty) = {
let ity = ty::lookup_item_type(tcx, did);
(vec::len(*ity.bounds), ity.region_param, ity.ty)
(ity.generics.bounds.len(), ity.generics.region_param, ity.ty)
};
let self_r = if region_param.is_some() {
@ -1122,103 +1126,84 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
unifier: &fn()) {
debug!(">> typechecking %s", fcx.expr_to_str(expr));
// A generic function to factor out common logic from call and
// overloaded operations
fn check_call_inner(
fn check_method_argument_types(
fcx: @mut FnCtxt,
sp: span,
call_expr_id: ast::node_id,
in_fty: ty::t,
method_fn_ty: ty::t,
callee_expr: @ast::expr,
args: &[@ast::expr],
sugar: ast::CallSugar,
deref_args: DerefArgs) -> ty::t
{
let tcx = fcx.ccx.tcx;
// Replace all region parameters in the arguments and return
// type with fresh region variables.
debug!("check_call_inner: before universal quant., in_fty=%s",
fcx.infcx().ty_to_str(in_fty));
let formal_tys;
// FIXME(#3678) For now, do not permit calls to C abi functions.
match structure_of(fcx, sp, in_fty) {
ty::ty_bare_fn(ty::BareFnTy {abis, _}) => {
if !abis.is_rust() {
tcx.sess.span_err(
if ty::type_is_error(method_fn_ty) {
let err_inputs = err_args(fcx.tcx(), args.len());
check_argument_types(fcx, sp, err_inputs, callee_expr,
args, sugar, deref_args);
method_fn_ty
} else {
match ty::get(method_fn_ty).sty {
ty::ty_bare_fn(ref fty) => {
check_argument_types(fcx, sp, fty.sig.inputs, callee_expr,
args, sugar, deref_args);
fty.sig.output
}
_ => {
fcx.tcx().sess.span_bug(
sp,
fmt!("Calls to C ABI functions are not (yet) \
supported; be patient, dear user"));
fmt!("Method without bare fn type"));
}
}
_ => {}
}
}
// This is subtle: we expect `fty` to be a function type, which
// normally introduce a level of binding. In this case, we want to
// process the types bound by the function but not by any nested
// functions. Therefore, we match one level of structure.
let ret_ty = match structure_of(fcx, sp, in_fty) {
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
let (_, _, sig) =
replace_bound_regions_in_fn_sig(
tcx, @Nil, None, sig,
|_br| fcx.infcx().next_region_var(
sp, call_expr_id));
fn check_argument_types(
fcx: @mut FnCtxt,
sp: span,
fn_inputs: &[ty::arg],
callee_expr: @ast::expr,
args: &[@ast::expr],
sugar: ast::CallSugar,
deref_args: DerefArgs)
{
/*!
*
* Generic function that factors out common logic from
* function calls, method calls and overloaded operators.
*/
let supplied_arg_count = args.len();
let tcx = fcx.ccx.tcx;
// Grab the argument types, supplying fresh type variables
// if the wrong number of arguments were supplied
let expected_arg_count = sig.inputs.len();
formal_tys = if expected_arg_count == supplied_arg_count {
sig.inputs.map(|a| a.ty)
} else {
let suffix = match sugar {
ast::NoSugar => "",
ast::DoSugar => " (including the closure passed by \
the `do` keyword)",
ast::ForSugar => " (including the closure passed by \
the `for` keyword)"
};
let msg = fmt!("this function takes %u parameter%s but \
%u parameter%s supplied%s",
expected_arg_count,
if expected_arg_count == 1 {""}
else {"s"},
supplied_arg_count,
if supplied_arg_count == 1 {" was"}
else {"s were"},
suffix);
// Grab the argument types, supplying fresh type variables
// if the wrong number of arguments were supplied
let supplied_arg_count = args.len();
let expected_arg_count = fn_inputs.len();
let formal_tys = if expected_arg_count == supplied_arg_count {
fn_inputs.map(|a| a.ty)
} else {
let suffix = match sugar {
ast::NoSugar => "",
ast::DoSugar => " (including the closure passed by \
the `do` keyword)",
ast::ForSugar => " (including the closure passed by \
the `for` keyword)"
};
let msg = fmt!("this function takes %u parameter%s but \
%u parameter%s supplied%s",
expected_arg_count,
if expected_arg_count == 1 {""}
else {"s"},
supplied_arg_count,
if supplied_arg_count == 1 {" was"}
else {"s were"},
suffix);
tcx.sess.span_err(sp, msg);
tcx.sess.span_err(sp, msg);
vec::from_fn(supplied_arg_count, |_| ty::mk_err(tcx))
};
sig.output
}
_ => {
fcx.type_error_message(sp, |actual| {
fmt!("expected function or foreign function but \
found `%s`", actual) }, in_fty, None);
// check each arg against "error", in order to set up
// all the node type bindings
formal_tys = args.map(|_x| ty::mk_err(tcx));
ty::mk_err(tcx)
}
vec::from_elem(supplied_arg_count, ty::mk_err(tcx))
};
debug!("check_call_inner: after universal quant., \
formal_tys=%? ret_ty=%s",
formal_tys.map(|t| fcx.infcx().ty_to_str(*t)),
fcx.infcx().ty_to_str(ret_ty));
debug!("check_argument_types: formal_tys=%?",
formal_tys.map(|t| fcx.infcx().ty_to_str(*t)));
// Check the arguments.
// We do this in a pretty awful way: first we typecheck any arguments
@ -1268,8 +1253,11 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
}
}
}
}
ret_ty
fn err_args(tcx: ty::ctxt, len: uint) -> ~[ty::arg] {
vec::from_fn(len, |_| ty::arg {mode: ast::expl(ast::by_copy),
ty: ty::mk_err(tcx)})
}
// A generic function for checking assignment expressions
@ -1284,43 +1272,63 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
// The callee checks for bot / err, we don't need to
}
// A generic function for doing all of the checking for call or
// method expressions
fn check_call_or_method(fcx: @mut FnCtxt,
sp: span,
call_expr_id: ast::node_id,
fn_ty: ty::t,
expr: @ast::expr,
args: &[@ast::expr],
sugar: ast::CallSugar)
{
// Call the generic checker.
let ret_ty = check_call_inner(fcx, sp, call_expr_id,
fn_ty, expr, args, sugar,
DontDerefArgs);
// Pull the return type out of the type of the function.
fcx.write_ty(call_expr_id, ret_ty);
// Callee checks for bot and err, no need for that
}
// A generic function for doing all of the checking for call expressions
fn check_call(fcx: @mut FnCtxt,
sp: span,
call_expr_id: ast::node_id,
call_expr: @ast::expr,
f: @ast::expr,
args: &[@ast::expr],
sugar: ast::CallSugar) {
// Index expressions need to be handled separately, to inform them
// that they appear in call position.
let mut _bot = check_expr(fcx, f);
check_call_or_method(fcx,
sp,
call_expr_id,
fcx.expr_ty(f),
f,
args,
sugar)
check_expr(fcx, f);
// Extract the function signature from `in_fty`.
let fn_ty = fcx.expr_ty(f);
let fn_sty = structure_of(fcx, f.span, fn_ty);
// FIXME(#3678) For now, do not permit calls to C abi functions.
match fn_sty {
ty::ty_bare_fn(ty::BareFnTy {abis, _}) => {
if !abis.is_rust() {
fcx.tcx().sess.span_err(
call_expr.span,
fmt!("Calls to C ABI functions are not (yet) \
supported; be patient, dear user"));
}
}
_ => {}
}
let fn_sig = match fn_sty {
ty::ty_bare_fn(ty::BareFnTy {sig: sig, _}) |
ty::ty_closure(ty::ClosureTy {sig: sig, _}) => sig,
_ => {
fcx.type_error_message(call_expr.span, |actual| {
fmt!("expected function but \
found `%s`", actual) }, fn_ty, None);
// check each arg against "error", in order to set up
// all the node type bindings
FnSig {bound_lifetime_names: opt_vec::Empty,
inputs: err_args(fcx.tcx(), args.len()),
output: ty::mk_err(fcx.tcx())}
}
};
// Replace any bound regions that appear in the function
// signature with region variables
let (_, _, fn_sig) =
replace_bound_regions_in_fn_sig(
fcx.tcx(), @Nil, None, &fn_sig,
|_br| fcx.infcx().next_region_var(call_expr.span, call_expr.id));
// Call the generic checker.
check_argument_types(fcx, call_expr.span, fn_sig.inputs, f,
args, sugar, DontDerefArgs);
// Pull the return type out of the type of the function.
fcx.write_ty(call_expr.id, fn_sig.output);
}
// Checks a method call.
@ -1332,6 +1340,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
tps: &[@ast::Ty],
sugar: ast::CallSugar) {
check_expr(fcx, rcvr);
// no need to check for bot/err -- callee does that
let expr_t = structurally_resolved_type(fcx,
expr.span,
@ -1369,13 +1378,14 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
}
}
check_call_or_method(fcx,
expr.span,
expr.id,
fcx.node_ty(expr.callee_id),
expr,
args,
sugar)
// Call the generic checker.
let fn_ty = fcx.node_ty(expr.callee_id);
let ret_ty = check_method_argument_types(fcx, expr.span,
fn_ty, expr, args, sugar,
DontDerefArgs);
// Pull the return type out of the type of the function.
fcx.write_ty(expr.id, ret_ty);
}
// A generic function for checking the then and else in an if
@ -1423,10 +1433,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
let method_ty = fcx.node_ty(op_ex.callee_id);
let method_map = fcx.inh.method_map;
method_map.insert(op_ex.id, *origin);
check_call_inner(fcx, op_ex.span,
op_ex.id, method_ty,
op_ex, args,
ast::NoSugar, deref_args)
check_method_argument_types(fcx, op_ex.span,
method_ty, op_ex, args,
ast::NoSugar, deref_args)
}
_ => {
let tcx = fcx.tcx();
@ -1434,9 +1443,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
// Check the args anyway
// so we get all the error messages
let expected_ty = ty::mk_err(tcx);
check_call_inner(fcx, op_ex.span, op_ex.id,
expected_ty, op_ex, args,
ast::NoSugar, deref_args);
check_method_argument_types(fcx, op_ex.span,
expected_ty, op_ex, args,
ast::NoSugar, deref_args);
ty::mk_err(tcx)
}
}
@ -1884,8 +1893,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
}
} else {
let item_type = ty::lookup_item_type(tcx, class_id);
type_parameter_count = (*item_type.bounds).len();
region_parameterized = item_type.region_param;
type_parameter_count = item_type.generics.bounds.len();
region_parameterized = item_type.generics.region_param;
raw_type = item_type.ty;
}
@ -1972,8 +1981,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
}
} else {
let item_type = ty::lookup_item_type(tcx, enum_id);
type_parameter_count = (*item_type.bounds).len();
region_parameterized = item_type.region_param;
type_parameter_count = item_type.generics.bounds.len();
region_parameterized = item_type.generics.region_param;
raw_type = item_type.ty;
}
@ -2121,12 +2130,12 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
match expr.node {
ast::expr_vstore(ev, vst) => {
let typ = match ev.node {
ast::expr_lit(@codemap::spanned { node: ast::lit_str(s), _ }) => {
let tt = ast_expr_vstore_to_vstore(fcx, ev, s.len(), vst);
ast::expr_lit(@codemap::spanned { node: ast::lit_str(_), _ }) => {
let tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
ty::mk_estr(tcx, tt)
}
ast::expr_vec(ref args, mutbl) => {
let tt = ast_expr_vstore_to_vstore(fcx, ev, args.len(), vst);
let tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
let mutability;
let mut any_error = false;
let mut any_bot = false;
@ -2158,9 +2167,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
}
}
ast::expr_repeat(element, count_expr, mutbl) => {
let count = ty::eval_repeat_count(tcx, count_expr);
let _ = ty::eval_repeat_count(tcx, count_expr);
check_expr_with_hint(fcx, count_expr, ty::mk_uint(tcx));
let tt = ast_expr_vstore_to_vstore(fcx, ev, count, vst);
let tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
let mutability = match vst {
ast::expr_vstore_mut_box | ast::expr_vstore_mut_slice => {
ast::m_mutbl
@ -2546,7 +2555,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
fcx.write_ty(id, fcx.node_ty(b.node.id));
}
ast::expr_call(f, ref args, sugar) => {
check_call(fcx, expr.span, expr.id, f, *args, sugar);
check_call(fcx, expr, f, *args, sugar);
let f_ty = fcx.expr_ty(f);
let (args_bot, args_err) = args.foldl((false, false),
|&(rest_bot, rest_err), a| {
@ -3143,8 +3152,10 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt,
ast::def_fn(_, ast::extern_fn) => {
// extern functions are just u8 pointers
return ty_param_bounds_and_ty {
bounds: @~[],
region_param: None,
generics: ty::Generics {
bounds: @~[],
region_param: None
},
ty: ty::mk_ptr(
fcx.ccx.tcx,
ty::mt {
@ -3169,7 +3180,10 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt,
ast::def_upvar(_, inner, _, _) => {
return ty_param_bounds_and_ty_for_def(fcx, sp, *inner);
}
ast::def_ty(_) | ast::def_prim_ty(_) | ast::def_ty_param(*)=> {
ast::def_trait(_) |
ast::def_ty(_) |
ast::def_prim_ty(_) |
ast::def_ty_param(*)=> {
fcx.ccx.tcx.sess.span_bug(sp, ~"expected value but found type");
}
ast::def_mod(*) | ast::def_foreign_mod(*) => {
@ -3204,14 +3218,18 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
region_lb: ty::Region) {
debug!(">>> instantiate_path");
let ty_param_count = vec::len(*tpt.bounds);
let ty_param_count = tpt.generics.bounds.len();
let ty_substs_len = vec::len(pth.types);
debug!("ty_param_count=%? ty_substs_len=%?",
ty_param_count,
ty_substs_len);
// determine the region bound, using the value given by the user
// (if any) and otherwise using a fresh region variable
let self_r = match pth.rp {
Some(_) => { // user supplied a lifetime parameter...
match tpt.region_param {
match tpt.generics.region_param {
None => { // ...but the type is not lifetime parameterized!
fcx.ccx.tcx.sess.span_err
(span, ~"this item is not region-parameterized");
@ -3224,7 +3242,7 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
}
None => { // no lifetime parameter supplied, insert default
fcx.region_var_if_parameterized(
tpt.region_param, span, region_lb)
tpt.generics.region_param, span, region_lb)
}
};
@ -3302,7 +3320,6 @@ pub fn type_is_c_like_enum(fcx: @mut FnCtxt, sp: span, typ: ty::t) -> bool {
pub fn ast_expr_vstore_to_vstore(fcx: @mut FnCtxt,
e: @ast::expr,
_n: uint,
v: ast::expr_vstore)
-> ty::vstore {
match v {
@ -3423,28 +3440,13 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
}
~"visit_tydesc" => {
let tydesc_name = special_idents::tydesc;
let ty_visitor_name = tcx.sess.ident_of(~"TyVisitor");
assert!(tcx.intrinsic_defs.contains_key(&tydesc_name));
assert!(ccx.tcx.intrinsic_defs.contains_key(&ty_visitor_name));
let (_, tydesc_ty) = *tcx.intrinsic_defs.get(&tydesc_name);
let (_, visitor_trait) = *tcx.intrinsic_defs.get(&ty_visitor_name);
let visitor_trait = match ty::get(visitor_trait).sty {
ty::ty_trait(trait_def_id, ref trait_substs, _) => {
ty::mk_trait(tcx,
trait_def_id,
copy *trait_substs,
ty::BoxTraitStore)
}
_ => {
tcx.sess.span_bug(it.span, ~"TyVisitor wasn't a trait?!")
}
};
let (_, visitor_object_ty) = ty::visitor_object_ty(tcx);
let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {ty: tydesc_ty,
mutbl: ast::m_imm});
(0u, ~[arg(ast::by_copy, td_ptr),
arg(ast::by_ref, visitor_trait)], ty::mk_nil(tcx))
arg(ast::by_ref, visitor_object_ty)], ty::mk_nil(tcx))
}
~"frame_address" => {
let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy {
@ -3690,7 +3692,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
output: output}
});
let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
let i_n_tps = (*i_ty.bounds).len();
let i_n_tps = i_ty.generics.bounds.len();
if i_n_tps != n_tps {
tcx.sess.span_err(it.span, fmt!("intrinsic has wrong number \
of type parameters: found %u, \

View file

@ -70,7 +70,7 @@ pub impl VtableContext {
fn tcx(&const self) -> ty::ctxt { self.ccx.tcx }
}
pub fn has_trait_bounds(tps: ~[ty::param_bounds]) -> bool {
fn has_trait_bounds(tps: ~[ty::param_bounds]) -> bool {
vec::any(tps, |bs| {
bs.any(|b| {
match b { &ty::bound_trait(_) => true, _ => false }
@ -78,11 +78,11 @@ pub fn has_trait_bounds(tps: ~[ty::param_bounds]) -> bool {
})
}
pub fn lookup_vtables(vcx: &VtableContext,
location_info: &LocationInfo,
bounds: @~[ty::param_bounds],
substs: &ty::substs,
is_early: bool) -> vtable_res {
fn lookup_vtables(vcx: &VtableContext,
location_info: &LocationInfo,
bounds: @~[ty::param_bounds],
substs: &ty::substs,
is_early: bool) -> vtable_res {
debug!("lookup_vtables(location_info=%?,
# bounds=%?, \
substs=%s",
@ -95,30 +95,30 @@ pub fn lookup_vtables(vcx: &VtableContext,
let mut result = ~[], i = 0u;
for substs.tps.each |ty| {
for ty::iter_bound_traits_and_supertraits(
tcx, bounds[i]) |trait_ty|
tcx, bounds[i]) |trait_ref|
{
debug!("about to subst: %?, %?",
ppaux::ty_to_str(tcx, trait_ty),
ppaux::trait_ref_to_str(tcx, trait_ref),
ty::substs_to_str(tcx, substs));
let new_substs = substs {
self_ty: Some(*ty),
../*bad*/copy *substs
};
let trait_ty = ty::subst(tcx, &new_substs, trait_ty);
let trait_ref = ty::subst_in_trait_ref(tcx, &new_substs, trait_ref);
debug!("after subst: %?",
ppaux::ty_to_str(tcx, trait_ty));
vcx.infcx.trait_ref_to_str(&trait_ref));
match lookup_vtable(vcx, location_info, *ty, trait_ty, is_early) {
match lookup_vtable(vcx, location_info, *ty, &trait_ref, is_early) {
Some(vtable) => result.push(vtable),
None => {
vcx.tcx().sess.span_fatal(
location_info.span,
fmt!("failed to find an implementation of \
trait %s for %s",
ppaux::ty_to_str(vcx.tcx(), trait_ty),
ppaux::ty_to_str(vcx.tcx(), *ty)));
vcx.infcx.trait_ref_to_str(&trait_ref),
vcx.infcx.ty_to_str(*ty)));
}
}
}
@ -136,9 +136,9 @@ pub fn lookup_vtables(vcx: &VtableContext,
@result
}
pub fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo,
id: ast::def_id, +substs: ty::substs,
is_early: bool) -> Option<ty::substs> {
fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo,
id: ast::def_id, +substs: ty::substs,
is_early: bool) -> Option<ty::substs> {
let tcx = vcx.tcx();
// use a dummy type just to package up the substs that need fixing up
let t = ty::mk_trait(tcx,
@ -152,31 +152,58 @@ pub fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo,
}
}
pub fn relate_trait_tys(vcx: &VtableContext, location_info: &LocationInfo,
exp_trait_ty: ty::t, act_trait_ty: ty::t) {
demand_suptype(vcx, location_info.span, exp_trait_ty, act_trait_ty)
fn relate_trait_refs(vcx: &VtableContext,
location_info: &LocationInfo,
act_trait_ref: &ty::TraitRef,
exp_trait_ref: &ty::TraitRef)
{
/*!
*
* Checks that an implementation of `act_trait_ref` is suitable
* for use where `exp_trait_ref` is required and reports an
* error otherwise.
*/
match infer::mk_sub_trait_refs(vcx.infcx, false, location_info.span,
act_trait_ref, exp_trait_ref)
{
result::Ok(()) => {} // Ok.
result::Err(ref err) => {
let r_act_trait_ref =
vcx.infcx.resolve_type_vars_in_trait_ref_if_possible(act_trait_ref);
let r_exp_trait_ref =
vcx.infcx.resolve_type_vars_in_trait_ref_if_possible(exp_trait_ref);
if !ty::trait_ref_contains_error(&r_act_trait_ref) &&
!ty::trait_ref_contains_error(&r_exp_trait_ref)
{
let tcx = vcx.tcx();
tcx.sess.span_err(
location_info.span,
fmt!("expected %s, but found %s (%s)",
ppaux::trait_ref_to_str(tcx, &r_exp_trait_ref),
ppaux::trait_ref_to_str(tcx, &r_act_trait_ref),
ty::type_err_to_str(tcx, err)));
}
}
}
}
// Look up the vtable to use when treating an item of type `t` as if it has
// type `trait_ty`
pub fn lookup_vtable(vcx: &VtableContext,
location_info: &LocationInfo,
ty: ty::t,
trait_ty: ty::t,
is_early: bool)
-> Option<vtable_origin> {
debug!("lookup_vtable(ty=%s, trait_ty=%s)",
vcx.infcx.ty_to_str(ty), vcx.infcx.ty_to_str(trait_ty));
fn lookup_vtable(vcx: &VtableContext,
location_info: &LocationInfo,
ty: ty::t,
trait_ref: &ty::TraitRef,
is_early: bool)
-> Option<vtable_origin>
{
debug!("lookup_vtable(ty=%s, trait_ref=%s)",
vcx.infcx.ty_to_str(ty),
vcx.infcx.trait_ref_to_str(trait_ref));
let _i = indenter();
let tcx = vcx.tcx();
let (trait_id, trait_substs, trait_store) = match ty::get(trait_ty).sty {
ty::ty_trait(did, ref substs, store) =>
(did, (/*bad*/copy *substs), store),
_ => tcx.sess.impossible_case(location_info.span,
"lookup_vtable: \
don't know how to handle a non-trait")
};
let ty = match fixup_ty(vcx, location_info, ty, is_early) {
Some(ty) => ty,
None => {
@ -194,37 +221,20 @@ pub fn lookup_vtable(vcx: &VtableContext,
let mut n_bound = 0;
let bounds = *tcx.ty_param_bounds.get(&did.node);
for ty::iter_bound_traits_and_supertraits(
tcx, bounds) |ity| {
tcx, bounds) |bound_trait_ref|
{
debug!("checking bounds trait %?",
vcx.infcx.ty_to_str(ity));
vcx.infcx.trait_ref_to_str(bound_trait_ref));
match ty::get(ity).sty {
ty::ty_trait(idid, ref isubsts, _) => {
if trait_id == idid {
debug!("(checking vtable) @0 \
relating ty to trait \
ty with did %?",
idid);
// Convert `ity` so that it has the right vstore.
let ity = ty::mk_trait(vcx.tcx(),
idid,
copy *isubsts,
trait_store);
relate_trait_tys(vcx, location_info,
trait_ty, ity);
let vtable = vtable_param(n, n_bound);
debug!("found param vtable: %?",
vtable);
return Some(vtable);
}
}
_ => tcx.sess.impossible_case(
location_info.span,
"lookup_vtable: in loop, \
don't know how to handle a \
non-trait ity")
if bound_trait_ref.def_id == trait_ref.def_id {
relate_trait_refs(vcx,
location_info,
bound_trait_ref,
trait_ref);
let vtable = vtable_param(n, n_bound);
debug!("found param vtable: %?",
vtable);
return Some(vtable);
}
n_bound += 1;
@ -236,18 +246,19 @@ pub fn lookup_vtable(vcx: &VtableContext,
let mut impls_seen = HashSet::new();
match vcx.ccx.coherence_info.extension_methods.find(&trait_id) {
match vcx.ccx.coherence_info.extension_methods.find(&trait_ref.def_id) {
None => {
// Nothing found. Continue.
}
Some(implementations) => {
let implementations: &mut ~[@Impl] = *implementations;
// implementations is the list of all impls in scope for
// trait_ty. (Usually, there's just one.)
// trait_ref. (Usually, there's just one.)
for uint::range(0, implementations.len()) |i| {
let im = implementations[i];
// im is one specific impl of trait_ty.
// im is one specific impl of trait_ref.
// First, ensure we haven't processed this impl yet.
if impls_seen.contains(&im.did) {
@ -269,22 +280,15 @@ pub fn lookup_vtable(vcx: &VtableContext,
// ~[baz<int>, bar, quux]
//
// For each of the traits foo implements, if
// it's the same trait as trait_ty, we need to
// unify it with trait_ty in order to get all
// it's the same trait as trait_ref, we need to
// unify it with trait_ref in order to get all
// the ty vars sorted out.
for vec::each(ty::impl_traits(tcx,
im.did,
trait_store)) |of_ty| {
match ty::get(*of_ty).sty {
ty::ty_trait(id, _, _) => {
// Not the trait we're looking for
if id != trait_id { loop; }
}
_ => { /* ok */ }
}
for ty::impl_trait_refs(tcx, im.did).each |&of_trait_ref|
{
if of_trait_ref.def_id != trait_ref.def_id { loop; }
// At this point, we know that of_ty is
// the same trait as trait_ty, but
// At this point, we know that of_trait_ref is
// the same trait as trait_ref, but
// possibly applied to different substs.
//
// Next, we check whether the "for" ty in
@ -318,39 +322,36 @@ pub fn lookup_vtable(vcx: &VtableContext,
vcx.infcx.ty_to_str(for_ty),
tys_to_str(vcx.tcx(), substs.tps));
// Next, we unify trait_ty -- the type
// that we want to cast to -- with of_ty
// Next, we unify trait_ref -- the type
// that we want to cast to -- with of_trait_ref
// -- the trait that im implements. At
// this point, we require that they be
// unifiable with each other -- that's
// what relate_trait_tys does.
// what relate_trait_refs does.
//
// For example, in the above example,
// of_ty would be some_trait<T>, so we
// would be unifying trait_ty<U> (for some
// of_trait_ref would be some_trait<T>, so we
// would be unifying trait_ref<U> (for some
// value of U) with some_trait<T>. This
// would fail if T and U weren't
// compatible.
debug!("(checking vtable) @2 relating trait \
ty %s to of_ty %s",
vcx.infcx.ty_to_str(trait_ty),
vcx.infcx.ty_to_str(*of_ty));
let of_ty = ty::subst(tcx, &substs, *of_ty);
relate_trait_tys(vcx, location_info, trait_ty,
of_ty);
ty %s to of_trait_ref %s",
vcx.infcx.trait_ref_to_str(trait_ref),
vcx.infcx.trait_ref_to_str(of_trait_ref));
// Recall that trait_ty -- the trait type
let of_trait_ref =
ty::subst_in_trait_ref(tcx, &substs, of_trait_ref);
relate_trait_refs(
vcx, location_info,
&of_trait_ref, trait_ref);
// Recall that trait_ref -- the trait type
// we're casting to -- is the trait with
// id trait_id applied to the substs
// trait_substs. Now we extract out the
// types themselves from trait_substs.
let trait_tps = /*bad*/copy trait_substs.tps;
debug!("Casting to a trait ty whose substs \
(trait_tps) are %s",
tys_to_str(vcx.tcx(), trait_tps));
// id trait_ref.def_id applied to the substs
// trait_ref.substs. Now we extract out the
// types themselves from trait_ref.substs.
// Recall that substs is the impl self
// type's list of substitutions. That is,
@ -362,7 +363,7 @@ pub fn lookup_vtable(vcx: &VtableContext,
let substs_f = match fixup_substs(vcx,
location_info,
trait_id,
trait_ref.def_id,
substs,
is_early) {
Some(ref substs) => (/*bad*/copy *substs),
@ -377,7 +378,7 @@ pub fn lookup_vtable(vcx: &VtableContext,
they will be unified with the bounds for \
the target ty, %s",
tys_to_str(vcx.tcx(), substs_f.tps),
tys_to_str(vcx.tcx(), trait_tps));
vcx.infcx.trait_ref_to_str(trait_ref));
// Next, we unify the fixed-up
// substitutions for the impl self ty with
@ -386,14 +387,13 @@ pub fn lookup_vtable(vcx: &VtableContext,
// to. connect_trait_tps requires these
// lists of types to unify pairwise.
let im_bs = ty::lookup_item_type(tcx,
im.did).bounds;
let im_bs =
ty::lookup_item_type(tcx, im.did).generics.bounds;
connect_trait_tps(vcx,
location_info,
/*bad*/copy substs_f.tps,
trait_tps,
im.did,
trait_store);
&substs_f,
trait_ref,
im.did);
let subres = lookup_vtables(
vcx, location_info, im_bs, &substs_f,
is_early);
@ -430,10 +430,10 @@ pub fn lookup_vtable(vcx: &VtableContext,
return None;
}
pub fn fixup_ty(vcx: &VtableContext,
location_info: &LocationInfo,
ty: ty::t,
is_early: bool) -> Option<ty::t> {
fn fixup_ty(vcx: &VtableContext,
location_info: &LocationInfo,
ty: ty::t,
is_early: bool) -> Option<ty::t> {
let tcx = vcx.tcx();
match resolve_type(vcx.infcx, ty, resolve_and_force_all_but_regions) {
Ok(new_type) => Some(new_type),
@ -450,45 +450,23 @@ pub fn fixup_ty(vcx: &VtableContext,
}
}
// Version of demand::suptype() that takes a vtable context instead of a
// function context.
pub fn demand_suptype(vcx: &VtableContext, sp: span, e: ty::t, a: ty::t) {
// NB: Order of actual, expected is reversed.
match infer::mk_subty(vcx.infcx, false, sp, a, e) {
result::Ok(()) => {} // Ok.
result::Err(ref err) => {
vcx.infcx.report_mismatched_types(sp, e, a, err);
}
}
}
pub fn connect_trait_tps(vcx: &VtableContext,
location_info: &LocationInfo,
impl_tys: ~[ty::t],
trait_tys: ~[ty::t],
impl_did: ast::def_id,
store: ty::TraitStore) {
fn connect_trait_tps(vcx: &VtableContext,
location_info: &LocationInfo,
impl_substs: &ty::substs,
trait_ref: &ty::TraitRef,
impl_did: ast::def_id)
{
let tcx = vcx.tcx();
// XXX: This should work for multiple traits.
let ity = ty::impl_traits(tcx, impl_did, store)[0];
let trait_ty = ty::subst_tps(tcx, impl_tys, None, ity);
debug!("(connect trait tps) trait type is %?, impl did is %?",
ty::get(trait_ty).sty, impl_did);
match ty::get(trait_ty).sty {
ty::ty_trait(_, ref substs, _) => {
for vec::each2((*substs).tps, trait_tys) |a, b| {
demand_suptype(vcx, location_info.span, *a, *b);
}
}
_ => tcx.sess.impossible_case(location_info.span, "connect_trait_tps: \
don't know how to handle a non-trait ty")
}
let impl_trait_ref = ty::impl_trait_refs(tcx, impl_did)[0];
let impl_trait_ref = ty::subst_in_trait_ref(tcx, impl_substs, impl_trait_ref);
relate_trait_refs(vcx, location_info, trait_ref, &impl_trait_ref);
}
pub fn insert_vtables(fcx: @mut FnCtxt,
callee_id: ast::node_id,
vtables: vtable_res) {
fn insert_vtables(fcx: @mut FnCtxt,
callee_id: ast::node_id,
vtables: vtable_res) {
debug!("insert_vtables(callee_id=%d, vtables=%?)",
callee_id, vtables.map(|v| v.to_str(fcx.tcx())));
fcx.inh.vtable_map.insert(callee_id, vtables);
@ -517,15 +495,15 @@ pub fn early_resolve_expr(ex: @ast::expr,
let item_ty = ty::lookup_item_type(cx.tcx, did);
debug!("early resolve expr: def %? %?, %?, %?", ex.id, did, def,
fcx.infcx().ty_to_str(item_ty.ty));
if has_trait_bounds(/*bad*/copy *item_ty.bounds) {
for item_ty.bounds.each |bounds| {
if has_trait_bounds(/*bad*/copy *item_ty.generics.bounds) {
for item_ty.generics.bounds.each |bounds| {
debug!("early_resolve_expr: looking up vtables for bound \
%s",
ty::param_bounds_to_str(fcx.tcx(), *bounds));
}
let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() };
let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex),
item_ty.bounds, substs, is_early);
item_ty.generics.bounds, substs, is_early);
if !is_early {
insert_vtables(fcx, ex.id, vtbls);
}
@ -564,7 +542,7 @@ pub fn early_resolve_expr(ex: @ast::expr,
ast::expr_cast(src, _) => {
let target_ty = fcx.expr_ty(ex);
match ty::get(target_ty).sty {
ty::ty_trait(_, _, store) => {
ty::ty_trait(target_def_id, ref target_substs, store) => {
// Look up vtables for the type we're casting to,
// passing in the source and target type. The source
// must be a pointer type suitable to the object sigil,
@ -573,7 +551,6 @@ pub fn early_resolve_expr(ex: @ast::expr,
fcx.expr_ty(src));
match (&ty::get(ty).sty, store) {
(&ty::ty_box(mt), ty::BoxTraitStore) |
// XXX: Bare trait store is deprecated.
(&ty::ty_uniq(mt), ty::UniqTraitStore) |
(&ty::ty_rptr(_, mt), ty::RegionTraitStore(*)) => {
let location_info =
@ -582,11 +559,15 @@ pub fn early_resolve_expr(ex: @ast::expr,
ccx: fcx.ccx,
infcx: fcx.infcx()
};
let target_trait_ref = ty::TraitRef {
def_id: target_def_id,
substs: copy *target_substs
};
let vtable_opt =
lookup_vtable(&vcx,
location_info,
mt.ty,
target_ty,
&target_trait_ref,
is_early);
match vtable_opt {
Some(vtable) => {
@ -622,11 +603,12 @@ pub fn early_resolve_expr(ex: @ast::expr,
}
}
(_, ty::BareTraitStore) => {
(_, ty::UniqTraitStore) => {
fcx.ccx.tcx.sess.span_err(
ex.span,
~"a sigil (`@`, `~`, or `&`) must be specified \
when casting to a trait");
fmt!("can only cast an ~-pointer \
to a ~-object, not a %s",
ty::ty_sort_str(fcx.tcx(), ty)));
}
(_, ty::BoxTraitStore) => {
@ -637,14 +619,6 @@ pub fn early_resolve_expr(ex: @ast::expr,
ty::ty_sort_str(fcx.tcx(), ty)));
}
(_, ty::UniqTraitStore) => {
fcx.ccx.tcx.sess.span_err(
ex.span,
fmt!("can only cast an ~-pointer \
to a ~-object, not a %s",
ty::ty_sort_str(fcx.tcx(), ty)));
}
(_, ty::RegionTraitStore(_)) => {
fcx.ccx.tcx.sess.span_err(
ex.span,
@ -661,9 +635,9 @@ pub fn early_resolve_expr(ex: @ast::expr,
}
}
pub fn resolve_expr(ex: @ast::expr,
&&fcx: @mut FnCtxt,
v: visit::vt<@mut FnCtxt>) {
fn resolve_expr(ex: @ast::expr,
&&fcx: @mut FnCtxt,
v: visit::vt<@mut FnCtxt>) {
early_resolve_expr(ex, fcx, false);
visit::visit_expr(ex, fcx, v);
}

View file

@ -38,7 +38,7 @@ use middle::typeck::infer::combine::Combine;
use middle::typeck::infer::InferCtxt;
use middle::typeck::infer::{new_infer_ctxt, resolve_ivar};
use middle::typeck::infer::{resolve_nested_tvar, resolve_type};
use syntax::ast::{crate, def_id, def_mod, def_ty};
use syntax::ast::{crate, def_id, def_mod, def_trait};
use syntax::ast::{item, item_impl, item_mod, local_crate, method, trait_ref};
use syntax::ast;
use syntax::ast_map::node_item;
@ -333,10 +333,16 @@ pub impl CoherenceChecker {
let new_id = parse::next_node_id(tcx.sess.parse_sess);
let new_did = local_def(new_id);
let new_method_ty = @ty::method {
def_id: new_did,
..copy *trait_method
};
// XXX: Perform substitutions.
let new_polytype = ty::lookup_item_type(tcx,
trait_method.def_id);
tcx.tcache.insert(new_did, new_polytype);
tcx.methods.insert(new_did, new_method_ty);
// Pair the new synthesized ID up with the
// ID of the method.
@ -352,7 +358,7 @@ pub impl CoherenceChecker {
@ProvidedMethodInfo {
method_info: @MethodInfo {
did: new_did,
n_tps: trait_method.tps.len(),
n_tps: trait_method.generics.bounds.len(),
ident: trait_method.ident,
self_type: trait_method.self_ty
},
@ -498,7 +504,7 @@ pub impl CoherenceChecker {
fn each_provided_trait_method(&self,
trait_did: ast::def_id,
f: &fn(x: &ty::method) -> bool) {
f: &fn(x: @ty::method) -> bool) {
// Make a list of all the names of the provided methods.
// XXX: This is horrible.
let mut provided_method_idents = HashSet::new();
@ -507,7 +513,7 @@ pub impl CoherenceChecker {
provided_method_idents.insert(*ident);
}
for ty::trait_methods(tcx, trait_did).each |method| {
for ty::trait_methods(tcx, trait_did).each |&method| {
if provided_method_idents.contains(&method.ident) {
if !f(method) {
break;
@ -536,10 +542,10 @@ pub impl CoherenceChecker {
-> UniversalQuantificationResult {
// NDM--this span is bogus.
let self_region =
polytype.region_param.map(
polytype.generics.region_param.map(
|_r| self.inference_context.next_region_var_nb(dummy_sp()));
let bounds_count = polytype.bounds.len();
let bounds_count = polytype.generics.bounds.len();
let type_parameters =
self.inference_context.next_ty_vars(bounds_count);
@ -559,7 +565,7 @@ pub impl CoherenceChecker {
UniversalQuantificationResult {
monotype: monotype,
type_variables: type_parameters,
bounds: polytype.bounds
bounds: polytype.generics.bounds
}
}
@ -858,17 +864,8 @@ pub impl CoherenceChecker {
}
// Record all the trait methods.
for associated_traits.each |trait_type| {
match get(*trait_type).sty {
ty_trait(trait_id, _, _) => {
self.add_trait_method(trait_id, *implementation);
}
_ => {
self.crate_context.tcx.sess.bug(~"trait type \
returned is not a \
trait");
}
}
for associated_traits.each |trait_ref| {
self.add_trait_method(trait_ref.def_id, *implementation);
}
// Add the implementation to the mapping from
@ -917,7 +914,7 @@ pub impl CoherenceChecker {
@ProvidedMethodInfo {
method_info: @MethodInfo {
did: new_did,
n_tps: trait_method_info.ty.tps.len(),
n_tps: trait_method_info.ty.generics.bounds.len(),
ident: trait_method_info.ty.ident,
self_type: trait_method_info.ty.self_ty
},
@ -947,16 +944,8 @@ pub impl CoherenceChecker {
crate_store,
def_id);
}
dl_def(def_ty(def_id)) => {
let tcx = self.crate_context.tcx;
let polytype = csearch::get_type(tcx, def_id);
match ty::get(polytype.ty).sty {
ty::ty_trait(*) => {
self.add_default_methods_for_external_trait(
def_id);
}
_ => {}
}
dl_def(def_trait(def_id)) => {
self.add_default_methods_for_external_trait(def_id);
}
dl_def(_) | dl_impl(_) | dl_field => {
// Skip this.

View file

@ -33,8 +33,7 @@ are represented as `ty_param()` instances.
use core::prelude::*;
use metadata::csearch;
use middle::ty::InstantiatedTraitRef;
use middle::ty::{substs, ty_param_bounds_and_ty, ty_param_substs_and_ty};
use middle::ty::{substs, ty_param_bounds_and_ty};
use middle::ty;
use middle::typeck::astconv::{AstConv, ty_of_arg};
use middle::typeck::astconv::{ast_ty_to_ty};
@ -42,8 +41,7 @@ use middle::typeck::astconv;
use middle::typeck::infer;
use middle::typeck::rscope::*;
use middle::typeck::rscope;
use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx,
write_tpt_to_tcx};
use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
use util::common::{indenter, pluralize};
use util::ppaux;
@ -53,7 +51,6 @@ use syntax::ast::{RegionTyParamBound, TraitTyParamBound};
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util::{local_def, split_trait_methods};
use syntax::ast_util::{trait_method_to_ty_method};
use syntax::ast_util;
use syntax::codemap::span;
use syntax::codemap;
@ -84,12 +81,10 @@ pub fn collect_item_types(ccx: @mut CrateCtxt, crate: @ast::crate) {
match intrinsic_item.node {
ast::item_trait(*) => {
let ty = ty::mk_trait(ccx.tcx,
def_id,
substs,
ty::BareTraitStore);
ccx.tcx.intrinsic_defs.insert
(intrinsic_item.ident, (def_id, ty));
let tref = @ty::TraitRef {def_id: def_id,
substs: substs};
ccx.tcx.intrinsic_traits.insert
(intrinsic_item.ident, tref);
}
ast::item_enum(*) => {
@ -153,6 +148,10 @@ impl AstConv for CrateCtxt {
}
}
fn get_trait_def(&self, id: ast::def_id) -> @ty::TraitDef {
get_trait_def(self, id)
}
fn ty_infer(&self, span: span) -> ty::t {
self.tcx.sess.span_bug(span,
~"found `ty_infer` in unexpected place");
@ -187,8 +186,7 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
ast::struct_variant_kind(struct_def) => {
let tpt = ty_param_bounds_and_ty {
bounds: ty_param_bounds(ccx, generics),
region_param: rp,
generics: ty_generics(ccx, rp, generics),
ty: enum_ty
};
@ -209,8 +207,7 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
None => {}
Some(result_ty) => {
let tpt = ty_param_bounds_and_ty {
bounds: ty_param_bounds(ccx, generics),
region_param: rp,
generics: ty_generics(ccx, rp, generics),
ty: result_ty
};
tcx.tcache.insert(local_def(variant.node.id), tpt);
@ -221,23 +218,62 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
}
pub fn ensure_trait_methods(ccx: &CrateCtxt,
id: ast::node_id,
trait_ty: ty::t) {
fn store_methods<T>(ccx: &CrateCtxt,
id: ast::node_id,
stuff: &[T],
f: &fn(v: &T) -> ty::method) {
ty::store_trait_methods(ccx.tcx, id, @stuff.map(f));
trait_id: ast::node_id)
{
let tcx = ccx.tcx;
let region_paramd = tcx.region_paramd_items.find(&trait_id).map(|&x| *x);
match *tcx.items.get(&trait_id) {
ast_map::node_item(@ast::item {
node: ast::item_trait(ref generics, _, ref ms),
_
}, _) => {
let trait_ty_generics = ty_generics(ccx, region_paramd, generics);
// For each method, construct a suitable ty::method and
// store it into the `tcx.methods` table:
for ms.each |m| {
let ty_method = @match m {
&ast::required(ref m) => {
ty_method_of_trait_method(
ccx, trait_id, region_paramd, generics,
&m.id, &m.ident, &m.self_ty,
&m.generics, &m.purity, &m.decl)
}
&ast::provided(ref m) => {
ty_method_of_trait_method(
ccx, trait_id, region_paramd, generics,
&m.id, &m.ident, &m.self_ty,
&m.generics, &m.purity, &m.decl)
}
};
if ty_method.self_ty == ast::sty_static {
make_static_method_ty(ccx, trait_id, ty_method,
&trait_ty_generics);
}
tcx.methods.insert(ty_method.def_id, ty_method);
}
// Add an entry mapping
let method_def_ids = @ms.map(|m| {
match m {
&ast::required(ref ty_method) => local_def(ty_method.id),
&ast::provided(ref method) => local_def(method.id)
}
});
let trait_def_id = local_def(trait_id);
tcx.trait_method_def_ids.insert(trait_def_id, method_def_ids);
}
_ => { /* Ignore things that aren't traits */ }
}
fn make_static_method_ty(ccx: &CrateCtxt,
am: &ast::ty_method,
rp: Option<ty::region_variance>,
m: ty::method,
// Take this as an argument b/c we may check
// the impl before the trait.
trait_ty: ty::t,
trait_bounds: @~[ty::param_bounds]) {
trait_id: ast::node_id,
m: &ty::method,
trait_ty_generics: &ty::Generics) {
// We need to create a typaram that replaces self. This param goes
// *in between* the typarams from the trait and those from the
// method (since its bound can depend on the trait? or
@ -248,12 +284,13 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
let dummy_defid = ast::def_id {crate: 0, node: 0};
let non_shifted_trait_tps = do vec::from_fn(trait_bounds.len()) |i| {
let num_trait_bounds = trait_ty_generics.bounds.len();
let non_shifted_trait_tps = do vec::from_fn(num_trait_bounds) |i| {
ty::mk_param(ccx.tcx, i, dummy_defid)
};
let self_param = ty::mk_param(ccx.tcx, trait_bounds.len(),
let self_param = ty::mk_param(ccx.tcx, num_trait_bounds,
dummy_defid);
let shifted_method_tps = do vec::from_fn(m.tps.len()) |i| {
let shifted_method_tps = do vec::from_fn(m.generics.bounds.len()) |i| {
ty::mk_param(ccx.tcx, i + 1, dummy_defid)
};
@ -265,50 +302,48 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
let ty = ty::subst(ccx.tcx,
&substs,
ty::mk_bare_fn(ccx.tcx, copy m.fty));
let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]]
+ *m.tps);
ccx.tcx.tcache.insert(local_def(am.id),
let trait_def = get_trait_def(ccx, local_def(trait_id));
let trait_ref = trait_def.trait_ref;
let mut new_bounds = ~[];
new_bounds.push_all(*trait_ty_generics.bounds);
new_bounds.push(@~[ty::bound_trait(trait_ref)]);
new_bounds.push_all(*m.generics.bounds);
ccx.tcx.tcache.insert(m.def_id,
ty_param_bounds_and_ty {
bounds: bounds,
region_param: rp,
ty: ty});
generics: ty::Generics {
bounds: @new_bounds,
region_param: trait_ty_generics.region_param
},
ty: ty
});
}
let tcx = ccx.tcx;
let region_paramd = tcx.region_paramd_items.find(&id).map_consume(|x| *x);
match *tcx.items.get(&id) {
ast_map::node_item(@ast::item {
node: ast::item_trait(ref generics, _, ref ms),
_
}, _) => {
store_methods::<ast::trait_method>(ccx, id, *ms, |m| {
let def_id;
match *m {
ast::required(ref ty_method) => {
def_id = local_def((*ty_method).id)
}
ast::provided(method) => def_id = local_def(method.id)
}
let trait_bounds = ty_param_bounds(ccx, generics);
let ty_m = trait_method_to_ty_method(m);
let method_ty = ty_of_ty_method(
ccx,
&ty_m,
region_paramd,
def_id,
generics
);
if ty_m.self_ty.node == ast::sty_static {
make_static_method_ty(ccx, &ty_m, region_paramd,
method_ty, trait_ty,
trait_bounds);
}
method_ty
});
}
_ => { /* Ignore things that aren't traits */ }
fn ty_method_of_trait_method(self: &CrateCtxt,
trait_id: ast::node_id,
trait_rp: Option<ty::region_variance>,
trait_generics: &ast::Generics,
m_id: &ast::node_id,
m_ident: &ast::ident,
m_self_ty: &ast::self_ty,
m_generics: &ast::Generics,
m_purity: &ast::purity,
m_decl: &ast::fn_decl) -> ty::method
{
let trait_self_ty = ty::mk_self(self.tcx, local_def(trait_id));
let rscope = MethodRscope::new(m_self_ty.node, trait_rp, trait_generics);
let (transformed_self_ty, fty) =
astconv::ty_of_method(self, &rscope, *m_purity, &m_generics.lifetimes,
trait_self_ty, *m_self_ty, m_decl);
ty::method {
ident: *m_ident,
generics: ty_generics(self, None, m_generics),
transformed_self_ty: transformed_self_ty,
fty: fty,
self_ty: m_self_ty.node,
// assume public, because this is only invoked on trait methods
vis: ast::public,
def_id: local_def(*m_id)
}
}
}
@ -316,25 +351,28 @@ pub fn ensure_supertraits(ccx: &CrateCtxt,
id: ast::node_id,
sp: codemap::span,
rp: Option<ty::region_variance>,
trait_refs: &[@ast::trait_ref],
generics: &ast::Generics) {
ast_trait_refs: &[@ast::trait_ref],
generics: &ast::Generics)
{
let tcx = ccx.tcx;
if tcx.supertraits.contains_key(&local_def(id)) { return; }
let mut instantiated = ~[];
for trait_refs.each |trait_ref| {
let (did, tpt) = instantiate_trait_ref(ccx, *trait_ref, rp, generics);
if instantiated.any(|other_trait: &InstantiatedTraitRef|
{ other_trait.def_id == did }) {
let mut ty_trait_refs: ~[@ty::TraitRef] = ~[];
for ast_trait_refs.each |&ast_trait_ref| {
let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, rp, generics);
// FIXME(#5527) Could have same trait multiple times
if ty_trait_refs.any(|other_trait| other_trait.def_id == trait_ref.def_id) {
// This means a trait inherited from the same supertrait more
// than once.
tcx.sess.span_err(sp, ~"Duplicate supertrait in trait \
declaration");
return;
break;
} else {
ty_trait_refs.push(trait_ref);
}
instantiated.push(InstantiatedTraitRef { def_id: did, tpt: tpt });
}
tcx.supertraits.insert(local_def(id), @instantiated);
tcx.supertraits.insert(local_def(id), @ty_trait_refs);
}
/**
@ -388,15 +426,15 @@ pub fn compare_impl_method(tcx: ty::ctxt,
}
}
if impl_m.tps.len() != trait_m.tps.len() {
if impl_m.generics.bounds.len() != trait_m.generics.bounds.len() {
tcx.sess.span_err(
cm.span,
fmt!("method `%s` has %u type %s, but its trait \
declaration has %u type %s",
*tcx.sess.str_of(trait_m.ident), impl_m.tps.len(),
pluralize(impl_m.tps.len(), ~"parameter"),
trait_m.tps.len(),
pluralize(trait_m.tps.len(), ~"parameter")));
*tcx.sess.str_of(trait_m.ident), impl_m.generics.bounds.len(),
pluralize(impl_m.generics.bounds.len(), ~"parameter"),
trait_m.generics.bounds.len(),
pluralize(trait_m.generics.bounds.len(), ~"parameter")));
return;
}
@ -414,9 +452,9 @@ pub fn compare_impl_method(tcx: ty::ctxt,
// FIXME(#2687)---we should be checking that the bounds of the
// trait imply the bounds of the subtype, but it appears
// we are...not checking this.
for trait_m.tps.eachi() |i, trait_param_bounds| {
for trait_m.generics.bounds.eachi() |i, trait_param_bounds| {
// For each of the corresponding impl ty param's bounds...
let impl_param_bounds = impl_m.tps[i];
let impl_param_bounds = impl_m.generics.bounds[i];
// Make sure the bounds lists have the same length
// Would be nice to use the ty param names in the error message,
// but we don't have easy access to them here
@ -456,7 +494,7 @@ pub fn compare_impl_method(tcx: ty::ctxt,
};
debug!("impl_fty: %s", ppaux::ty_to_str(tcx, impl_fty));
let trait_fty = {
let dummy_tps = do vec::from_fn((*trait_m.tps).len()) |i| {
let dummy_tps = do vec::from_fn(trait_m.generics.bounds.len()) |i| {
// hack: we don't know the def id of the impl tp, but it
// is not important for unification
ty::mk_param(tcx, i + impl_tps, ast::def_id {crate: 0, node: 0})
@ -501,40 +539,26 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt,
rp: Option<ty::region_variance>,
selfty: ty::t,
a_trait_ty: @ast::trait_ref,
impl_ms: &[ConvertedMethod]) {
impl_ms: &[ConvertedMethod])
{
let tcx = ccx.tcx;
let (did, tpt) = instantiate_trait_ref(ccx, a_trait_ty, rp, generics);
let trait_ref = instantiate_trait_ref(ccx, a_trait_ty, rp, generics);
if did.crate == ast::local_crate {
// NB: This is subtle. We need to do this on the type of the trait
// item *itself*, not on the type that includes the parameter
// substitutions provided by the programmer at this particular
// trait ref. Otherwise, we will potentially overwrite the types of
// the methods within the trait with bogus results. (See issue #3903.)
match tcx.items.find(&did.node) {
Some(&ast_map::node_item(item, _)) => {
let tpt = ty_of_item(ccx, item);
ensure_trait_methods(ccx, did.node, tpt.ty);
}
_ => {
tcx.sess.bug(~"trait ref didn't resolve to trait");
}
}
if trait_ref.def_id.crate == ast::local_crate {
ensure_trait_methods(ccx, trait_ref.def_id.node);
}
// Check that each method we impl is a method on the trait
// Trait methods we don't implement must be default methods, but if not
// we'll catch it in coherence
let trait_ms = ty::trait_methods(tcx, did);
let trait_ms = ty::trait_methods(tcx, trait_ref.def_id);
for impl_ms.each |impl_m| {
match trait_ms.find(|trait_m| trait_m.ident == impl_m.mty.ident) {
Some(ref trait_m) => {
Some(trait_m) => {
let num_impl_tps = generics.ty_params.len();
compare_impl_method(
ccx.tcx, num_impl_tps, impl_m, trait_m,
&tpt.substs, selfty);
&trait_ref.substs, selfty);
}
None => {
// This method is not part of the trait
@ -560,14 +584,16 @@ pub fn convert_field(ccx: &CrateCtxt,
/* add the field to the tcache */
ccx.tcx.tcache.insert(local_def(v.node.id),
ty::ty_param_bounds_and_ty {
bounds: bounds,
region_param: rp,
generics: ty::Generics {
bounds: bounds,
region_param: rp
},
ty: tt
});
}
pub struct ConvertedMethod {
mty: ty::method,
mty: @ty::method,
id: ast::node_id,
span: span,
body_id: ast::node_id
@ -575,29 +601,74 @@ pub struct ConvertedMethod {
pub fn convert_methods(ccx: &CrateCtxt,
ms: &[@ast::method],
rp: Option<ty::region_variance>,
rcvr_bounds: @~[ty::param_bounds],
rcvr_generics: &ast::Generics)
-> ~[ConvertedMethod] {
untransformed_rcvr_ty: ty::t,
rcvr_ty_generics: &ty::Generics,
rcvr_ast_generics: &ast::Generics,
rcvr_visibility: ast::visibility)
-> ~[ConvertedMethod]
{
let tcx = ccx.tcx;
do vec::map(ms) |m| {
let bounds = ty_param_bounds(ccx, &m.generics);
let mty = ty_of_method(ccx, *m, rp, rcvr_generics, &m.generics);
let fty = ty::mk_bare_fn(tcx, copy mty.fty);
return vec::map(ms, |m| {
let m_ty_generics =
ty_generics(ccx, rcvr_ty_generics.region_param, &m.generics);
let mty =
@ty_of_method(ccx, *m, rcvr_ty_generics.region_param,
untransformed_rcvr_ty,
rcvr_ast_generics, rcvr_visibility,
&m.generics);
let fty =
ty::mk_bare_fn(tcx, copy mty.fty);
tcx.tcache.insert(
local_def(m.id),
// n.b.: the type of a method is parameterized by both
// the tps on the receiver and those on the method itself
ty_param_bounds_and_ty {
bounds: @(vec::append(/*bad*/copy *rcvr_bounds, *bounds)),
region_param: rp,
generics: ty::Generics {
bounds: @(vec::append(copy *rcvr_ty_generics.bounds,
*m_ty_generics.bounds)),
region_param: rcvr_ty_generics.region_param
},
ty: fty
});
write_ty_to_tcx(tcx, m.id, fty);
tcx.methods.insert(mty.def_id, mty);
ConvertedMethod {mty: mty, id: m.id,
span: m.span, body_id: m.body.node.id}
});
fn ty_of_method(ccx: &CrateCtxt,
m: @ast::method,
rp: Option<ty::region_variance>,
untransformed_rcvr_ty: ty::t,
rcvr_generics: &ast::Generics,
rcvr_visibility: ast::visibility,
method_generics: &ast::Generics) -> ty::method
{
let rscope = MethodRscope::new(m.self_ty.node,
rp,
rcvr_generics);
let (transformed_self_ty, fty) =
astconv::ty_of_method(ccx, &rscope, m.purity,
&method_generics.lifetimes,
untransformed_rcvr_ty,
m.self_ty, &m.decl);
// if the method specifies a visibility, use that, otherwise
// inherit the visibility from the impl (so `foo` in `pub impl
// { fn foo(); }` is public, but private in `priv impl { fn
// foo(); }`).
let method_vis = m.vis.inherit_from(rcvr_visibility);
ty::method {
ident: m.ident,
generics: ty_generics(ccx, None, &m.generics),
transformed_self_ty: transformed_self_ty,
fty: fty,
self_ty: m.self_ty.node,
vis: method_vis,
def_id: local_def(m.id)
}
}
}
@ -633,36 +704,49 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
generics,
rp);
}
ast::item_impl(ref generics, trait_ref, selfty, ref ms) => {
let i_bounds = ty_param_bounds(ccx, generics);
ast::item_impl(ref generics, opt_trait_ref, selfty, ref ms) => {
let i_ty_generics = ty_generics(ccx, rp, generics);
let region_parameterization =
RegionParameterization::from_variance_and_generics(rp, generics);
let selfty = ccx.to_ty(&type_rscope(region_parameterization), selfty);
write_ty_to_tcx(tcx, it.id, selfty);
tcx.tcache.insert(local_def(it.id),
ty_param_bounds_and_ty {
bounds: i_bounds,
region_param: rp,
ty: selfty});
generics: i_ty_generics,
ty: selfty});
// XXX: Bad copy of `ms` below.
let cms = convert_methods(ccx, *ms, rp, i_bounds, generics);
for trait_ref.each |t| {
// If there is a trait reference, treat the methods as always public.
// This is to work around some incorrect behavior in privacy checking:
// when the method belongs to a trait, it should acquire the privacy
// from the trait, not the impl. Forcing the visibility to be public
// makes things sorta work.
let parent_visibility = if opt_trait_ref.is_some() {
ast::public
} else {
it.vis
};
let cms = convert_methods(ccx, *ms, selfty,
&i_ty_generics, generics,
parent_visibility);
for opt_trait_ref.each |t| {
check_methods_against_trait(ccx, generics, rp, selfty, *t, cms);
}
}
ast::item_trait(ref generics, ref supertraits, ref trait_methods) => {
let tpt = ty_of_item(ccx, it);
debug!("item_trait(it.id=%d, tpt.ty=%s)",
it.id, ppaux::ty_to_str(tcx, tpt.ty));
write_ty_to_tcx(tcx, it.id, tpt.ty);
ensure_trait_methods(ccx, it.id, tpt.ty);
ensure_supertraits(ccx, it.id, it.span, rp, *supertraits, generics);
let trait_def = trait_def_of_item(ccx, it);
tcx.trait_defs.insert(local_def(it.id), trait_def);
ensure_trait_methods(ccx, it.id);
ensure_supertraits(ccx, it.id, it.span, rp, *supertraits, generics);
let (_, provided_methods) =
split_trait_methods(*trait_methods);
let (bounds, _) = mk_substs(ccx, generics, rp);
let _ = convert_methods(ccx, provided_methods, rp, bounds, generics);
let (_, provided_methods) =
split_trait_methods(*trait_methods);
let (ty_generics, _) = mk_substs(ccx, generics, rp);
let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
let _ = convert_methods(ccx, provided_methods,
untransformed_rcvr_ty,
&ty_generics, generics,
it.vis);
}
ast::item_struct(struct_def, ref generics) => {
ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
@ -714,14 +798,16 @@ pub fn convert_struct(ccx: &CrateCtxt,
write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
tcx.tcache.insert(local_def(dtor.node.id),
ty_param_bounds_and_ty {
bounds: tpt.bounds,
region_param: rp,
ty: t_dtor});
generics: ty::Generics {
bounds: tpt.generics.bounds,
region_param: rp
},
ty: t_dtor});
};
// Write the type of each of the members
for struct_def.fields.each |f| {
convert_field(ccx, rp, tpt.bounds, *f, generics);
convert_field(ccx, rp, tpt.generics.bounds, *f, generics);
}
let (_, substs) = mk_substs(ccx, generics, rp);
let selfty = ty::mk_struct(tcx, local_def(id), substs);
@ -744,8 +830,7 @@ pub fn convert_struct(ccx: &CrateCtxt,
let ctor_fn_ty = ty::mk_ctor_fn(tcx, inputs, selfty);
write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
tcx.tcache.insert(local_def(ctor_id), ty_param_bounds_and_ty {
bounds: tpt.bounds,
region_param: tpt.region_param,
generics: tpt.generics,
ty: ctor_fn_ty
});
}
@ -762,85 +847,75 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: @ast::foreign_item) {
ccx.tcx.tcache.insert(local_def(i.id), tpt);
}
pub fn ty_of_method(ccx: &CrateCtxt,
m: @ast::method,
rp: Option<ty::region_variance>,
rcvr_generics: &ast::Generics,
method_generics: &ast::Generics)
-> ty::method {
let rscope = MethodRscope::new(m.self_ty.node,
rp,
rcvr_generics);
ty::method {
ident: m.ident,
tps: ty_param_bounds(ccx, &m.generics),
fty: astconv::ty_of_bare_fn(ccx,
&rscope,
m.purity,
AbiSet::Rust(),
&method_generics.lifetimes,
&m.decl),
self_ty: m.self_ty.node,
vis: m.vis,
def_id: local_def(m.id)
}
}
pub fn ty_of_ty_method(self: &CrateCtxt,
m: &ast::ty_method,
rp: Option<ty::region_variance>,
id: ast::def_id,
generics: &ast::Generics)
-> ty::method {
let rscope = MethodRscope::new(m.self_ty.node, rp, generics);
ty::method {
ident: m.ident,
tps: ty_param_bounds(self, &m.generics),
fty: astconv::ty_of_bare_fn(self,
&rscope,
m.purity,
AbiSet::Rust(),
&m.generics.lifetimes,
&m.decl),
// assume public, because this is only invoked on trait methods
self_ty: m.self_ty.node,
vis: ast::public,
def_id: id
}
}
/*
Instantiates the path for the given trait reference, assuming that
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.
*/
pub fn instantiate_trait_ref(ccx: &CrateCtxt,
t: @ast::trait_ref,
ast_trait_ref: @ast::trait_ref,
rp: Option<ty::region_variance>,
generics: &ast::Generics)
-> (ast::def_id, ty_param_substs_and_ty) {
let sp = t.path.span, err = ~"can only implement trait types",
sess = ccx.tcx.sess;
generics: &ast::Generics) -> @ty::TraitRef
{
/*!
* Instantiates the path for the given trait reference, assuming that
* 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.
*/
let rp = RegionParameterization::from_variance_and_generics(rp, generics);
let rscope = type_rscope(rp);
match lookup_def_tcx(ccx.tcx, t.path.span, t.ref_id) {
ast::def_ty(t_id) => {
let tpt = astconv::ast_path_to_ty(ccx, &rscope, t_id, t.path);
write_tpt_to_tcx(ccx.tcx, t.ref_id, &tpt);
match ty::get(tpt.ty).sty {
ty::ty_trait(*) => {
(t_id, tpt)
}
_ => sess.span_fatal(sp, err),
match lookup_def_tcx(ccx.tcx, ast_trait_ref.path.span, ast_trait_ref.ref_id) {
ast::def_trait(trait_did) => {
let trait_ref =
astconv::ast_path_to_trait_ref(
ccx, &rscope, trait_did, ast_trait_ref.path);
ccx.tcx.trait_refs.insert(
ast_trait_ref.ref_id, trait_ref);
return trait_ref;
}
_ => {
ccx.tcx.sess.span_fatal(
ast_trait_ref.path.span,
fmt!("%s is not a trait",
path_to_str(ast_trait_ref.path,
ccx.tcx.sess.intr())));
}
}
}
fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::def_id) -> @ty::TraitDef {
if trait_id.crate != ast::local_crate {
ty::lookup_trait_def(ccx.tcx, trait_id)
} else {
match ccx.tcx.items.get(&trait_id.node) {
&ast_map::node_item(item, _) => trait_def_of_item(ccx, item),
_ => ccx.tcx.sess.bug(fmt!("get_trait_def(%d): not an item",
trait_id.node))
}
}
}
pub fn trait_def_of_item(ccx: &CrateCtxt, it: @ast::item) -> @ty::TraitDef {
let def_id = local_def(it.id);
let tcx = ccx.tcx;
match tcx.trait_defs.find(&def_id) {
Some(&def) => return def,
_ => {}
}
let rp = tcx.region_paramd_items.find(&it.id).map_consume(|x| *x);
match it.node {
ast::item_trait(ref generics, _, _) => {
let (ty_generics, substs) = mk_substs(ccx, generics, rp);
let trait_ref = @ty::TraitRef {def_id: def_id,
substs: substs};
let trait_def = @ty::TraitDef {generics: ty_generics,
trait_ref: trait_ref};
tcx.trait_defs.insert(def_id, trait_def);
return trait_def;
}
ref s => {
tcx.sess.span_bug(
it.span,
fmt!("trait_def_of_item invoked on %?", s));
}
}
_ => sess.span_fatal(sp, err)
}
}
@ -861,7 +936,8 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
return tpt;
}
ast::item_fn(ref decl, purity, _, ref generics, _) => {
let bounds = ty_param_bounds(ccx, generics);
assert!(rp.is_none());
let ty_generics = ty_generics(ccx, None, generics);
let tofd = astconv::ty_of_bare_fn(ccx,
&empty_rscope,
purity,
@ -869,8 +945,10 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
&generics.lifetimes,
decl);
let tpt = ty_param_bounds_and_ty {
bounds: bounds,
region_param: None,
generics: ty::Generics {
bounds: ty_generics.bounds,
region_param: None
},
ty: ty::mk_bare_fn(ccx.tcx, tofd)
};
debug!("type of %s (id %d) is %s",
@ -901,8 +979,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
}
};
ty_param_bounds_and_ty {
bounds: ty_param_bounds(ccx, generics),
region_param: rp,
generics: ty_generics(ccx, rp, generics),
ty: ty
}
};
@ -912,37 +989,26 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
}
ast::item_enum(_, ref generics) => {
// Create a new generic polytype.
let (bounds, substs) = mk_substs(ccx, generics, rp);
let (ty_generics, substs) = mk_substs(ccx, generics, rp);
let t = ty::mk_enum(tcx, local_def(it.id), substs);
let tpt = ty_param_bounds_and_ty {
bounds: bounds,
region_param: rp,
generics: ty_generics,
ty: t
};
tcx.tcache.insert(local_def(it.id), tpt);
return tpt;
}
ast::item_trait(ref generics, _, _) => {
let (bounds, substs) = mk_substs(ccx, generics, rp);
let t = ty::mk_trait(tcx,
local_def(it.id),
substs,
ty::BareTraitStore);
let tpt = ty_param_bounds_and_ty {
bounds: bounds,
region_param: rp,
ty: t
};
tcx.tcache.insert(local_def(it.id), tpt);
return tpt;
ast::item_trait(*) => {
tcx.sess.span_bug(
it.span,
fmt!("Invoked ty_of_item on trait"));
}
ast::item_struct(_, ref generics) => {
let (bounds, substs) = mk_substs(ccx, generics, rp);
let (ty_generics, substs) = mk_substs(ccx, generics, rp);
let t = ty::mk_struct(tcx, local_def(it.id), substs);
let tpt = ty_param_bounds_and_ty {
bounds: bounds,
region_param: rp,
ty: t
generics: ty_generics,
ty: t
};
tcx.tcache.insert(local_def(it.id), tpt);
return tpt;
@ -964,76 +1030,82 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt, it: @ast::foreign_item)
}
ast::foreign_item_const(t) => {
ty::ty_param_bounds_and_ty {
bounds: @~[],
region_param: None,
generics: ty::Generics {
bounds: @~[],
region_param: None,
},
ty: ast_ty_to_ty(ccx, &empty_rscope, t)
}
}
}
}
// Translate the AST's notion of ty param bounds (which are an enum consisting
// of a newtyped Ty or a region) to ty's notion of ty param bounds, which can
// either be user-defined traits, or one of the four built-in traits (formerly
// known as kinds): Const, Copy, Durable, and Send.
pub fn compute_bounds(ccx: &CrateCtxt,
ast_bounds: @OptVec<ast::TyParamBound>)
-> ty::param_bounds {
@ast_bounds.flat_map_to_vec(|b| {
match b {
&TraitTyParamBound(b) => {
let li = &ccx.tcx.lang_items;
let ity = ast_ty_to_ty(ccx, &empty_rscope, b);
match ty::get(ity).sty {
ty::ty_trait(did, _, _) => {
if did == li.owned_trait() {
~[ty::bound_owned]
} else if did == li.copy_trait() {
~[ty::bound_copy]
} else if did == li.const_trait() {
~[ty::bound_const]
} else if did == li.durable_trait() {
~[ty::bound_durable]
} else {
// Must be a user-defined trait
~[ty::bound_trait(ity)]
}
}
_ => {
ccx.tcx.sess.span_err(
(*b).span, ~"type parameter bounds must be \
trait types");
~[]
}
pub fn ty_generics(ccx: &CrateCtxt,
rp: Option<ty::region_variance>,
generics: &ast::Generics) -> ty::Generics {
return ty::Generics {
region_param: rp,
bounds: @generics.ty_params.map_to_vec(|param| {
match ccx.tcx.ty_param_bounds.find(&param.id) {
Some(&bs) => bs,
None => {
let bounds = compute_bounds(ccx, rp, generics, param.bounds);
ccx.tcx.ty_param_bounds.insert(param.id, bounds);
bounds
}
}
&RegionTyParamBound => ~[ty::bound_durable]
}
})
}
})
};
pub fn ty_param_bounds(ccx: &CrateCtxt,
generics: &ast::Generics)
-> @~[ty::param_bounds] {
@do generics.ty_params.map_to_vec |param| {
match ccx.tcx.ty_param_bounds.find(&param.id) {
Some(&bs) => bs,
None => {
let bounds = compute_bounds(ccx, param.bounds);
ccx.tcx.ty_param_bounds.insert(param.id, bounds);
bounds
}
}
fn compute_bounds(
ccx: &CrateCtxt,
rp: Option<ty::region_variance>,
generics: &ast::Generics,
ast_bounds: @OptVec<ast::TyParamBound>) -> ty::param_bounds
{
/*!
*
* Translate the AST's notion of ty param bounds (which are an
* enum consisting of a newtyped Ty or a region) to ty's
* notion of ty param bounds, which can either be user-defined
* traits, or one of the four built-in traits (formerly known
* as kinds): Const, Copy, Durable, and Send.
*/
@ast_bounds.flat_map_to_vec(|b| {
match b {
&TraitTyParamBound(b) => {
let li = &ccx.tcx.lang_items;
let trait_ref = instantiate_trait_ref(ccx, b, rp, generics);
if trait_ref.def_id == li.owned_trait() {
~[ty::bound_owned]
} else if trait_ref.def_id == li.copy_trait() {
~[ty::bound_copy]
} else if trait_ref.def_id == li.const_trait() {
~[ty::bound_const]
} else if trait_ref.def_id == li.durable_trait() {
~[ty::bound_durable]
} else {
// Must be a user-defined trait
~[ty::bound_trait(trait_ref)]
}
}
&RegionTyParamBound => {
~[ty::bound_durable]
}
}
})
}
}
pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
decl: &ast::fn_decl,
def_id: ast::def_id,
generics: &ast::Generics)
ast_generics: &ast::Generics)
-> ty::ty_param_bounds_and_ty {
let bounds = ty_param_bounds(ccx, generics);
let region_param_names = RegionParamNames::from_generics(generics);
let ty_generics = ty_generics(ccx, None, ast_generics);
let region_param_names = RegionParamNames::from_generics(ast_generics);
let rb = in_binding_rscope(&empty_rscope, region_param_names);
let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, &rb, *a, None) );
let output_ty = ast_ty_to_ty(ccx, &rb, decl.output);
@ -1048,33 +1120,24 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
output: output_ty}
});
let tpt = ty_param_bounds_and_ty {
bounds: bounds,
region_param: None,
generics: ty_generics,
ty: t_fn
};
ccx.tcx.tcache.insert(def_id, tpt);
return tpt;
}
pub fn mk_generics(ccx: &CrateCtxt, generics: &ast::Generics)
-> (@~[ty::param_bounds], ~[ty::t])
{
let mut i = 0u;
let bounds = ty_param_bounds(ccx, generics);
(bounds,
generics.ty_params.map_to_vec(|atp| {
let t = ty::mk_param(ccx.tcx, i, local_def(atp.id));
i += 1u;
t
}))
}
pub fn mk_substs(ccx: &CrateCtxt,
generics: &ast::Generics,
rp: Option<ty::region_variance>)
-> (@~[ty::param_bounds], ty::substs)
ast_generics: &ast::Generics,
rp: Option<ty::region_variance>) -> (ty::Generics, ty::substs)
{
let (bounds, params) = mk_generics(ccx, generics);
let mut i = 0;
let ty_generics = ty_generics(ccx, rp, ast_generics);
let params = ast_generics.ty_params.map_to_vec(|atp| {
let t = ty::mk_param(ccx.tcx, i, local_def(atp.id));
i += 1u;
t
});
let self_r = rscope::bound_self_region(rp);
(bounds, substs { self_r: self_r, self_ty: None, tps: params })
(ty_generics, substs {self_r: self_r, self_ty: None, tps: params})
}

View file

@ -90,7 +90,7 @@ pub trait Combine {
fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]>;
fn self_tys(&self, a: Option<ty::t>, b: Option<ty::t>)
-> cres<Option<ty::t>>;
fn substs(&self, did: ast::def_id, as_: &ty::substs,
fn substs(&self, generics: &ty::Generics, as_: &ty::substs,
bs: &ty::substs) -> cres<ty::substs>;
fn bare_fn_tys(&self, a: &ty::BareFnTy,
b: &ty::BareFnTy) -> cres<ty::BareFnTy>;
@ -114,6 +114,7 @@ pub trait Combine {
a: ty::TraitStore,
b: ty::TraitStore)
-> cres<ty::TraitStore>;
fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef>;
}
pub struct CombineFields {
@ -192,32 +193,31 @@ pub fn eq_opt_regions<C:Combine>(
}
pub fn super_substs<C:Combine>(
self: &C, did: ast::def_id,
self: &C, generics: &ty::Generics,
a: &ty::substs, b: &ty::substs) -> cres<ty::substs> {
fn relate_region_param<C:Combine>(
self: &C,
did: ast::def_id,
generics: &ty::Generics,
a: Option<ty::Region>,
b: Option<ty::Region>)
-> cres<Option<ty::Region>>
{
let polyty = ty::lookup_item_type(self.infcx().tcx, did);
match (polyty.region_param, a, b) {
(None, None, None) => {
match (&generics.region_param, &a, &b) {
(&None, &None, &None) => {
Ok(None)
}
(Some(ty::rv_invariant), Some(a), Some(b)) => {
(&Some(ty::rv_invariant), &Some(a), &Some(b)) => {
do eq_regions(self, a, b).then {
Ok(Some(a))
}
}
(Some(ty::rv_covariant), Some(a), Some(b)) => {
(&Some(ty::rv_covariant), &Some(a), &Some(b)) => {
do self.regions(a, b).chain |r| {
Ok(Some(r))
}
}
(Some(ty::rv_contravariant), Some(a), Some(b)) => {
(&Some(ty::rv_contravariant), &Some(a), &Some(b)) => {
do self.contraregions(a, b).chain |r| {
Ok(Some(r))
}
@ -233,14 +233,14 @@ pub fn super_substs<C:Combine>(
b had opt_region %s with variance %?",
a.inf_str(self.infcx()),
b.inf_str(self.infcx()),
polyty.region_param));
generics.region_param));
}
}
}
do self.tps(a.tps, b.tps).chain |tps| {
do self.self_tys(a.self_ty, b.self_ty).chain |self_ty| {
do relate_region_param(self, did,
do relate_region_param(self, generics,
a.self_r, b.self_r).chain |self_r|
{
Ok(substs {
@ -520,26 +520,29 @@ pub fn super_tys<C:Combine>(
(ty::ty_enum(a_id, ref a_substs),
ty::ty_enum(b_id, ref b_substs))
if a_id == b_id => {
do self.substs(a_id, a_substs, b_substs).chain |substs| {
Ok(ty::mk_enum(tcx, a_id, substs))
}
let type_def = ty::lookup_item_type(tcx, a_id);
do self.substs(&type_def.generics, a_substs, b_substs).chain |substs| {
Ok(ty::mk_enum(tcx, a_id, substs))
}
}
(ty::ty_trait(a_id, ref a_substs, a_store),
ty::ty_trait(b_id, ref b_substs, b_store))
if a_id == b_id => {
do self.substs(a_id, a_substs, b_substs).chain |substs| {
do self.trait_stores(ty::terr_trait, a_store, b_store).chain |s| {
Ok(ty::mk_trait(tcx, a_id, /*bad*/copy substs, s))
}
}
let trait_def = ty::lookup_trait_def(tcx, a_id);
do self.substs(&trait_def.generics, a_substs, b_substs).chain |substs| {
do self.trait_stores(ty::terr_trait, a_store, b_store).chain |s| {
Ok(ty::mk_trait(tcx, a_id, /*bad*/copy substs, s))
}
}
}
(ty::ty_struct(a_id, ref a_substs), ty::ty_struct(b_id, ref b_substs))
if a_id == b_id => {
do self.substs(a_id, a_substs, b_substs).chain |substs| {
Ok(ty::mk_struct(tcx, a_id, substs))
}
let type_def = ty::lookup_item_type(tcx, a_id);
do self.substs(&type_def.generics, a_substs, b_substs).chain |substs| {
Ok(ty::mk_struct(tcx, a_id, substs))
}
}
(ty::ty_box(ref a_mt), ty::ty_box(ref b_mt)) => {
@ -634,3 +637,25 @@ pub fn super_tys<C:Combine>(
Ok(ty::mk_mach_float(tcx, val))
}
}
pub fn super_trait_refs<C:Combine>(
self: &C, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef>
{
// Different traits cannot be related
// - NOTE in the future, expand out subtraits!
if a.def_id != b.def_id {
Err(ty::terr_traits(
expected_found(self, a.def_id, b.def_id)))
} else {
let tcx = self.infcx().tcx;
let trait_def = ty::lookup_trait_def(tcx, a.def_id);
let substs = if_ok!(self.substs(&trait_def.generics, &a.substs, &b.substs));
Ok(ty::TraitRef {
def_id: a.def_id,
substs: substs
})
}
}

View file

@ -299,10 +299,11 @@ impl Combine for Glb {
super_closure_tys(self, a, b)
}
fn substs(&self, did: ast::def_id,
fn substs(&self,
generics: &ty::Generics,
as_: &ty::substs,
bs: &ty::substs) -> cres<ty::substs> {
super_substs(self, did, as_, bs)
super_substs(self, generics, as_, bs)
}
fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> {
@ -313,5 +314,9 @@ impl Combine for Glb {
-> cres<Option<ty::t>> {
super_self_tys(self, a, b)
}
fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef> {
super_trait_refs(self, a, b)
}
}

View file

@ -244,10 +244,11 @@ impl Combine for Lub {
super_args(self, a, b)
}
fn substs(&self, did: ast::def_id,
fn substs(&self,
generics: &ty::Generics,
as_: &ty::substs,
bs: &ty::substs) -> cres<ty::substs> {
super_substs(self, did, as_, bs)
super_substs(self, generics, as_, bs)
}
fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> {
@ -258,4 +259,8 @@ impl Combine for Lub {
-> cres<Option<ty::t>> {
super_self_tys(self, a, b)
}
fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef> {
super_trait_refs(self, a, b)
}
}

View file

@ -265,7 +265,7 @@ use middle::typeck::infer::to_str::InferStr;
use middle::typeck::infer::unify::{ValsAndBindings, Root};
use middle::typeck::isr_alist;
use util::common::indent;
use util::ppaux::{bound_region_to_str, ty_to_str};
use util::ppaux::{bound_region_to_str, ty_to_str, trait_ref_to_str};
use core::cmp::Eq;
use core::result::{Result, Ok, Err};
@ -419,6 +419,23 @@ pub fn mk_eqty(cx: @mut InferCtxt,
}.to_ures()
}
pub fn mk_sub_trait_refs(cx: @mut InferCtxt,
a_is_expected: bool,
span: span,
a: &ty::TraitRef,
b: &ty::TraitRef)
-> ures
{
debug!("mk_sub_trait_refs(%s <: %s)",
a.inf_str(cx), b.inf_str(cx));
do indent {
do cx.commit {
let suber = cx.sub(a_is_expected, span);
suber.trait_refs(a, b)
}
}.to_ures()
}
pub fn mk_coercety(cx: @mut InferCtxt,
a_is_expected: bool,
span: span,
@ -700,6 +717,11 @@ pub impl InferCtxt {
self.resolve_type_vars_if_possible(t))
}
fn trait_ref_to_str(@mut self, t: &ty::TraitRef) -> ~str {
let t = self.resolve_type_vars_in_trait_ref_if_possible(t);
trait_ref_to_str(self.tcx, &t)
}
fn resolve_type_vars_if_possible(@mut self, typ: ty::t) -> ty::t {
match resolve_type(self, typ, resolve_nested_tvar | resolve_ivar) {
result::Ok(new_type) => new_type,
@ -707,6 +729,31 @@ pub impl InferCtxt {
}
}
fn resolve_type_vars_in_trait_ref_if_possible(@mut self,
trait_ref: &ty::TraitRef)
-> ty::TraitRef
{
// make up a dummy type just to reuse/abuse the resolve machinery
let dummy0 = ty::mk_trait(self.tcx,
trait_ref.def_id,
copy trait_ref.substs,
ty::UniqTraitStore);
let dummy1 = self.resolve_type_vars_if_possible(dummy0);
match ty::get(dummy1).sty {
ty::ty_trait(ref def_id, ref substs, _) => {
ty::TraitRef {def_id: *def_id,
substs: copy *substs}
}
_ => {
self.tcx.sess.bug(
fmt!("resolve_type_vars_if_possible() yielded %s \
when supplied with %s",
self.ty_to_str(dummy0),
self.ty_to_str(dummy1)));
}
}
}
fn type_error_message(@mut self, sp: span, mk_msg: &fn(~str) -> ~str,
actual_ty: ty::t, err: Option<&ty::type_err>) {
let actual_ty = self.resolve_type_vars_if_possible(actual_ty);

View file

@ -256,10 +256,11 @@ impl Combine for Sub {
super_args(self, a, b)
}
fn substs(&self, did: ast::def_id,
fn substs(&self,
generics: &ty::Generics,
as_: &ty::substs,
bs: &ty::substs) -> cres<ty::substs> {
super_substs(self, did, as_, bs)
super_substs(self, generics, as_, bs)
}
fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> {
@ -270,5 +271,9 @@ impl Combine for Sub {
-> cres<Option<ty::t>> {
super_self_tys(self, a, b)
}
fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef> {
super_trait_refs(self, a, b)
}
}

View file

@ -16,7 +16,7 @@ use middle::ty;
use middle::typeck::infer::{Bound, Bounds};
use middle::typeck::infer::InferCtxt;
use middle::typeck::infer::unify::{Redirect, Root, VarValue};
use util::ppaux::{mt_to_str, ty_to_str};
use util::ppaux::{mt_to_str, ty_to_str, trait_ref_to_str};
use syntax::ast;
@ -91,3 +91,9 @@ impl InferStr for ast::float_ty {
self.to_str()
}
}
impl InferStr for ty::TraitRef {
fn inf_str(&self, cx: &InferCtxt) -> ~str {
trait_ref_to_str(cx.tcx, self)
}
}

View file

@ -222,8 +222,8 @@ pub fn lookup_def_ccx(ccx: @mut CrateCtxt, sp: span, id: ast::node_id)
pub fn no_params(t: ty::t) -> ty::ty_param_bounds_and_ty {
ty::ty_param_bounds_and_ty {
bounds: @~[],
region_param: None,
generics: ty::Generics {bounds: @~[],
region_param: None},
ty: t
}
}

View file

@ -239,7 +239,6 @@ pub fn vstore_to_str(cx: ctxt, vs: ty::vstore) -> ~str {
pub fn trait_store_to_str(cx: ctxt, s: ty::TraitStore) -> ~str {
match s {
ty::BareTraitStore => ~"",
ty::UniqTraitStore => ~"~",
ty::BoxTraitStore => ~"@",
ty::RegionTraitStore(r) => region_to_str_space(cx, "&", r)
@ -285,6 +284,12 @@ pub fn fn_sig_to_str(cx: ctxt, typ: &ty::FnSig) -> ~str {
ty_to_str(cx, typ.output))
}
pub fn trait_ref_to_str(cx: ctxt, trait_ref: &ty::TraitRef) -> ~str {
let path = ty::item_path(cx, trait_ref.def_id);
let base = ast_map::path_to_str(path, cx.sess.intr());
parameterized(cx, base, trait_ref.substs.self_r, trait_ref.substs.tps)
}
pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
fn fn_input_to_str(cx: ctxt, input: ty::arg) -> ~str {
let ty::arg {mode: mode, ty: ty} = input;
@ -443,7 +448,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
str::from_bytes(~[('a' as u8) + (id as u8)]))
}
}
ty_self(*) => ~"self",
ty_self(*) => ~"Self",
ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
let path = ty::item_path(cx, did);
let base = ast_map::path_to_str(path, cx.sess.intr());

View file

@ -117,7 +117,7 @@ fn fold_mod(
!doc.methods.is_empty()
} else {
// This is a trait implementation, make it visible
// NOTE: This is not quite right since this could be an impl
// NB: This is not quite right since this could be an impl
// of a private trait. We can't know that without running
// resolve though.
true

View file

@ -144,7 +144,7 @@ pub static crate_node_id: node_id = 0;
// the "special" built-in traits (see middle::lang_items) and
// detects Copy, Send, Owned, and Const.
pub enum TyParamBound {
TraitTyParamBound(@Ty),
TraitTyParamBound(@trait_ref),
RegionTyParamBound
}
@ -194,6 +194,7 @@ pub enum def {
def_local(node_id, bool /* is_mutbl */),
def_variant(def_id /* enum */, def_id /* variant */),
def_ty(def_id),
def_trait(def_id),
def_prim_ty(prim_ty),
def_ty_param(def_id, uint),
def_binding(node_id, binding_mode),
@ -1185,6 +1186,15 @@ pub struct trait_ref {
#[deriving(Eq)]
pub enum visibility { public, private, inherited }
impl visibility {
fn inherit_from(&self, parent_visibility: visibility) -> visibility {
match self {
&inherited => parent_visibility,
&public | &private => *self
}
}
}
#[auto_encode]
#[auto_decode]
#[deriving(Eq)]

View file

@ -61,7 +61,7 @@ pub fn def_id_of_def(d: def) -> def_id {
def_fn(id, _) | def_static_method(id, _, _) | def_mod(id) |
def_foreign_mod(id) | def_const(id) |
def_variant(_, id) | def_ty(id) | def_ty_param(id, _) |
def_use(id) | def_struct(id) => {
def_use(id) | def_struct(id) | def_trait(id) => {
id
}
def_arg(id, _, _) | def_local(id, _) | def_self(id, _) | def_self_ty(id)

View file

@ -222,15 +222,14 @@ pub fn expand_auto_decode(
priv impl @ext_ctxt {
fn bind_path(
&self,
span: span,
_span: span,
ident: ast::ident,
path: @ast::path,
bounds: @OptVec<ast::TyParamBound>
) -> ast::TyParam {
let bound = ast::TraitTyParamBound(@ast::Ty {
id: self.next_id(),
node: ast::ty_path(path, self.next_id()),
span: span,
let bound = ast::TraitTyParamBound(@ast::trait_ref {
ref_id: self.next_id(),
path: path
});
ast::TyParam {
@ -466,10 +465,9 @@ fn mk_impl(
// All the type parameters need to bound to the trait.
let mut impl_tps = opt_vec::with(ty_param);
for generics.ty_params.each |tp| {
let t_bound = ast::TraitTyParamBound(@ast::Ty {
id: cx.next_id(),
node: ast::ty_path(path, cx.next_id()),
span: span,
let t_bound = ast::TraitTyParamBound(@ast::trait_ref {
path: path,
ref_id: cx.next_id(),
});
impl_tps.push(ast::TyParam {

View file

@ -337,6 +337,17 @@ pub fn mk_ty_path_global(cx: @ext_ctxt,
let ty = @ast::Ty { id: cx.next_id(), node: ty, span: span };
ty
}
pub fn mk_trait_ref_global(cx: @ext_ctxt,
span: span,
+idents: ~[ ast::ident ])
-> @ast::trait_ref
{
let path = build::mk_raw_path_global(span, idents);
@ast::trait_ref {
path: path,
ref_id: cx.next_id()
}
}
pub fn mk_simple_ty_path(cx: @ext_ctxt,
span: span,
ident: ast::ident)

View file

@ -177,9 +177,9 @@ pub fn create_derived_impl(cx: @ext_ctxt,
// Create the type parameters.
let impl_ty_params = generics.ty_params.map(|ty_param| {
let bound = build::mk_ty_path_global(cx,
span,
trait_path.map(|x| *x));
let bound = build::mk_trait_ref_global(cx,
span,
trait_path.map(|x| *x));
let bounds = @opt_vec::with(TraitTyParamBound(bound));
build::mk_ty_param(cx, ty_param.ident, bounds)
});

View file

@ -134,7 +134,7 @@ pub fn fold_fn_decl(decl: &ast::fn_decl, fld: @ast_fold) -> ast::fn_decl {
fn fold_ty_param_bound(tpb: &TyParamBound, fld: @ast_fold) -> TyParamBound {
match *tpb {
TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_ty(ty)),
TraitTyParamBound(ty) => TraitTyParamBound(fold_trait_ref(ty, fld)),
RegionTyParamBound => RegionTyParamBound
}
}

View file

@ -2750,8 +2750,8 @@ pub impl Parser {
self.bump();
}
token::MOD_SEP | token::IDENT(*) => {
let maybe_bound = match *self.token {
token::MOD_SEP => None,
let obsolete_bound = match *self.token {
token::MOD_SEP => false,
token::IDENT(copy sid, _) => {
match *self.id_to_str(sid) {
~"send" |
@ -2761,27 +2761,18 @@ pub impl Parser {
self.obsolete(
*self.span,
ObsoleteLowerCaseKindBounds);
// Bogus value, but doesn't matter, since
// is an error
Some(TraitTyParamBound(
self.mk_ty_path(sid)))
self.bump();
true
}
_ => None
_ => false
}
}
_ => fail!()
};
match maybe_bound {
Some(bound) => {
self.bump();
result.push(bound);
}
None => {
let ty = self.parse_ty(true);
result.push(TraitTyParamBound(ty));
}
if !obsolete_bound {
let tref = self.parse_trait_ref();
result.push(TraitTyParamBound(tref));
}
}
_ => break,

View file

@ -562,7 +562,7 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
match opt_trait {
Some(t) => {
print_path(s, t.path, false);
print_trait_ref(s, t);
space(s.s);
word_space(s, ~"for");
}
@ -619,6 +619,10 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
(s.ann.post)(ann_node);
}
fn print_trait_ref(s: @ps, t: &ast::trait_ref) {
print_path(s, t.path, false);
}
pub fn print_enum_def(s: @ps, enum_definition: ast::enum_def,
generics: &ast::Generics, ident: ast::ident,
span: codemap::span, visibility: ast::visibility) {
@ -1744,7 +1748,7 @@ pub fn print_bounds(s: @ps, bounds: @OptVec<ast::TyParamBound>) {
}
match *bound {
TraitTyParamBound(ty) => print_type(s, ty),
TraitTyParamBound(tref) => print_trait_ref(s, tref),
RegionTyParamBound => word(s.s, ~"'static"),
}
}

View file

@ -147,6 +147,10 @@ pub fn visit_local<E>(loc: @local, e: E, v: vt<E>) {
}
}
fn visit_trait_ref<E>(tref: @ast::trait_ref, e: E, v: vt<E>) {
visit_path(tref.path, e, v);
}
pub fn visit_item<E>(i: @item, e: E, v: vt<E>) {
match i.node {
item_const(t, ex) => {
@ -189,9 +193,9 @@ pub fn visit_item<E>(i: @item, e: E, v: vt<E>) {
}
item_impl(ref tps, ref traits, ty, ref methods) => {
(v.visit_generics)(tps, e, v);
for traits.each |p| {
visit_path(p.path, e, v);
}
for traits.each |&p| {
visit_trait_ref(p, e, v);
}
(v.visit_ty)(ty, e, v);
for methods.each |m| {
visit_method_helper(*m, e, v)
@ -327,8 +331,8 @@ pub fn visit_ty_param_bounds<E>(bounds: @OptVec<TyParamBound>,
e: E, v: vt<E>) {
for bounds.each |bound| {
match *bound {
TraitTyParamBound(ty) => (v.visit_ty)(ty, e, v),
RegionTyParamBound => ()
TraitTyParamBound(ty) => visit_trait_ref(ty, e, v),
RegionTyParamBound => {}
}
}
}

View file

@ -314,7 +314,7 @@ void update_log_settings(void* crate_map, char* settings) {
n_dirs, &n_matches);
if (n_matches < n_dirs) {
// NOTE: Android compiler is complaining about format specifiers here
// NB: Android compiler is complaining about format specifiers here
// and I don't understand why
/*printf("warning: got %" PRIdPTR " RUST_LOG specs, "
"enabled %" PRIdPTR " flags.",

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern:expected function or foreign function but found `*u8`
// error-pattern:expected function but found `*u8`
extern fn f() {
}

View file

@ -15,7 +15,7 @@ trait channel<T> {
}
// `chan` is not a trait, it's an enum
impl chan for int { //~ ERROR can only implement trait types
impl chan for int { //~ ERROR chan is not a trait
fn send(&self, v: int) { fail!() }
}

View file

@ -10,7 +10,7 @@
trait A {
fn a(&self) {
|| self.b() //~ ERROR type `&'self self` does not implement any method in scope named `b`
|| self.b() //~ ERROR type `&'self Self` does not implement any method in scope named `b`
}
}
fn main() {}

View file

@ -12,7 +12,7 @@ trait add {
fn plus(&self, x: Self) -> Self;
}
fn do_add(x: add, y: add) -> add {
fn do_add(x: @add, y: @add) -> @add {
x.plus(y) //~ ERROR cannot call a method whose type contains a self-type through a boxed trait
}

View file

@ -13,7 +13,7 @@ pub fn main() {
fn to_str(&self) -> ~str;
}
fn to_string(t: Text) {
fn to_string(t: @Text) {
io::println(t.to_str());
}

View file

@ -417,9 +417,9 @@ impl<V:TyVisitor + movable_ptr> TyVisitor for ptr_visit_adaptor<V> {
}
fn visit_trait(&self) -> bool {
self.align_to::<TyVisitor>();
self.align_to::<@TyVisitor>();
if ! self.inner.visit_trait() { return false; }
self.bump_past::<TyVisitor>();
self.bump_past::<@TyVisitor>();
true
}

View file

@ -15,7 +15,7 @@ struct Foo {
}
pub impl Foo {
fn foo(&'a self) {}
fn foo<'a>(&'a self) {}
}
pub fn main() {}