mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-08 01:28:18 +03:00
librustc: Implement associated types behind a feature gate.
The implementation essentially desugars during type collection and AST type conversion time into the parameter scheme we have now. Only fully qualified names--e.g. `<T as Foo>::Bar`--are supported.
This commit is contained in:
@@ -2557,6 +2557,8 @@ The currently implemented features of the reference compiler are:
|
||||
|
||||
* `tuple_indexing` - Allows use of tuple indexing (expressions like `expr.0`)
|
||||
|
||||
* `associated_types` - Allows type aliases in traits. Experimental.
|
||||
|
||||
If a feature is promoted to a language feature, then all existing programs will
|
||||
start to receive compilation warnings about #[feature] directives which enabled
|
||||
the new feature (because the directive is no longer necessary). However, if
|
||||
|
||||
+1
-1
Submodule src/jemalloc updated: 2dba541881...aae04170cc
@@ -844,6 +844,17 @@ fn method_context(cx: &Context, m: &ast::Method) -> MethodContext {
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::TypeTraitItem(typedef) => {
|
||||
match typedef.container {
|
||||
ty::TraitContainer(..) => TraitDefaultImpl,
|
||||
ty::ImplContainer(cid) => {
|
||||
match ty::impl_trait_ref(cx.tcx, cid) {
|
||||
Some(..) => TraitImpl,
|
||||
None => PlainImpl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1511,13 +1522,9 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
|
||||
method_num: index,
|
||||
..
|
||||
}) => {
|
||||
match ty::trait_item(cx.tcx,
|
||||
trait_ref.def_id,
|
||||
index) {
|
||||
ty::MethodTraitItem(method) => {
|
||||
method.def_id
|
||||
}
|
||||
}
|
||||
ty::trait_item(cx.tcx,
|
||||
trait_ref.def_id,
|
||||
index).def_id()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
//! for all lint attributes.
|
||||
|
||||
use middle::privacy::ExportedItems;
|
||||
use middle::subst;
|
||||
use middle::ty;
|
||||
use middle::typeck::astconv::AstConv;
|
||||
use middle::typeck::infer;
|
||||
@@ -491,6 +492,26 @@ fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
|
||||
fn ty_infer(&self, _span: Span) -> ty::t {
|
||||
infer::new_infer_ctxt(self.tcx).next_ty_var()
|
||||
}
|
||||
|
||||
fn associated_types_of_trait_are_valid(&self, _: ty::t, _: ast::DefId)
|
||||
-> bool {
|
||||
// FIXME(pcwalton): This is wrong.
|
||||
true
|
||||
}
|
||||
|
||||
fn associated_type_binding(&self,
|
||||
_: Span,
|
||||
_: Option<ty::t>,
|
||||
trait_id: ast::DefId,
|
||||
associated_type_id: ast::DefId)
|
||||
-> ty::t {
|
||||
// FIXME(pcwalton): This is wrong.
|
||||
let trait_def = self.get_trait_def(trait_id);
|
||||
let index = ty::associated_type_parameter_index(self.tcx,
|
||||
&*trait_def,
|
||||
associated_type_id);
|
||||
ty::mk_param(self.tcx, subst::TypeSpace, index, associated_type_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
|
||||
|
||||
@@ -349,3 +349,9 @@ pub fn get_stability(cstore: &cstore::CStore,
|
||||
let cdata = cstore.get_crate_data(def.krate);
|
||||
decoder::get_stability(&*cdata, def.node)
|
||||
}
|
||||
|
||||
pub fn is_associated_type(cstore: &cstore::CStore, def: ast::DefId) -> bool {
|
||||
let cdata = cstore.get_crate_data(def.krate);
|
||||
decoder::is_associated_type(&*cdata, def.node)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
parse_bare_fn_ty_data, parse_trait_ref_data};
|
||||
use middle::def;
|
||||
use middle::lang_items;
|
||||
use middle::resolve::TraitItemKind;
|
||||
use middle::resolve::{TraitItemKind, TypeTraitItemKind};
|
||||
use middle::subst;
|
||||
use middle::ty::{ImplContainer, TraitContainer};
|
||||
use middle::ty;
|
||||
@@ -167,6 +167,8 @@ fn item_visibility(item: rbml::Doc) -> ast::Visibility {
|
||||
}
|
||||
|
||||
fn item_sort(item: rbml::Doc) -> char {
|
||||
// NB(pcwalton): The default of 'r' here is relied upon in
|
||||
// `is_associated_type` below.
|
||||
let mut ret = 'r';
|
||||
reader::tagged_docs(item, tag_item_trait_item_sort, |doc| {
|
||||
ret = doc.as_str_slice().as_bytes()[0] as char;
|
||||
@@ -714,6 +716,7 @@ pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
|
||||
let def_id = item_def_id(doc, cdata);
|
||||
match item_sort(doc) {
|
||||
'r' | 'p' => impl_items.push(ty::MethodTraitItemId(def_id)),
|
||||
't' => impl_items.push(ty::TypeTraitItemId(def_id)),
|
||||
_ => fail!("unknown impl item sort"),
|
||||
}
|
||||
true
|
||||
@@ -733,6 +736,7 @@ pub fn get_trait_item_name_and_kind(intr: Rc<IdentInterner>,
|
||||
let explicit_self = get_explicit_self(doc);
|
||||
(name, TraitItemKind::from_explicit_self_category(explicit_self))
|
||||
}
|
||||
't' => (name, TypeTraitItemKind),
|
||||
c => {
|
||||
fail!("get_trait_item_name_and_kind(): unknown trait item kind \
|
||||
in metadata: `{}`", c)
|
||||
@@ -758,13 +762,13 @@ pub fn get_impl_or_trait_item(intr: Rc<IdentInterner>,
|
||||
};
|
||||
|
||||
let name = item_name(&*intr, method_doc);
|
||||
let vis = item_visibility(method_doc);
|
||||
|
||||
match item_sort(method_doc) {
|
||||
'r' | 'p' => {
|
||||
let generics = doc_generics(method_doc, tcx, cdata,
|
||||
tag_method_ty_generics);
|
||||
let fty = doc_method_fty(method_doc, tcx, cdata);
|
||||
let vis = item_visibility(method_doc);
|
||||
let explicit_self = get_explicit_self(method_doc);
|
||||
let provided_source = get_provided_source(method_doc, cdata);
|
||||
|
||||
@@ -777,6 +781,14 @@ pub fn get_impl_or_trait_item(intr: Rc<IdentInterner>,
|
||||
container,
|
||||
provided_source)))
|
||||
}
|
||||
't' => {
|
||||
ty::TypeTraitItem(Rc::new(ty::AssociatedType {
|
||||
ident: name,
|
||||
vis: vis,
|
||||
def_id: def_id,
|
||||
container: container,
|
||||
}))
|
||||
}
|
||||
_ => fail!("unknown impl/trait item sort"),
|
||||
}
|
||||
}
|
||||
@@ -790,6 +802,7 @@ pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
|
||||
let def_id = item_def_id(mth, cdata);
|
||||
match item_sort(mth) {
|
||||
'r' | 'p' => result.push(ty::MethodTraitItemId(def_id)),
|
||||
't' => result.push(ty::TypeTraitItemId(def_id)),
|
||||
_ => fail!("unknown trait item sort"),
|
||||
}
|
||||
true
|
||||
@@ -827,6 +840,7 @@ pub fn get_provided_trait_methods(intr: Rc<IdentInterner>,
|
||||
ty::MethodTraitItem(ref method) => {
|
||||
result.push((*method).clone())
|
||||
}
|
||||
ty::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
true
|
||||
@@ -1394,3 +1408,12 @@ fn doc_generics(base_doc: rbml::Doc,
|
||||
|
||||
ty::Generics { types: types, regions: regions }
|
||||
}
|
||||
|
||||
pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool {
|
||||
let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items);
|
||||
match maybe_find_item(id, items) {
|
||||
None => false,
|
||||
Some(item) => item_sort(item) == 't',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -416,6 +416,7 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
|
||||
m.ident);
|
||||
}
|
||||
}
|
||||
ty::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -887,7 +888,44 @@ fn encode_info_for_method(ecx: &EncodeContext,
|
||||
}
|
||||
encode_method_argument_names(rbml_w, ast_method.pe_fn_decl());
|
||||
}
|
||||
Some(_) | None => {}
|
||||
}
|
||||
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
|
||||
fn encode_info_for_associated_type(ecx: &EncodeContext,
|
||||
rbml_w: &mut Encoder,
|
||||
associated_type: &ty::AssociatedType,
|
||||
impl_path: PathElems,
|
||||
parent_id: NodeId,
|
||||
typedef_opt: Option<P<ast::Typedef>>) {
|
||||
debug!("encode_info_for_associated_type({},{})",
|
||||
associated_type.def_id,
|
||||
token::get_ident(associated_type.ident));
|
||||
|
||||
rbml_w.start_tag(tag_items_data_item);
|
||||
|
||||
encode_def_id(rbml_w, associated_type.def_id);
|
||||
encode_name(rbml_w, associated_type.ident.name);
|
||||
encode_visibility(rbml_w, associated_type.vis);
|
||||
encode_family(rbml_w, 'y');
|
||||
encode_parent_item(rbml_w, local_def(parent_id));
|
||||
encode_item_sort(rbml_w, 'r');
|
||||
|
||||
let stab = stability::lookup(ecx.tcx, associated_type.def_id);
|
||||
encode_stability(rbml_w, stab);
|
||||
|
||||
let elem = ast_map::PathName(associated_type.ident.name);
|
||||
encode_path(rbml_w, impl_path.chain(Some(elem).move_iter()));
|
||||
|
||||
match typedef_opt {
|
||||
None => {}
|
||||
Some(typedef) => {
|
||||
encode_attributes(rbml_w, typedef.attrs.as_slice());
|
||||
encode_type(ecx, rbml_w, ty::node_id_to_type(ecx.tcx,
|
||||
typedef.id));
|
||||
}
|
||||
}
|
||||
|
||||
rbml_w.end_tag();
|
||||
@@ -1198,6 +1236,10 @@ fn add_to_index(item: &Item, rbml_w: &Encoder,
|
||||
encode_def_id(rbml_w, item_def_id);
|
||||
encode_item_sort(rbml_w, 'r');
|
||||
}
|
||||
ty::TypeTraitItemId(item_def_id) => {
|
||||
encode_def_id(rbml_w, item_def_id);
|
||||
encode_item_sort(rbml_w, 't');
|
||||
}
|
||||
}
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
@@ -1227,10 +1269,46 @@ fn add_to_index(item: &Item, rbml_w: &Encoder,
|
||||
pos: rbml_w.writer.tell().unwrap(),
|
||||
});
|
||||
|
||||
let ty::MethodTraitItem(method_type) =
|
||||
let trait_item_type =
|
||||
ty::impl_or_trait_item(tcx, trait_item_def_id.def_id());
|
||||
encode_info_for_method(ecx, rbml_w, &*method_type, path.clone(),
|
||||
false, item.id, ast_item)
|
||||
match (trait_item_type, ast_item) {
|
||||
(ty::MethodTraitItem(ref method_type),
|
||||
Some(&ast::MethodImplItem(_))) => {
|
||||
encode_info_for_method(ecx,
|
||||
rbml_w,
|
||||
&**method_type,
|
||||
path.clone(),
|
||||
false,
|
||||
item.id,
|
||||
ast_item)
|
||||
}
|
||||
(ty::MethodTraitItem(ref method_type), _) => {
|
||||
encode_info_for_method(ecx,
|
||||
rbml_w,
|
||||
&**method_type,
|
||||
path.clone(),
|
||||
false,
|
||||
item.id,
|
||||
None)
|
||||
}
|
||||
(ty::TypeTraitItem(ref associated_type),
|
||||
Some(&ast::TypeImplItem(ref typedef))) => {
|
||||
encode_info_for_associated_type(ecx,
|
||||
rbml_w,
|
||||
&**associated_type,
|
||||
path.clone(),
|
||||
item.id,
|
||||
Some((*typedef).clone()))
|
||||
}
|
||||
(ty::TypeTraitItem(ref associated_type), _) => {
|
||||
encode_info_for_associated_type(ecx,
|
||||
rbml_w,
|
||||
&**associated_type,
|
||||
path.clone(),
|
||||
item.id,
|
||||
None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemTrait(_, _, _, ref ms) => {
|
||||
@@ -1253,6 +1331,10 @@ fn add_to_index(item: &Item, rbml_w: &Encoder,
|
||||
encode_def_id(rbml_w, method_def_id);
|
||||
encode_item_sort(rbml_w, 'r');
|
||||
}
|
||||
ty::TypeTraitItemId(type_def_id) => {
|
||||
encode_def_id(rbml_w, type_def_id);
|
||||
encode_item_sort(rbml_w, 't');
|
||||
}
|
||||
}
|
||||
rbml_w.end_tag();
|
||||
|
||||
@@ -1281,17 +1363,19 @@ fn add_to_index(item: &Item, rbml_w: &Encoder,
|
||||
|
||||
rbml_w.start_tag(tag_items_data_item);
|
||||
|
||||
encode_parent_item(rbml_w, def_id);
|
||||
|
||||
let stab = stability::lookup(tcx, item_def_id.def_id());
|
||||
encode_stability(rbml_w, stab);
|
||||
|
||||
let trait_item_type =
|
||||
ty::impl_or_trait_item(tcx, item_def_id.def_id());
|
||||
let is_nonstatic_method;
|
||||
match trait_item_type {
|
||||
ty::MethodTraitItem(method_ty) => {
|
||||
ty::MethodTraitItem(method_ty) => {
|
||||
let method_def_id = item_def_id.def_id();
|
||||
|
||||
encode_method_ty_fields(ecx, rbml_w, &*method_ty);
|
||||
encode_parent_item(rbml_w, def_id);
|
||||
|
||||
let stab = stability::lookup(tcx, method_def_id);
|
||||
encode_stability(rbml_w, stab);
|
||||
|
||||
let elem = ast_map::PathName(method_ty.ident.name);
|
||||
encode_path(rbml_w,
|
||||
@@ -1315,33 +1399,53 @@ fn add_to_index(item: &Item, rbml_w: &Encoder,
|
||||
}
|
||||
}
|
||||
|
||||
let trait_item = ms.get(i);
|
||||
match *trait_item {
|
||||
RequiredMethod(ref tm) => {
|
||||
encode_attributes(rbml_w, tm.attrs.as_slice());
|
||||
encode_item_sort(rbml_w, 'r');
|
||||
encode_parent_sort(rbml_w, 't');
|
||||
encode_method_argument_names(rbml_w, &*tm.decl);
|
||||
}
|
||||
is_nonstatic_method = method_ty.explicit_self !=
|
||||
ty::StaticExplicitSelfCategory;
|
||||
}
|
||||
ty::TypeTraitItem(associated_type) => {
|
||||
let elem = ast_map::PathName(associated_type.ident.name);
|
||||
encode_path(rbml_w,
|
||||
path.clone().chain(Some(elem).move_iter()));
|
||||
|
||||
ProvidedMethod(ref m) => {
|
||||
encode_attributes(rbml_w, m.attrs.as_slice());
|
||||
// If this is a static method, we've already
|
||||
// encoded this.
|
||||
if method_ty.explicit_self !=
|
||||
ty::StaticExplicitSelfCategory {
|
||||
// FIXME: I feel like there is something funny
|
||||
// going on.
|
||||
let pty = ty::lookup_item_type(tcx, method_def_id);
|
||||
encode_bounds_and_type(rbml_w, ecx, &pty);
|
||||
}
|
||||
encode_item_sort(rbml_w, 'p');
|
||||
encode_parent_sort(rbml_w, 't');
|
||||
encode_inlined_item(ecx, rbml_w,
|
||||
IITraitItemRef(def_id, trait_item));
|
||||
encode_method_argument_names(rbml_w, &*m.pe_fn_decl());
|
||||
}
|
||||
encode_family(rbml_w, 'y');
|
||||
|
||||
is_nonstatic_method = false;
|
||||
}
|
||||
}
|
||||
|
||||
encode_parent_sort(rbml_w, 't');
|
||||
|
||||
let trait_item = ms.get(i);
|
||||
match ms.get(i) {
|
||||
&RequiredMethod(ref tm) => {
|
||||
encode_attributes(rbml_w, tm.attrs.as_slice());
|
||||
encode_item_sort(rbml_w, 'r');
|
||||
encode_method_argument_names(rbml_w, &*tm.decl);
|
||||
}
|
||||
|
||||
&ProvidedMethod(ref m) => {
|
||||
encode_attributes(rbml_w, m.attrs.as_slice());
|
||||
// If this is a static method, we've already
|
||||
// encoded this.
|
||||
if is_nonstatic_method {
|
||||
// FIXME: I feel like there is something funny
|
||||
// going on.
|
||||
let pty = ty::lookup_item_type(tcx,
|
||||
item_def_id.def_id());
|
||||
encode_bounds_and_type(rbml_w, ecx, &pty);
|
||||
}
|
||||
encode_item_sort(rbml_w, 'p');
|
||||
encode_inlined_item(ecx,
|
||||
rbml_w,
|
||||
IITraitItemRef(def_id, trait_item));
|
||||
encode_method_argument_names(rbml_w,
|
||||
&*m.pe_fn_decl());
|
||||
}
|
||||
|
||||
&TypeTraitItem(ref associated_type) => {
|
||||
encode_attributes(rbml_w,
|
||||
associated_type.attrs.as_slice());
|
||||
encode_item_sort(rbml_w, 't');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -630,6 +630,10 @@ fn parse_type_param_def(st: &mut PState, conv: conv_did) -> ty::TypeParameterDef
|
||||
assert_eq!(next(st), '|');
|
||||
let index = parse_uint(st);
|
||||
assert_eq!(next(st), '|');
|
||||
let associated_with = parse_opt(st, |st| {
|
||||
parse_def(st, NominalType, |x,y| conv(x,y))
|
||||
});
|
||||
assert_eq!(next(st), '|');
|
||||
let bounds = parse_bounds(st, |x,y| conv(x,y));
|
||||
let default = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)));
|
||||
|
||||
@@ -638,6 +642,7 @@ fn parse_type_param_def(st: &mut PState, conv: conv_did) -> ty::TypeParameterDef
|
||||
def_id: def_id,
|
||||
space: space,
|
||||
index: index,
|
||||
associated_with: associated_with,
|
||||
bounds: bounds,
|
||||
default: default
|
||||
}
|
||||
|
||||
@@ -383,6 +383,8 @@ pub fn enc_type_param_def(w: &mut SeekableMemWriter, cx: &ctxt, v: &ty::TypePara
|
||||
mywrite!(w, "{}:{}|{}|{}|",
|
||||
token::get_ident(v.ident), (cx.ds)(v.def_id),
|
||||
v.space.to_uint(), v.index);
|
||||
enc_opt(w, v.associated_with, |w, did| mywrite!(w, "{}", (cx.ds)(did)));
|
||||
mywrite!(w, "|");
|
||||
enc_bounds(w, cx, &v.bounds);
|
||||
enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
|
||||
}
|
||||
|
||||
@@ -83,7 +83,9 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
|
||||
e::IIForeignRef(i) => i.id,
|
||||
e::IITraitItemRef(_, &ast::ProvidedMethod(ref m)) => m.id,
|
||||
e::IITraitItemRef(_, &ast::RequiredMethod(ref m)) => m.id,
|
||||
e::IIImplItemRef(_, &ast::MethodImplItem(ref m)) => m.id
|
||||
e::IITraitItemRef(_, &ast::TypeTraitItem(ref ti)) => ti.id,
|
||||
e::IIImplItemRef(_, &ast::MethodImplItem(ref m)) => m.id,
|
||||
e::IIImplItemRef(_, &ast::TypeImplItem(ref ti)) => ti.id,
|
||||
};
|
||||
debug!("> Encoding inlined item: {} ({})",
|
||||
ecx.tcx.map.path_to_string(id),
|
||||
@@ -155,12 +157,14 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
|
||||
ast::IITraitItem(_, ref ti) => {
|
||||
match *ti {
|
||||
ast::ProvidedMethod(ref m) => m.pe_ident(),
|
||||
ast::RequiredMethod(ref ty_m) => ty_m.ident
|
||||
ast::RequiredMethod(ref ty_m) => ty_m.ident,
|
||||
ast::TypeTraitItem(ref ti) => ti.ident,
|
||||
}
|
||||
},
|
||||
ast::IIImplItem(_, ref m) => {
|
||||
match *m {
|
||||
ast::MethodImplItem(ref m) => m.pe_ident()
|
||||
ast::MethodImplItem(ref m) => m.pe_ident(),
|
||||
ast::TypeImplItem(ref ti) => ti.ident,
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -392,6 +396,12 @@ fn simplify_ast(ii: e::InlinedItemRef) -> ast::InlinedItem {
|
||||
ast::RequiredMethod(
|
||||
fold::noop_fold_type_method(ty_m.clone(), &mut fld))
|
||||
}
|
||||
ast::TypeTraitItem(ref associated_type) => {
|
||||
ast::TypeTraitItem(
|
||||
P(fold::noop_fold_associated_type(
|
||||
(**associated_type).clone(),
|
||||
&mut fld)))
|
||||
}
|
||||
})
|
||||
}
|
||||
e::IIImplItemRef(d, m) => {
|
||||
@@ -402,6 +412,10 @@ fn simplify_ast(ii: e::InlinedItemRef) -> ast::InlinedItem {
|
||||
.expect_one("noop_fold_method must produce \
|
||||
exactly one method"))
|
||||
}
|
||||
ast::TypeImplItem(ref td) => {
|
||||
ast::TypeImplItem(
|
||||
P(fold::noop_fold_typedef((**td).clone(), &mut fld)))
|
||||
}
|
||||
})
|
||||
}
|
||||
e::IIForeignRef(i) => {
|
||||
@@ -455,6 +469,7 @@ fn tr(&self, dcx: &DecodeContext) -> def::Def {
|
||||
},
|
||||
def::DefTrait(did) => def::DefTrait(did.tr(dcx)),
|
||||
def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum),
|
||||
def::DefAssociatedTy(did) => def::DefAssociatedTy(did.tr(dcx)),
|
||||
def::DefPrimTy(p) => def::DefPrimTy(p),
|
||||
def::DefTyParam(s, did, v) => def::DefTyParam(s, did.tr(dcx), v),
|
||||
def::DefBinding(nid, bm) => def::DefBinding(dcx.tr_id(nid), bm),
|
||||
|
||||
@@ -118,6 +118,9 @@ fn lookup_and_handle_method(&mut self, id: ast::NodeId,
|
||||
ty::MethodTraitItem(method) => {
|
||||
self.check_def_id(method.def_id);
|
||||
}
|
||||
ty::TypeTraitItem(typedef) => {
|
||||
self.check_def_id(typedef.def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,6 +229,7 @@ fn visit_node(&mut self, node: &ast_map::Node) {
|
||||
ast::MethodImplItem(ref method) => {
|
||||
visit::walk_block(self, method.pe_body());
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
ast_map::NodeForeignItem(foreign_item) => {
|
||||
@@ -341,6 +345,7 @@ fn visit_item(&mut self, item: &ast::Item) {
|
||||
ast::MethodImplItem(ref method) => {
|
||||
self.worklist.push(method.id);
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -544,7 +549,8 @@ fn visit_trait_item(&mut self, trait_method: &ast::TraitItem) {
|
||||
ast::ProvidedMethod(ref method) => {
|
||||
visit::walk_block(self, &*method.pe_body())
|
||||
}
|
||||
ast::RequiredMethod(_) => ()
|
||||
ast::RequiredMethod(_) => {}
|
||||
ast::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ pub enum Def {
|
||||
DefLocal(ast::NodeId, ast::BindingMode),
|
||||
DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */),
|
||||
DefTy(ast::DefId, bool /* is_enum */),
|
||||
DefAssociatedTy(ast::DefId),
|
||||
DefTrait(ast::DefId),
|
||||
DefPrimTy(ast::PrimTy),
|
||||
DefTyParam(ParamSpace, ast::DefId, uint),
|
||||
@@ -62,8 +63,9 @@ pub fn def_id(&self) -> ast::DefId {
|
||||
match *self {
|
||||
DefFn(id, _) | DefStaticMethod(id, _, _) | DefMod(id) |
|
||||
DefForeignMod(id) | DefStatic(id, _) |
|
||||
DefVariant(_, id, _) | DefTy(id, _) | DefTyParam(_, id, _) |
|
||||
DefUse(id) | DefStruct(id) | DefTrait(id) | DefMethod(id, _) => {
|
||||
DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(id) |
|
||||
DefTyParam(_, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) |
|
||||
DefMethod(id, _) => {
|
||||
id
|
||||
}
|
||||
DefArg(id, _) |
|
||||
@@ -90,3 +92,4 @@ pub fn variant_def_ids(&self) -> Option<(ast::DefId, ast::DefId)> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -134,6 +134,9 @@ fn from_method_id(tcx: &ty::ctxt, method_id: ast::DefId)
|
||||
ty::MethodTraitItem(ref method_descriptor) => {
|
||||
(*method_descriptor).clone()
|
||||
}
|
||||
ty::TypeTraitItem(_) => {
|
||||
tcx.sess.bug("overloaded call method wasn't in method map")
|
||||
}
|
||||
};
|
||||
let impl_id = match method_descriptor.container {
|
||||
ty::TraitContainer(_) => {
|
||||
|
||||
@@ -319,7 +319,9 @@ fn from_def(def: &def::Def) -> MutabilityCategory {
|
||||
def::DefTy(..) | def::DefTrait(..) | def::DefPrimTy(..) |
|
||||
def::DefTyParam(..) | def::DefUse(..) | def::DefStruct(..) |
|
||||
def::DefTyParamBinder(..) | def::DefRegion(..) | def::DefLabel(..) |
|
||||
def::DefMethod(..) => fail!("no MutabilityCategory for def: {}", *def),
|
||||
def::DefMethod(..) | def::DefAssociatedTy(..) => {
|
||||
fail!("no MutabilityCategory for def: {}", *def)
|
||||
}
|
||||
|
||||
def::DefStatic(_, false) => McImmutable,
|
||||
def::DefStatic(_, true) => McDeclared,
|
||||
@@ -533,7 +535,8 @@ pub fn cat_def(&self,
|
||||
def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
|
||||
def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
|
||||
def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
|
||||
def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) => {
|
||||
def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) |
|
||||
def::DefAssociatedTy(..) => {
|
||||
Ok(Rc::new(cmt_ {
|
||||
id:id,
|
||||
span:span,
|
||||
|
||||
@@ -82,8 +82,13 @@ fn visit_item(&mut self, item: &ast::Item) {
|
||||
ast::ItemTrait(_, _, _, ref methods) if item.vis != ast::Public => {
|
||||
for m in methods.iter() {
|
||||
match *m {
|
||||
ast::ProvidedMethod(ref m) => self.parents.insert(m.id, item.id),
|
||||
ast::RequiredMethod(ref m) => self.parents.insert(m.id, item.id),
|
||||
ast::ProvidedMethod(ref m) => {
|
||||
self.parents.insert(m.id, item.id);
|
||||
}
|
||||
ast::RequiredMethod(ref m) => {
|
||||
self.parents.insert(m.id, item.id);
|
||||
}
|
||||
ast::TypeTraitItem(_) => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -272,6 +277,7 @@ fn visit_item(&mut self, item: &ast::Item) {
|
||||
self.exported_items.insert(method.id);
|
||||
}
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -290,6 +296,10 @@ fn visit_item(&mut self, item: &ast::Item) {
|
||||
debug!("required {}", m.id);
|
||||
self.exported_items.insert(m.id);
|
||||
}
|
||||
ast::TypeTraitItem(ref t) => {
|
||||
debug!("typedef {}", t.id);
|
||||
self.exported_items.insert(t.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -419,6 +429,31 @@ fn def_privacy(&self, did: ast::DefId) -> PrivacyResult {
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(&ty::TypeTraitItem(ref typedef)) => {
|
||||
match typedef.container {
|
||||
ty::TraitContainer(id) => {
|
||||
debug!("privacy - recursing on trait {:?}", id);
|
||||
self.def_privacy(id)
|
||||
}
|
||||
ty::ImplContainer(id) => {
|
||||
match ty::impl_trait_ref(self.tcx, id) {
|
||||
Some(t) => {
|
||||
debug!("privacy - impl of trait {:?}", id);
|
||||
self.def_privacy(t.def_id)
|
||||
}
|
||||
None => {
|
||||
debug!("privacy - found a typedef {:?}",
|
||||
typedef.vis);
|
||||
if typedef.vis == ast::Public {
|
||||
Allowable
|
||||
} else {
|
||||
ExternallyDenied
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
debug!("privacy - nope, not even a method");
|
||||
ExternallyDenied
|
||||
@@ -469,6 +504,7 @@ fn def_privacy(&self, did: ast::DefId) -> PrivacyResult {
|
||||
_ => m.pe_vis()
|
||||
}
|
||||
}
|
||||
ast::TypeImplItem(_) => return Allowable,
|
||||
}
|
||||
}
|
||||
Some(ast_map::NodeTraitItem(_)) => {
|
||||
@@ -670,6 +706,7 @@ fn check_static_method(&mut self,
|
||||
ty::MethodTraitItem(method_type) => {
|
||||
method_type.provided_source.unwrap_or(method_id)
|
||||
}
|
||||
ty::TypeTraitItem(_) => method_id,
|
||||
};
|
||||
|
||||
let string = token::get_ident(name);
|
||||
@@ -1110,6 +1147,7 @@ fn check_sane_privacy(&self, item: &ast::Item) {
|
||||
ast::MethodImplItem(ref m) => {
|
||||
check_inherited(m.span, m.pe_vis(), "");
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1149,6 +1187,7 @@ fn check_sane_privacy(&self, item: &ast::Item) {
|
||||
check_inherited(m.span, m.vis,
|
||||
"unnecessary visibility");
|
||||
}
|
||||
ast::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1184,6 +1223,7 @@ fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: ast::Visibility) {
|
||||
ast::MethodImplItem(ref m) => {
|
||||
check_inherited(tcx, m.span, m.pe_vis());
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1211,6 +1251,7 @@ fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: ast::Visibility) {
|
||||
ast::RequiredMethod(..) => {}
|
||||
ast::ProvidedMethod(ref m) => check_inherited(tcx, m.span,
|
||||
m.pe_vis()),
|
||||
ast::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1351,6 +1392,7 @@ fn visit_item(&mut self, item: &ast::Item) {
|
||||
ast::MethodImplItem(ref m) => {
|
||||
self.exported_items.contains(&m.id)
|
||||
}
|
||||
ast::TypeImplItem(_) => false,
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1367,6 +1409,7 @@ fn visit_item(&mut self, item: &ast::Item) {
|
||||
ast::MethodImplItem(ref method) => {
|
||||
visit::walk_method_helper(self, &**method)
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1401,6 +1444,7 @@ fn visit_item(&mut self, item: &ast::Item) {
|
||||
visit::walk_method_helper(self, &**method);
|
||||
}
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
if found_pub_static {
|
||||
|
||||
@@ -197,6 +197,7 @@ fn def_id_represents_local_inlined_item(&self, def_id: ast::DefId) -> bool {
|
||||
match *trait_method {
|
||||
ast::RequiredMethod(_) => false,
|
||||
ast::ProvidedMethod(_) => true,
|
||||
ast::TypeTraitItem(_) => false,
|
||||
}
|
||||
}
|
||||
Some(ast_map::NodeImplItem(impl_item)) => {
|
||||
@@ -225,6 +226,7 @@ fn def_id_represents_local_inlined_item(&self, def_id: ast::DefId) -> bool {
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::TypeImplItem(_) => false,
|
||||
}
|
||||
}
|
||||
Some(_) => false,
|
||||
@@ -327,8 +329,9 @@ fn propagate_node(&mut self, node: &ast_map::Node,
|
||||
// Keep going, nothing to get exported
|
||||
}
|
||||
ast::ProvidedMethod(ref method) => {
|
||||
visit::walk_block(self, &*method.pe_body())
|
||||
visit::walk_block(self, &*method.pe_body());
|
||||
}
|
||||
ast::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
ast_map::NodeImplItem(impl_item) => {
|
||||
@@ -339,6 +342,7 @@ fn propagate_node(&mut self, node: &ast_map::Node,
|
||||
visit::walk_block(self, method.pe_body())
|
||||
}
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
// Nothing to recurse on for these
|
||||
|
||||
+160
-39
@@ -37,13 +37,15 @@
|
||||
use syntax::ast::{StructVariantKind, TraitRef, TraitTyParamBound};
|
||||
use syntax::ast::{TupleVariantKind, Ty, TyBool, TyChar, TyClosure, TyF32};
|
||||
use syntax::ast::{TyF64, TyFloat, TyI, TyI8, TyI16, TyI32, TyI64, TyInt};
|
||||
use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyProc, TyRptr};
|
||||
use syntax::ast::{TyStr, TyU, TyU8, TyU16, TyU32, TyU64, TyUint};
|
||||
use syntax::ast::{UnboxedFnTyParamBound, UnnamedField, UnsafeFn, Variant};
|
||||
use syntax::ast::{ViewItem, ViewItemExternCrate, ViewItemUse, ViewPathGlob};
|
||||
use syntax::ast::{ViewPathList, ViewPathSimple, Visibility};
|
||||
use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyProc, TyQPath};
|
||||
use syntax::ast::{TyRptr, TyStr, TyU, TyU8, TyU16, TyU32, TyU64, TyUint};
|
||||
use syntax::ast::{TypeImplItem, UnboxedFnTyParamBound, UnnamedField};
|
||||
use syntax::ast::{UnsafeFn, Variant, ViewItem, ViewItemExternCrate};
|
||||
use syntax::ast::{ViewItemUse, ViewPathGlob, ViewPathList, ViewPathSimple};
|
||||
use syntax::ast::{Visibility};
|
||||
use syntax::ast;
|
||||
use syntax::ast_util::{PostExpansionMethod, local_def, walk_pat};
|
||||
use syntax::ast_util;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::ext::mtwt;
|
||||
use syntax::parse::token::special_names;
|
||||
@@ -313,6 +315,7 @@ enum ModulePrefixResult {
|
||||
pub enum TraitItemKind {
|
||||
NonstaticMethodTraitItemKind,
|
||||
StaticMethodTraitItemKind,
|
||||
TypeTraitItemKind,
|
||||
}
|
||||
|
||||
impl TraitItemKind {
|
||||
@@ -1393,6 +1396,24 @@ fn build_reduced_graph_for_item(&mut self,
|
||||
method.span,
|
||||
is_public);
|
||||
}
|
||||
TypeImplItem(ref typedef) => {
|
||||
// Add the typedef to the module.
|
||||
let ident = typedef.ident;
|
||||
let typedef_name_bindings =
|
||||
self.add_child(
|
||||
ident,
|
||||
new_parent.clone(),
|
||||
ForbidDuplicateTypesAndModules,
|
||||
typedef.span);
|
||||
let def = DefAssociatedTy(local_def(
|
||||
typedef.id));
|
||||
let is_public = typedef.vis ==
|
||||
ast::Public;
|
||||
typedef_name_bindings.define_type(
|
||||
def,
|
||||
typedef.span,
|
||||
is_public);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1432,42 +1453,66 @@ fn build_reduced_graph_for_item(&mut self,
|
||||
|
||||
// Add the names of all the methods to the trait info.
|
||||
for method in methods.iter() {
|
||||
let (m_id, m_ident, m_fn_style, m_self, m_span) = match *method {
|
||||
ast::RequiredMethod(ref m) => {
|
||||
(m.id, m.ident, m.fn_style, &m.explicit_self, m.span)
|
||||
let (ident, kind) = match *method {
|
||||
ast::RequiredMethod(_) |
|
||||
ast::ProvidedMethod(_) => {
|
||||
let ty_m =
|
||||
ast_util::trait_item_to_ty_method(method);
|
||||
|
||||
let ident = ty_m.ident;
|
||||
|
||||
// Add it as a name in the trait module.
|
||||
let (def, static_flag) = match ty_m.explicit_self
|
||||
.node {
|
||||
SelfStatic => {
|
||||
// Static methods become
|
||||
// `def_static_method`s.
|
||||
(DefStaticMethod(
|
||||
local_def(ty_m.id),
|
||||
FromTrait(local_def(item.id)),
|
||||
ty_m.fn_style),
|
||||
StaticMethodTraitItemKind)
|
||||
}
|
||||
_ => {
|
||||
// Non-static methods become
|
||||
// `def_method`s.
|
||||
(DefMethod(local_def(ty_m.id),
|
||||
Some(local_def(item.id))),
|
||||
NonstaticMethodTraitItemKind)
|
||||
}
|
||||
};
|
||||
|
||||
let method_name_bindings =
|
||||
self.add_child(ident,
|
||||
module_parent.clone(),
|
||||
ForbidDuplicateTypesAndValues,
|
||||
ty_m.span);
|
||||
method_name_bindings.define_value(def,
|
||||
ty_m.span,
|
||||
true);
|
||||
|
||||
(ident, static_flag)
|
||||
}
|
||||
ast::ProvidedMethod(ref m) => {
|
||||
(m.id, m.pe_ident(), m.pe_fn_style(), m.pe_explicit_self(), m.span)
|
||||
ast::TypeTraitItem(ref associated_type) => {
|
||||
let def = DefAssociatedTy(local_def(
|
||||
associated_type.id));
|
||||
|
||||
let name_bindings =
|
||||
self.add_child(associated_type.ident,
|
||||
module_parent.clone(),
|
||||
ForbidDuplicateTypesAndValues,
|
||||
associated_type.span);
|
||||
name_bindings.define_type(def,
|
||||
associated_type.span,
|
||||
true);
|
||||
|
||||
(associated_type.ident, TypeTraitItemKind)
|
||||
}
|
||||
};
|
||||
|
||||
// Add it as a name in the trait module.
|
||||
let (def, static_flag) = match m_self.node {
|
||||
SelfStatic => {
|
||||
// Static methods become `def_static_method`s.
|
||||
(DefStaticMethod(local_def(m_id),
|
||||
FromTrait(local_def(item.id)),
|
||||
m_fn_style),
|
||||
StaticMethodTraitItemKind)
|
||||
}
|
||||
_ => {
|
||||
// Non-static methods become `def_method`s.
|
||||
(DefMethod(local_def(m_id),
|
||||
Some(local_def(item.id))),
|
||||
NonstaticMethodTraitItemKind)
|
||||
}
|
||||
};
|
||||
|
||||
let method_name_bindings =
|
||||
self.add_child(m_ident,
|
||||
module_parent.clone(),
|
||||
ForbidDuplicateValues,
|
||||
m_span);
|
||||
method_name_bindings.define_value(def, m_span, true);
|
||||
|
||||
self.trait_item_map
|
||||
.borrow_mut()
|
||||
.insert((m_ident.name, def_id), static_flag);
|
||||
.insert((ident.name, def_id), kind);
|
||||
}
|
||||
|
||||
name_bindings.define_type(DefTrait(def_id), sp, is_public);
|
||||
@@ -1823,7 +1868,7 @@ fn handle_external_def(&mut self,
|
||||
is_public,
|
||||
DUMMY_SP)
|
||||
}
|
||||
DefTy(..) => {
|
||||
DefTy(..) | DefAssociatedTy(..) => {
|
||||
debug!("(building reduced graph for external \
|
||||
crate) building type {}", final_ident);
|
||||
|
||||
@@ -4065,6 +4110,9 @@ fn resolve_item(&mut self, item: &Item) {
|
||||
ProvidedMethod(m.id)),
|
||||
&**m)
|
||||
}
|
||||
ast::TypeTraitItem(_) => {
|
||||
visit::walk_trait_item(this, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -4509,6 +4557,14 @@ fn resolve_implementation(&mut self,
|
||||
ProvidedMethod(method.id)),
|
||||
&**method);
|
||||
}
|
||||
TypeImplItem(ref typedef) => {
|
||||
// If this is a trait impl, ensure the method
|
||||
// exists in trait
|
||||
this.check_trait_item(typedef.ident,
|
||||
typedef.span);
|
||||
|
||||
this.resolve_type(&*typedef.typ);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -4745,9 +4801,73 @@ fn resolve_type(&mut self, ty: &Ty) {
|
||||
});
|
||||
}
|
||||
|
||||
TyQPath(ref qpath) => {
|
||||
self.resolve_type(&*qpath.for_type);
|
||||
|
||||
let current_module = self.current_module.clone();
|
||||
let module_path_idents: Vec<_> =
|
||||
qpath.trait_name
|
||||
.segments
|
||||
.iter()
|
||||
.map(|ps| ps.identifier)
|
||||
.collect();
|
||||
match self.resolve_module_path(
|
||||
current_module,
|
||||
module_path_idents.as_slice(),
|
||||
UseLexicalScope,
|
||||
qpath.trait_name.span,
|
||||
PathSearch) {
|
||||
Success((ref module, _)) if module.kind.get() ==
|
||||
TraitModuleKind => {
|
||||
match self.resolve_definition_of_name_in_module(
|
||||
(*module).clone(),
|
||||
qpath.item_name.name,
|
||||
TypeNS) {
|
||||
ChildNameDefinition(def, lp) |
|
||||
ImportNameDefinition(def, lp) => {
|
||||
match def {
|
||||
DefAssociatedTy(trait_type_id) => {
|
||||
let def = DefAssociatedTy(
|
||||
trait_type_id);
|
||||
self.record_def(ty.id, (def, lp));
|
||||
}
|
||||
_ => {
|
||||
self.resolve_error(
|
||||
ty.span,
|
||||
"not an associated type");
|
||||
}
|
||||
}
|
||||
}
|
||||
NoNameDefinition => {
|
||||
self.resolve_error(ty.span,
|
||||
"unresolved associated \
|
||||
type");
|
||||
}
|
||||
}
|
||||
}
|
||||
Success(..) => self.resolve_error(ty.span, "not a trait"),
|
||||
Indeterminate => {
|
||||
self.session.span_bug(ty.span,
|
||||
"indeterminate result when \
|
||||
resolving associated type")
|
||||
}
|
||||
Failed(error) => {
|
||||
let (span, help) = match error {
|
||||
Some((span, msg)) => (span, format!("; {}", msg)),
|
||||
None => (ty.span, String::new()),
|
||||
};
|
||||
self.resolve_error(span,
|
||||
format!("unresolved trait: {}",
|
||||
help).as_slice())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TyClosure(ref c) | TyProc(ref c) => {
|
||||
self.resolve_type_parameter_bounds(ty.id, &c.bounds,
|
||||
TraitBoundingTypeParameter);
|
||||
self.resolve_type_parameter_bounds(
|
||||
ty.id,
|
||||
&c.bounds,
|
||||
TraitBoundingTypeParameter);
|
||||
visit::walk_ty(self, ty);
|
||||
}
|
||||
|
||||
@@ -5210,8 +5330,9 @@ fn resolve_module_relative_path(&mut self,
|
||||
Some(def_id) => {
|
||||
match self.trait_item_map.borrow().find(&(ident.name, def_id)) {
|
||||
Some(&StaticMethodTraitItemKind) => (),
|
||||
Some(&TypeTraitItemKind) => (),
|
||||
None => (),
|
||||
_ => {
|
||||
Some(&NonstaticMethodTraitItemKind) => {
|
||||
debug!("containing module was a trait or impl \
|
||||
and name was a method -> not resolved");
|
||||
return None;
|
||||
|
||||
@@ -227,6 +227,7 @@ fn lookup_def_kind(&self, ref_id: NodeId, span: Span) -> Option<recorder::Row> {
|
||||
def::DefForeignMod(_) => Some(recorder::ModRef),
|
||||
def::DefStruct(_) => Some(recorder::StructRef),
|
||||
def::DefTy(..) |
|
||||
def::DefAssociatedTy(..) |
|
||||
def::DefTrait(_) => Some(recorder::TypeRef),
|
||||
def::DefStatic(_, _) |
|
||||
def::DefBinding(_, _) |
|
||||
@@ -355,11 +356,12 @@ fn process_method(&mut self, method: &ast::Method) {
|
||||
ty::MethodTraitItemId(def_id) => {
|
||||
method.id != 0 && def_id.node == 0
|
||||
}
|
||||
ty::TypeTraitItemId(_) => false,
|
||||
}
|
||||
});
|
||||
let decl_id = match decl_id {
|
||||
None => None,
|
||||
Some(ty::MethodTraitItemId(def_id)) => Some(def_id),
|
||||
Some(id) => Some(id.def_id()),
|
||||
};
|
||||
|
||||
let sub_span = self.span.sub_span_after_keyword(method.span, keywords::Fn);
|
||||
@@ -646,6 +648,9 @@ fn process_impl(&mut self,
|
||||
ast::MethodImplItem(ref method) => {
|
||||
visit::walk_method_helper(self, &**method)
|
||||
}
|
||||
ast::TypeImplItem(ref typedef) => {
|
||||
visit::walk_ty(self, &*typedef.typ)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -764,12 +769,7 @@ fn process_path(&mut self,
|
||||
def_id)
|
||||
.iter()
|
||||
.find(|mr| {
|
||||
match **mr {
|
||||
ty::MethodTraitItem(ref mr) => {
|
||||
mr.ident.name == ti.ident()
|
||||
.name
|
||||
}
|
||||
}
|
||||
mr.ident().name == ti.ident().name
|
||||
})
|
||||
.unwrap()
|
||||
.def_id())
|
||||
@@ -782,18 +782,13 @@ fn process_path(&mut self,
|
||||
Some(impl_items.get(&def_id)
|
||||
.iter()
|
||||
.find(|mr| {
|
||||
match **mr {
|
||||
ty::MethodTraitItemId(mr) => {
|
||||
ty::impl_or_trait_item(
|
||||
&self.analysis
|
||||
.ty_cx,
|
||||
mr).ident()
|
||||
.name ==
|
||||
ti.ident().name
|
||||
}
|
||||
}
|
||||
}).unwrap()
|
||||
.def_id())
|
||||
ty::impl_or_trait_item(
|
||||
&self.analysis.ty_cx,
|
||||
mr.def_id()).ident().name ==
|
||||
ti.ident().name
|
||||
})
|
||||
.unwrap()
|
||||
.def_id())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -894,7 +889,7 @@ fn process_method_call(&mut self,
|
||||
match ty::trait_item_of_item(&self.analysis.ty_cx,
|
||||
def_id) {
|
||||
None => None,
|
||||
Some(ty::MethodTraitItemId(decl_id)) => Some(decl_id),
|
||||
Some(decl_id) => Some(decl_id.def_id()),
|
||||
};
|
||||
|
||||
// This incantation is required if the method referenced is a
|
||||
@@ -905,6 +900,7 @@ fn process_method_call(&mut self,
|
||||
ty::MethodTraitItem(method) => {
|
||||
method.provided_source.unwrap_or(def_id)
|
||||
}
|
||||
ty::TypeTraitItem(_) => def_id,
|
||||
};
|
||||
(Some(def_id), decl_id)
|
||||
}
|
||||
@@ -913,23 +909,15 @@ fn process_method_call(&mut self,
|
||||
let trait_item = ty::trait_item(&self.analysis.ty_cx,
|
||||
mp.trait_ref.def_id,
|
||||
mp.method_num);
|
||||
match trait_item {
|
||||
ty::MethodTraitItem(method) => {
|
||||
(None, Some(method.def_id))
|
||||
}
|
||||
}
|
||||
},
|
||||
(None, Some(trait_item.def_id()))
|
||||
}
|
||||
typeck::MethodObject(ref mo) => {
|
||||
// method invoked on a trait instance
|
||||
let trait_item = ty::trait_item(&self.analysis.ty_cx,
|
||||
mo.trait_ref.def_id,
|
||||
mo.method_num);
|
||||
match trait_item {
|
||||
ty::MethodTraitItem(method) => {
|
||||
(None, Some(method.def_id))
|
||||
}
|
||||
}
|
||||
},
|
||||
(None, Some(trait_item.def_id()))
|
||||
}
|
||||
};
|
||||
let sub_span = self.span.sub_span_for_meth_name(ex.span);
|
||||
self.fmt.meth_call_str(ex.span,
|
||||
@@ -1139,7 +1127,8 @@ fn visit_trait_item(&mut self, tm: &ast::TraitItem) {
|
||||
qualname,
|
||||
method_type.id);
|
||||
}
|
||||
ast::ProvidedMethod(ref method) => self.process_method(&**method)
|
||||
ast::ProvidedMethod(ref method) => self.process_method(&**method),
|
||||
ast::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
use syntax::{attr, visit};
|
||||
use syntax::ast;
|
||||
use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant};
|
||||
use syntax::ast::{Item, RequiredMethod, ProvidedMethod, TraitItem, TypeMethod, Method};
|
||||
use syntax::ast::{Generics, StructDef, StructField, Ident};
|
||||
use syntax::ast::{Item, RequiredMethod, ProvidedMethod, TraitItem};
|
||||
use syntax::ast::{TypeMethod, Method, Generics, StructDef, StructField};
|
||||
use syntax::ast::{Ident, TypeTraitItem};
|
||||
use syntax::ast_util::is_local;
|
||||
use syntax::attr::Stability;
|
||||
use syntax::visit::{FnKind, FkMethod, Visitor};
|
||||
@@ -79,9 +80,13 @@ fn visit_trait_item(&mut self, t: &TraitItem) {
|
||||
RequiredMethod(TypeMethod {id, ref attrs, ..}) => (id, attrs),
|
||||
|
||||
// work around lack of pattern matching for @ types
|
||||
ProvidedMethod(ref method) => match **method {
|
||||
Method {id, ref attrs, ..} => (id, attrs)
|
||||
ProvidedMethod(ref method) => {
|
||||
match **method {
|
||||
Method {attrs: ref attrs, id: id, ..} => (id, attrs),
|
||||
}
|
||||
}
|
||||
|
||||
TypeTraitItem(ref typedef) => (typedef.id, &typedef.attrs),
|
||||
};
|
||||
self.annotate(id, attrs, |v| visit::walk_trait_item(v, t));
|
||||
}
|
||||
|
||||
@@ -630,7 +630,12 @@ fn fold_ty(&mut self, t: ty::t) -> ty::t {
|
||||
|
||||
let t1 = match ty::get(t).sty {
|
||||
ty::ty_param(p) => {
|
||||
check(self, p, t, self.substs.types.opt_get(p.space, p.idx))
|
||||
check(self,
|
||||
p,
|
||||
t,
|
||||
self.substs.types.opt_get(p.space, p.idx),
|
||||
p.space,
|
||||
p.idx)
|
||||
}
|
||||
_ => {
|
||||
ty_fold::super_fold_ty(self, t)
|
||||
@@ -648,7 +653,9 @@ fn fold_ty(&mut self, t: ty::t) -> ty::t {
|
||||
fn check(this: &SubstFolder,
|
||||
p: ty::ParamTy,
|
||||
source_ty: ty::t,
|
||||
opt_ty: Option<&ty::t>)
|
||||
opt_ty: Option<&ty::t>,
|
||||
space: ParamSpace,
|
||||
index: uint)
|
||||
-> ty::t {
|
||||
match opt_ty {
|
||||
Some(t) => *t,
|
||||
@@ -656,10 +663,12 @@ fn check(this: &SubstFolder,
|
||||
let span = this.span.unwrap_or(DUMMY_SP);
|
||||
this.tcx().sess.span_bug(
|
||||
span,
|
||||
format!("Type parameter `{}` ({}) out of range \
|
||||
format!("Type parameter `{}` ({}/{}/{}) out of range \
|
||||
when substituting (root type={})",
|
||||
p.repr(this.tcx()),
|
||||
source_ty.repr(this.tcx()),
|
||||
space,
|
||||
index,
|
||||
this.root_ty.repr(this.tcx())).as_slice());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1375,6 +1375,10 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
|
||||
tcx.sess.bug("unexpected variant: required trait method \
|
||||
in has_nested_returns")
|
||||
}
|
||||
ast::TypeTraitItem(_) => {
|
||||
tcx.sess.bug("unexpected variant: type trait item in \
|
||||
has_nested_returns")
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(ast_map::NodeImplItem(ii)) => {
|
||||
@@ -1391,6 +1395,10 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
|
||||
ast::MethMac(_) => tcx.sess.bug("unexpanded macro")
|
||||
}
|
||||
}
|
||||
ast::TypeImplItem(_) => {
|
||||
tcx.sess.bug("unexpected variant: type impl item in \
|
||||
has_nested_returns")
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(ast_map::NodeExpr(e)) => {
|
||||
@@ -2779,9 +2787,9 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
|
||||
ast_map::NodeTraitItem(trait_method) => {
|
||||
debug!("get_item_val(): processing a NodeTraitItem");
|
||||
match *trait_method {
|
||||
ast::RequiredMethod(_) => {
|
||||
ccx.sess().bug("unexpected variant: required trait method in \
|
||||
get_item_val()");
|
||||
ast::RequiredMethod(_) | ast::TypeTraitItem(_) => {
|
||||
ccx.sess().bug("unexpected variant: required trait \
|
||||
method in get_item_val()");
|
||||
}
|
||||
ast::ProvidedMethod(ref m) => {
|
||||
register_method(ccx, id, &**m)
|
||||
@@ -2792,6 +2800,11 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
|
||||
ast_map::NodeImplItem(ii) => {
|
||||
match *ii {
|
||||
ast::MethodImplItem(ref m) => register_method(ccx, id, &**m),
|
||||
ast::TypeImplItem(ref typedef) => {
|
||||
ccx.sess().span_bug(typedef.span,
|
||||
"unexpected variant: required impl \
|
||||
method in get_item_val()")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, def: def::Def, ref_expr: &ast::
|
||||
datum_callee(bcx, ref_expr)
|
||||
}
|
||||
def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) |
|
||||
def::DefTy(..) | def::DefPrimTy(..) |
|
||||
def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) |
|
||||
def::DefUse(..) | def::DefTyParamBinder(..) |
|
||||
def::DefRegion(..) | def::DefLabel(..) | def::DefTyParam(..) |
|
||||
def::DefSelfTy(..) | def::DefMethod(..) => {
|
||||
@@ -458,6 +458,10 @@ pub fn trans_fn_ref_with_substs(
|
||||
|
||||
(true, source_id, new_substs)
|
||||
}
|
||||
ty::TypeTraitItem(_) => {
|
||||
bcx.tcx().sess.bug("trans_fn_ref_with_vtables() tried \
|
||||
to translate an associated type?!")
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1153,6 +1153,11 @@ pub fn create_function_debug_context(cx: &CrateContext,
|
||||
method.span,
|
||||
true)
|
||||
}
|
||||
ast::TypeImplItem(ref typedef) => {
|
||||
cx.sess().span_bug(typedef.span,
|
||||
"create_function_debug_context() \
|
||||
called on associated type?!")
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_map::NodeExpr(ref expr) => {
|
||||
|
||||
@@ -156,6 +156,9 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
|
||||
// don't.
|
||||
local_def(mth.id)
|
||||
}
|
||||
ast::TypeTraitItem(_) => {
|
||||
ccx.sess().bug("found TypeTraitItem IITraitItem")
|
||||
}
|
||||
}
|
||||
}
|
||||
csearch::found(&ast::IIImplItem(impl_did, ref impl_item)) => {
|
||||
@@ -185,6 +188,9 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
|
||||
}
|
||||
local_def(mth.id)
|
||||
}
|
||||
ast::TypeImplItem(_) => {
|
||||
ccx.sess().bug("found TypeImplItem IIImplItem")
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -71,6 +71,7 @@ pub fn trans_impl(ccx: &CrateContext,
|
||||
ast::MethodImplItem(ref method) => {
|
||||
visit::walk_method_helper(&mut v, &**method);
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -100,6 +101,7 @@ pub fn trans_impl(ccx: &CrateContext,
|
||||
};
|
||||
visit::walk_method_helper(&mut v, &**method);
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,7 +185,11 @@ pub fn trans_static_method_callee(bcx: Block,
|
||||
ast_map::NodeTraitItem(method) => {
|
||||
let ident = match *method {
|
||||
ast::RequiredMethod(ref m) => m.ident,
|
||||
ast::ProvidedMethod(ref m) => m.pe_ident()
|
||||
ast::ProvidedMethod(ref m) => m.pe_ident(),
|
||||
ast::TypeTraitItem(_) => {
|
||||
bcx.tcx().sess.bug("trans_static_method_callee() on \
|
||||
an associated type?!")
|
||||
}
|
||||
};
|
||||
ident.name
|
||||
}
|
||||
@@ -294,14 +300,10 @@ fn method_with_name(ccx: &CrateContext, impl_id: ast::DefId, name: ast::Name)
|
||||
.expect("could not find impl while translating");
|
||||
let meth_did = impl_items.iter()
|
||||
.find(|&did| {
|
||||
match *did {
|
||||
ty::MethodTraitItemId(did) => {
|
||||
ty::impl_or_trait_item(ccx.tcx(),
|
||||
did).ident()
|
||||
.name ==
|
||||
name
|
||||
}
|
||||
}
|
||||
ty::impl_or_trait_item(ccx.tcx(),
|
||||
did.def_id()).ident()
|
||||
.name ==
|
||||
name
|
||||
}).expect("could not find method while \
|
||||
translating");
|
||||
|
||||
@@ -323,6 +325,10 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let impl_did = vtable_impl.impl_def_id;
|
||||
let mname = match ty::trait_item(ccx.tcx(), trait_id, n_method) {
|
||||
ty::MethodTraitItem(method) => method.ident,
|
||||
ty::TypeTraitItem(_) => {
|
||||
bcx.tcx().sess.bug("can't monomorphize an associated \
|
||||
type")
|
||||
}
|
||||
};
|
||||
let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name);
|
||||
|
||||
@@ -693,7 +699,7 @@ fn emit_vtable_methods(bcx: Block,
|
||||
ty::populate_implementations_for_trait_if_necessary(bcx.tcx(), trt_id);
|
||||
|
||||
let trait_item_def_ids = ty::trait_item_def_ids(tcx, trt_id);
|
||||
trait_item_def_ids.iter().map(|method_def_id| {
|
||||
trait_item_def_ids.iter().flat_map(|method_def_id| {
|
||||
let method_def_id = method_def_id.def_id();
|
||||
let ident = ty::impl_or_trait_item(tcx, method_def_id).ident();
|
||||
// The substitutions we have are on the impl, so we grab
|
||||
@@ -710,7 +716,7 @@ fn emit_vtable_methods(bcx: Block,
|
||||
debug!("(making impl vtable) method has self or type \
|
||||
params: {}",
|
||||
token::get_ident(ident));
|
||||
C_null(Type::nil(ccx).ptr_to())
|
||||
Some(C_null(Type::nil(ccx).ptr_to())).move_iter()
|
||||
} else {
|
||||
let mut fn_ref = trans_fn_ref_with_substs(
|
||||
bcx,
|
||||
@@ -724,9 +730,12 @@ fn emit_vtable_methods(bcx: Block,
|
||||
m_id,
|
||||
substs.clone());
|
||||
}
|
||||
fn_ref
|
||||
Some(fn_ref).move_iter()
|
||||
}
|
||||
}
|
||||
ty::TypeTraitItem(_) => {
|
||||
None.move_iter()
|
||||
}
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
||||
@@ -231,6 +231,9 @@ pub fn monomorphic_fn(ccx: &CrateContext,
|
||||
}
|
||||
d
|
||||
}
|
||||
ast::TypeImplItem(_) => {
|
||||
ccx.sess().bug("can't monomorphize an associated type")
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_map::NodeTraitItem(method) => {
|
||||
|
||||
@@ -92,6 +92,7 @@ pub fn visit(&mut self, ty_name: &str, args: &[ValueRef]) {
|
||||
format!("couldn't find visit method for {}", ty_name).as_slice());
|
||||
let method = match self.visitor_items[mth_idx] {
|
||||
ty::MethodTraitItem(ref method) => (*method).clone(),
|
||||
ty::TypeTraitItem(_) => return,
|
||||
};
|
||||
let mth_ty = ty::mk_bare_fn(tcx, method.fty.clone());
|
||||
debug!("Emit call visit method: visit_{}: {}", ty_name, ty_to_string(tcx, mth_ty));
|
||||
|
||||
+148
-10
@@ -97,30 +97,37 @@ pub fn id(&self) -> ast::DefId {
|
||||
#[deriving(Clone)]
|
||||
pub enum ImplOrTraitItem {
|
||||
MethodTraitItem(Rc<Method>),
|
||||
TypeTraitItem(Rc<AssociatedType>),
|
||||
}
|
||||
|
||||
impl ImplOrTraitItem {
|
||||
fn id(&self) -> ImplOrTraitItemId {
|
||||
match *self {
|
||||
MethodTraitItem(ref method) => MethodTraitItemId(method.def_id),
|
||||
TypeTraitItem(ref associated_type) => {
|
||||
TypeTraitItemId(associated_type.def_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn def_id(&self) -> ast::DefId {
|
||||
match *self {
|
||||
MethodTraitItem(ref method) => method.def_id,
|
||||
TypeTraitItem(ref associated_type) => associated_type.def_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ident(&self) -> ast::Ident {
|
||||
match *self {
|
||||
MethodTraitItem(ref method) => method.ident,
|
||||
TypeTraitItem(ref associated_type) => associated_type.ident,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn container(&self) -> ImplOrTraitItemContainer {
|
||||
match *self {
|
||||
MethodTraitItem(ref method) => method.container,
|
||||
TypeTraitItem(ref associated_type) => associated_type.container,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,12 +135,14 @@ pub fn container(&self) -> ImplOrTraitItemContainer {
|
||||
#[deriving(Clone)]
|
||||
pub enum ImplOrTraitItemId {
|
||||
MethodTraitItemId(ast::DefId),
|
||||
TypeTraitItemId(ast::DefId),
|
||||
}
|
||||
|
||||
impl ImplOrTraitItemId {
|
||||
pub fn def_id(&self) -> ast::DefId {
|
||||
match *self {
|
||||
MethodTraitItemId(def_id) => def_id,
|
||||
TypeTraitItemId(def_id) => def_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,6 +191,14 @@ pub fn container_id(&self) -> ast::DefId {
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct AssociatedType {
|
||||
pub ident: ast::Ident,
|
||||
pub vis: ast::Visibility,
|
||||
pub def_id: ast::DefId,
|
||||
pub container: ImplOrTraitItemContainer,
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
||||
pub struct mt {
|
||||
pub ty: t,
|
||||
@@ -556,6 +573,13 @@ pub struct ctxt<'tcx> {
|
||||
|
||||
/// Maps closures to their capture clauses.
|
||||
pub capture_modes: RefCell<CaptureModeMap>,
|
||||
|
||||
/// Maps def IDs to true if and only if they're associated types.
|
||||
pub associated_types: RefCell<DefIdMap<bool>>,
|
||||
|
||||
/// Maps def IDs of traits to information about their associated types.
|
||||
pub trait_associated_types:
|
||||
RefCell<DefIdMap<Rc<Vec<AssociatedTypeInfo>>>>,
|
||||
}
|
||||
|
||||
pub enum tbox_flag {
|
||||
@@ -1179,6 +1203,7 @@ pub struct TypeParameterDef {
|
||||
pub def_id: ast::DefId,
|
||||
pub space: subst::ParamSpace,
|
||||
pub index: uint,
|
||||
pub associated_with: Option<ast::DefId>,
|
||||
pub bounds: ParamBounds,
|
||||
pub default: Option<ty::t>,
|
||||
}
|
||||
@@ -1238,7 +1263,7 @@ pub struct ParameterEnvironment {
|
||||
/// the "outer" view of a type or method to the "inner" view.
|
||||
/// In general, this means converting from bound parameters to
|
||||
/// free parameters. Since we currently represent bound/free type
|
||||
/// parameters in the same way, this only has an affect on regions.
|
||||
/// parameters in the same way, this only has an effect on regions.
|
||||
pub free_substs: Substs,
|
||||
|
||||
/// Bounds on the various type parameters
|
||||
@@ -1275,8 +1300,19 @@ pub fn for_item(cx: &ctxt, id: NodeId) -> ParameterEnvironment {
|
||||
method_generics,
|
||||
method.pe_body().id)
|
||||
}
|
||||
TypeTraitItem(_) => {
|
||||
cx.sess
|
||||
.bug("ParameterEnvironment::from_item(): \
|
||||
can't create a parameter environment \
|
||||
for type trait items")
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::TypeImplItem(_) => {
|
||||
cx.sess.bug("ParameterEnvironment::from_item(): \
|
||||
can't create a parameter environment \
|
||||
for type impl items")
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(ast_map::NodeTraitItem(trait_method)) => {
|
||||
@@ -1299,8 +1335,19 @@ pub fn for_item(cx: &ctxt, id: NodeId) -> ParameterEnvironment {
|
||||
method_generics,
|
||||
method.pe_body().id)
|
||||
}
|
||||
TypeTraitItem(_) => {
|
||||
cx.sess
|
||||
.bug("ParameterEnvironment::from_item(): \
|
||||
can't create a parameter environment \
|
||||
for type trait items")
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::TypeTraitItem(_) => {
|
||||
cx.sess.bug("ParameterEnvironment::from_item(): \
|
||||
can't create a parameter environment \
|
||||
for type trait items")
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(ast_map::NodeItem(item)) => {
|
||||
@@ -1476,6 +1523,8 @@ pub fn mk_ctxt<'tcx>(s: Session,
|
||||
transmute_restrictions: RefCell::new(Vec::new()),
|
||||
stability: RefCell::new(stability),
|
||||
capture_modes: RefCell::new(capture_modes),
|
||||
associated_types: RefCell::new(DefIdMap::new()),
|
||||
trait_associated_types: RefCell::new(DefIdMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1894,6 +1943,10 @@ pub fn for_def(def: &TypeParameterDef) -> ParamTy {
|
||||
pub fn to_ty(self, tcx: &ty::ctxt) -> ty::t {
|
||||
ty::mk_param(tcx, self.space, self.idx, self.def_id)
|
||||
}
|
||||
|
||||
pub fn is_self(&self) -> bool {
|
||||
self.space == subst::SelfSpace && self.idx == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl ItemSubsts {
|
||||
@@ -3543,6 +3596,10 @@ pub fn method_call_type_param_defs<'tcx, T>(typer: &T,
|
||||
}) => {
|
||||
match ty::trait_item(typer.tcx(), trait_ref.def_id, n_mth) {
|
||||
ty::MethodTraitItem(method) => method.generics.types.clone(),
|
||||
ty::TypeTraitItem(_) => {
|
||||
typer.tcx().sess.bug("method_call_type_param_defs() \
|
||||
called on associated type")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4007,12 +4064,19 @@ pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec<Rc<Method>> {
|
||||
Some(ast_map::NodeItem(item)) => {
|
||||
match item.node {
|
||||
ItemTrait(_, _, _, ref ms) => {
|
||||
ms.iter().filter_map(|m| match *m {
|
||||
ast::RequiredMethod(_) => None,
|
||||
ast::ProvidedMethod(ref m) => {
|
||||
match impl_or_trait_item(cx,
|
||||
ast_util::local_def(m.id)) {
|
||||
MethodTraitItem(m) => Some(m),
|
||||
let (_, p) =
|
||||
ast_util::split_trait_methods(ms.as_slice());
|
||||
p.iter()
|
||||
.map(|m| {
|
||||
match impl_or_trait_item(
|
||||
cx,
|
||||
ast_util::local_def(m.id)) {
|
||||
MethodTraitItem(m) => m,
|
||||
TypeTraitItem(_) => {
|
||||
cx.sess.bug("provided_trait_methods(): \
|
||||
split_trait_methods() put \
|
||||
associated types in the \
|
||||
provided method bucket?!")
|
||||
}
|
||||
}
|
||||
}).collect()
|
||||
@@ -4097,6 +4161,75 @@ pub fn impl_or_trait_item(cx: &ctxt, id: ast::DefId) -> ImplOrTraitItem {
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns true if the given ID refers to an associated type and false if it
|
||||
/// refers to anything else.
|
||||
pub fn is_associated_type(cx: &ctxt, id: ast::DefId) -> bool {
|
||||
let result = match cx.associated_types.borrow_mut().find(&id) {
|
||||
Some(result) => return *result,
|
||||
None if id.krate == ast::LOCAL_CRATE => {
|
||||
match cx.impl_or_trait_items.borrow().find(&id) {
|
||||
Some(ref item) => {
|
||||
match **item {
|
||||
TypeTraitItem(_) => true,
|
||||
MethodTraitItem(_) => false,
|
||||
}
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
None => {
|
||||
csearch::is_associated_type(&cx.sess.cstore, id)
|
||||
}
|
||||
};
|
||||
|
||||
cx.associated_types.borrow_mut().insert(id, result);
|
||||
result
|
||||
}
|
||||
|
||||
/// Returns the parameter index that the given associated type corresponds to.
|
||||
pub fn associated_type_parameter_index(cx: &ctxt,
|
||||
trait_def: &TraitDef,
|
||||
associated_type_id: ast::DefId)
|
||||
-> uint {
|
||||
for type_parameter_def in trait_def.generics.types.iter() {
|
||||
if type_parameter_def.def_id == associated_type_id {
|
||||
return type_parameter_def.index
|
||||
}
|
||||
}
|
||||
cx.sess.bug("couldn't find associated type parameter index")
|
||||
}
|
||||
|
||||
#[deriving(PartialEq, Eq)]
|
||||
pub struct AssociatedTypeInfo {
|
||||
pub def_id: ast::DefId,
|
||||
pub index: uint,
|
||||
pub ident: ast::Ident,
|
||||
}
|
||||
|
||||
impl PartialOrd for AssociatedTypeInfo {
|
||||
fn partial_cmp(&self, other: &AssociatedTypeInfo) -> Option<Ordering> {
|
||||
Some(self.index.cmp(&other.index))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for AssociatedTypeInfo {
|
||||
fn cmp(&self, other: &AssociatedTypeInfo) -> Ordering {
|
||||
self.index.cmp(&other.index)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the associated types belonging to the given trait, in parameter
|
||||
/// order.
|
||||
pub fn associated_types_for_trait(cx: &ctxt, trait_id: ast::DefId)
|
||||
-> Rc<Vec<AssociatedTypeInfo>> {
|
||||
cx.trait_associated_types
|
||||
.borrow()
|
||||
.find(&trait_id)
|
||||
.expect("associated_types_for_trait(): trait not found, try calling \
|
||||
ensure_associated_types()")
|
||||
.clone()
|
||||
}
|
||||
|
||||
pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
|
||||
-> Rc<Vec<ImplOrTraitItemId>> {
|
||||
lookup_locally_or_in_crate_store("trait_item_def_ids",
|
||||
@@ -4978,6 +5111,7 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
|
||||
.insert(method_def_id, source);
|
||||
}
|
||||
}
|
||||
TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5025,6 +5159,7 @@ pub fn populate_implementations_for_trait_if_necessary(
|
||||
.insert(method_def_id, source);
|
||||
}
|
||||
}
|
||||
TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5108,9 +5243,7 @@ pub fn trait_item_of_item(tcx: &ctxt, def_id: ast::DefId)
|
||||
Some(m) => m.clone(),
|
||||
None => return None,
|
||||
};
|
||||
let name = match impl_item {
|
||||
MethodTraitItem(method) => method.ident.name,
|
||||
};
|
||||
let name = impl_item.ident().name;
|
||||
match trait_of_item(tcx, def_id) {
|
||||
Some(trait_did) => {
|
||||
let trait_items = ty::trait_items(tcx, trait_did);
|
||||
@@ -5364,6 +5497,11 @@ fn push_types_from_defs(tcx: &ty::ctxt,
|
||||
space: subst::ParamSpace,
|
||||
defs: &[TypeParameterDef]) {
|
||||
for (i, def) in defs.iter().enumerate() {
|
||||
debug!("construct_parameter_environment(): push_types_from_defs: \
|
||||
space={} def={} index={}",
|
||||
space,
|
||||
def.repr(tcx),
|
||||
i);
|
||||
let ty = ty::mk_param(tcx, space, i, def.def_id);
|
||||
types.push(space, ty);
|
||||
}
|
||||
|
||||
@@ -301,6 +301,7 @@ fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TypeParame
|
||||
def_id: self.def_id,
|
||||
space: self.space,
|
||||
index: self.index,
|
||||
associated_with: self.associated_with,
|
||||
bounds: self.bounds.fold_with(folder),
|
||||
default: self.default.fold_with(folder),
|
||||
}
|
||||
|
||||
@@ -70,14 +70,30 @@
|
||||
use syntax::abi;
|
||||
use syntax::{ast, ast_util};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::parse::token;
|
||||
|
||||
pub trait AstConv<'tcx> {
|
||||
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
|
||||
fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype;
|
||||
fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef>;
|
||||
|
||||
// what type should we use when a type is omitted?
|
||||
/// What type should we use when a type is omitted?
|
||||
fn ty_infer(&self, span: Span) -> ty::t;
|
||||
|
||||
/// Returns true if associated types from the given trait and type are
|
||||
/// allowed to be used here and false otherwise.
|
||||
fn associated_types_of_trait_are_valid(&self,
|
||||
ty: ty::t,
|
||||
trait_id: ast::DefId)
|
||||
-> bool;
|
||||
|
||||
/// Returns the binding of the given associated type for some type.
|
||||
fn associated_type_binding(&self,
|
||||
span: Span,
|
||||
ty: Option<ty::t>,
|
||||
trait_id: ast::DefId,
|
||||
associated_type_id: ast::DefId)
|
||||
-> ty::t;
|
||||
}
|
||||
|
||||
pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
|
||||
@@ -152,13 +168,16 @@ pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
r
|
||||
}
|
||||
|
||||
fn ast_path_substs<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
decl_generics: &ty::Generics,
|
||||
self_ty: Option<ty::t>,
|
||||
path: &ast::Path) -> Substs
|
||||
{
|
||||
fn ast_path_substs<'tcx,AC,RS>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
decl_def_id: ast::DefId,
|
||||
decl_generics: &ty::Generics,
|
||||
self_ty: Option<ty::t>,
|
||||
associated_ty: Option<ty::t>,
|
||||
path: &ast::Path)
|
||||
-> Substs
|
||||
where AC: AstConv<'tcx>, RS: RegionScope {
|
||||
/*!
|
||||
* Given a path `path` that refers to an item `I` with the
|
||||
* declared generics `decl_generics`, returns an appropriate
|
||||
@@ -206,10 +225,17 @@ fn ast_path_substs<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
// Convert the type parameters supplied by the user.
|
||||
let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
|
||||
let supplied_ty_param_count = path.segments.iter().flat_map(|s| s.types.iter()).count();
|
||||
let formal_ty_param_count = ty_param_defs.len();
|
||||
let required_ty_param_count = ty_param_defs.iter()
|
||||
.take_while(|x| x.default.is_none())
|
||||
.count();
|
||||
let formal_ty_param_count =
|
||||
ty_param_defs.iter()
|
||||
.take_while(|x| !ty::is_associated_type(tcx, x.def_id))
|
||||
.count();
|
||||
let required_ty_param_count =
|
||||
ty_param_defs.iter()
|
||||
.take_while(|x| {
|
||||
x.default.is_none() &&
|
||||
!ty::is_associated_type(tcx, x.def_id)
|
||||
})
|
||||
.count();
|
||||
if supplied_ty_param_count < required_ty_param_count {
|
||||
let expected = if required_ty_param_count < formal_ty_param_count {
|
||||
"expected at least"
|
||||
@@ -242,9 +268,11 @@ fn ast_path_substs<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
"add #![feature(default_type_params)] to the crate attributes to enable");
|
||||
}
|
||||
|
||||
let tps = path.segments.iter().flat_map(|s| s.types.iter())
|
||||
.map(|a_t| ast_ty_to_ty(this, rscope, &**a_t))
|
||||
.collect();
|
||||
let tps = path.segments
|
||||
.iter()
|
||||
.flat_map(|s| s.types.iter())
|
||||
.map(|a_t| ast_ty_to_ty(this, rscope, &**a_t))
|
||||
.collect();
|
||||
|
||||
let mut substs = Substs::new_type(tps, regions);
|
||||
|
||||
@@ -263,24 +291,48 @@ fn ast_path_substs<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
}
|
||||
|
||||
for param in ty_param_defs.slice_from(supplied_ty_param_count).iter() {
|
||||
let default = param.default.unwrap();
|
||||
let default = default.subst_spanned(tcx, &substs, Some(path.span));
|
||||
substs.types.push(TypeSpace, default);
|
||||
match param.default {
|
||||
Some(default) => {
|
||||
// This is a default type parameter.
|
||||
let default = default.subst_spanned(tcx,
|
||||
&substs,
|
||||
Some(path.span));
|
||||
substs.types.push(TypeSpace, default);
|
||||
}
|
||||
None => {
|
||||
// This is an associated type.
|
||||
substs.types.push(
|
||||
TypeSpace,
|
||||
this.associated_type_binding(path.span,
|
||||
associated_ty,
|
||||
decl_def_id,
|
||||
param.def_id))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
substs
|
||||
}
|
||||
|
||||
pub fn ast_path_to_trait_ref<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
trait_def_id: ast::DefId,
|
||||
self_ty: Option<ty::t>,
|
||||
path: &ast::Path) -> Rc<ty::TraitRef> {
|
||||
pub fn ast_path_to_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
rscope: &RS,
|
||||
trait_def_id: ast::DefId,
|
||||
self_ty: Option<ty::t>,
|
||||
associated_type: Option<ty::t>,
|
||||
path: &ast::Path)
|
||||
-> Rc<ty::TraitRef>
|
||||
where AC: AstConv<'tcx>,
|
||||
RS: RegionScope {
|
||||
let trait_def = this.get_trait_def(trait_def_id);
|
||||
Rc::new(ty::TraitRef {
|
||||
def_id: trait_def_id,
|
||||
substs: ast_path_substs(this, rscope, &trait_def.generics, self_ty, path)
|
||||
substs: ast_path_substs(this,
|
||||
rscope,
|
||||
trait_def_id,
|
||||
&trait_def.generics,
|
||||
self_ty,
|
||||
associated_type,
|
||||
path)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -289,15 +341,20 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
rscope: &RS,
|
||||
did: ast::DefId,
|
||||
path: &ast::Path)
|
||||
-> TypeAndSubsts
|
||||
{
|
||||
-> TypeAndSubsts {
|
||||
let tcx = this.tcx();
|
||||
let ty::Polytype {
|
||||
generics: generics,
|
||||
ty: decl_ty
|
||||
} = this.get_item_ty(did);
|
||||
|
||||
let substs = ast_path_substs(this, rscope, &generics, None, path);
|
||||
let substs = ast_path_substs(this,
|
||||
rscope,
|
||||
did,
|
||||
&generics,
|
||||
None,
|
||||
None,
|
||||
path);
|
||||
let ty = decl_ty.subst(tcx, &substs);
|
||||
TypeAndSubsts { substs: substs, ty: ty }
|
||||
}
|
||||
@@ -333,7 +390,7 @@ pub fn ast_path_to_ty_relaxed<'tcx, AC: AstConv<'tcx>,
|
||||
Substs::new(VecPerParamSpace::params_from_type(type_params),
|
||||
VecPerParamSpace::params_from_type(region_params))
|
||||
} else {
|
||||
ast_path_substs(this, rscope, &generics, None, path)
|
||||
ast_path_substs(this, rscope, did, &generics, None, None, path)
|
||||
};
|
||||
|
||||
let ty = decl_ty.subst(tcx, &substs);
|
||||
@@ -639,8 +696,12 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
}
|
||||
}
|
||||
Some(&def::DefTrait(trait_def_id)) => {
|
||||
let result = ast_path_to_trait_ref(
|
||||
this, rscope, trait_def_id, None, path);
|
||||
let result = ast_path_to_trait_ref(this,
|
||||
rscope,
|
||||
trait_def_id,
|
||||
None,
|
||||
None,
|
||||
path);
|
||||
let bounds = match *opt_bounds {
|
||||
None => {
|
||||
conv_existential_bounds(this,
|
||||
@@ -686,6 +747,52 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
constr(ast_ty_to_ty(this, rscope, a_seq_ty))
|
||||
}
|
||||
|
||||
fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
|
||||
rscope: &RS,
|
||||
trait_path: &ast::Path,
|
||||
for_ast_type: &ast::Ty,
|
||||
trait_type_id: ast::DefId,
|
||||
span: Span)
|
||||
-> ty::t
|
||||
where AC: AstConv<'tcx>, RS: RegionScope {
|
||||
// Find the trait that this associated type belongs to.
|
||||
let trait_did = match ty::impl_or_trait_item(this.tcx(),
|
||||
trait_type_id).container() {
|
||||
ty::ImplContainer(_) => {
|
||||
this.tcx().sess.span_bug(span,
|
||||
"associated_ty_to_ty(): impl associated \
|
||||
types shouldn't go through this \
|
||||
function")
|
||||
}
|
||||
ty::TraitContainer(trait_id) => trait_id,
|
||||
};
|
||||
|
||||
let for_type = ast_ty_to_ty(this, rscope, for_ast_type);
|
||||
if !this.associated_types_of_trait_are_valid(for_type, trait_did) {
|
||||
this.tcx().sess.span_err(span,
|
||||
"this associated type is not \
|
||||
allowed in this context");
|
||||
return ty::mk_err()
|
||||
}
|
||||
|
||||
let trait_ref = ast_path_to_trait_ref(this,
|
||||
rscope,
|
||||
trait_did,
|
||||
None,
|
||||
Some(for_type),
|
||||
trait_path);
|
||||
let trait_def = this.get_trait_def(trait_did);
|
||||
for type_parameter in trait_def.generics.types.iter() {
|
||||
if type_parameter.def_id == trait_type_id {
|
||||
return *trait_ref.substs.types.get(type_parameter.space,
|
||||
type_parameter.index)
|
||||
}
|
||||
}
|
||||
this.tcx().sess.span_bug(span,
|
||||
"this associated type didn't get added \
|
||||
as a parameter for some reason")
|
||||
}
|
||||
|
||||
// Parses the programmer's textual representation of a type into our
|
||||
// internal notion of a type.
|
||||
pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
@@ -816,8 +923,12 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
}
|
||||
match a_def {
|
||||
def::DefTrait(trait_def_id) => {
|
||||
let result = ast_path_to_trait_ref(
|
||||
this, rscope, trait_def_id, None, path);
|
||||
let result = ast_path_to_trait_ref(this,
|
||||
rscope,
|
||||
trait_def_id,
|
||||
None,
|
||||
None,
|
||||
path);
|
||||
let empty_bounds: &[ast::TyParamBound] = &[];
|
||||
let ast_bounds = match *bounds {
|
||||
Some(ref b) => b.as_slice(),
|
||||
@@ -856,6 +967,23 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
def::DefPrimTy(_) => {
|
||||
fail!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
|
||||
}
|
||||
def::DefAssociatedTy(trait_type_id) => {
|
||||
let path_str = tcx.map.path_to_string(
|
||||
tcx.map.get_parent(trait_type_id.node));
|
||||
tcx.sess.span_err(ast_ty.span,
|
||||
format!("ambiguous associated \
|
||||
type; specify the type \
|
||||
using the syntax `<Type \
|
||||
as {}>::{}`",
|
||||
path_str,
|
||||
token::get_ident(
|
||||
path.segments
|
||||
.last()
|
||||
.unwrap()
|
||||
.identifier)
|
||||
.get()).as_slice());
|
||||
ty::mk_err()
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.span_fatal(ast_ty.span,
|
||||
format!("found value name used \
|
||||
@@ -864,6 +992,28 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::TyQPath(ref qpath) => {
|
||||
match tcx.def_map.borrow().find(&ast_ty.id) {
|
||||
None => {
|
||||
tcx.sess.span_bug(ast_ty.span,
|
||||
"unbound qualified path")
|
||||
}
|
||||
Some(&def::DefAssociatedTy(trait_type_id)) => {
|
||||
associated_ty_to_ty(this,
|
||||
rscope,
|
||||
&qpath.trait_name,
|
||||
&*qpath.for_type,
|
||||
trait_type_id,
|
||||
ast_ty.span)
|
||||
}
|
||||
Some(_) => {
|
||||
tcx.sess.span_err(ast_ty.span,
|
||||
"this qualified path does not name \
|
||||
an associated type");
|
||||
ty::mk_err()
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::TyFixedLengthVec(ref ty, ref e) => {
|
||||
match const_eval::eval_const_expr_partial(tcx, &**e) {
|
||||
Ok(ref r) => {
|
||||
|
||||
@@ -226,6 +226,7 @@ fn get_method_index(tcx: &ty::ctxt,
|
||||
for trait_item in trait_items.iter() {
|
||||
match *trait_item {
|
||||
ty::MethodTraitItem(_) => method_count += 1,
|
||||
ty::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
true
|
||||
@@ -531,6 +532,11 @@ fn push_unboxed_closure_call_candidate_if_applicable(
|
||||
.clone();
|
||||
let method = match trait_item {
|
||||
ty::MethodTraitItem(method) => method,
|
||||
ty::TypeTraitItem(_) => {
|
||||
self.tcx().sess.bug(
|
||||
"push_unboxed_closure_call_candidates_if_applicable(): \
|
||||
unexpected associated type in function trait")
|
||||
}
|
||||
};
|
||||
|
||||
// Make sure it has the right name!
|
||||
@@ -730,11 +736,16 @@ fn push_inherent_candidates_from_bounds_inner(
|
||||
m.explicit_self != ty::StaticExplicitSelfCategory &&
|
||||
m.ident.name == self.m_name
|
||||
}
|
||||
ty::TypeTraitItem(_) => false,
|
||||
}
|
||||
}) {
|
||||
Some(pos) => {
|
||||
let method = match *trait_items.get(pos) {
|
||||
ty::MethodTraitItem(ref method) => (*method).clone(),
|
||||
ty::TypeTraitItem(_) => {
|
||||
tcx.sess.bug("typechecking associated type as \
|
||||
though it were a method")
|
||||
}
|
||||
};
|
||||
|
||||
match mk_cand(self,
|
||||
@@ -812,7 +823,10 @@ fn push_candidates_from_impl(&mut self,
|
||||
m.ident().name == self.m_name
|
||||
}) {
|
||||
Some(ty::MethodTraitItem(method)) => method,
|
||||
None => { return; } // No method with the right name.
|
||||
Some(ty::TypeTraitItem(_)) | None => {
|
||||
// No method with the right name.
|
||||
return
|
||||
}
|
||||
};
|
||||
|
||||
// determine the `self` of the impl with fresh
|
||||
@@ -1575,7 +1589,7 @@ fn report_candidate(&self, idx: uint, origin: &MethodOrigin) {
|
||||
// If we're reporting statics, we want to report the trait
|
||||
// definition if possible, rather than an impl
|
||||
match ty::trait_item_of_item(self.tcx(), impl_did) {
|
||||
None => {
|
||||
None | Some(TypeTraitItemId(_)) => {
|
||||
debug!("(report candidate) No trait method \
|
||||
found");
|
||||
impl_did
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
use std::rc::Rc;
|
||||
use std::slice;
|
||||
use syntax::abi;
|
||||
use syntax::ast::{ProvidedMethod, RequiredMethod};
|
||||
use syntax::ast::{ProvidedMethod, RequiredMethod, TypeTraitItem};
|
||||
use syntax::ast;
|
||||
use syntax::ast_map;
|
||||
use syntax::ast_util::{local_def, PostExpansionMethod};
|
||||
@@ -765,6 +765,9 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
ast::MethodImplItem(ref m) => {
|
||||
check_method_body(ccx, &impl_pty.generics, &**m);
|
||||
}
|
||||
ast::TypeImplItem(_) => {
|
||||
// Nothing to do here.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -793,6 +796,9 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
ProvidedMethod(ref m) => {
|
||||
check_method_body(ccx, &trait_def.generics, &**m);
|
||||
}
|
||||
TypeTraitItem(_) => {
|
||||
// Nothing to do.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -898,6 +904,20 @@ fn check_impl_items_against_trait(ccx: &CrateCtxt,
|
||||
&**trait_method_ty,
|
||||
&impl_trait_ref.substs);
|
||||
}
|
||||
_ => {
|
||||
// This is span_bug as it should have already been
|
||||
// caught in resolve.
|
||||
tcx.sess
|
||||
.span_bug(impl_method.span,
|
||||
format!("item `{}` is of a \
|
||||
different kind from \
|
||||
its trait `{}`",
|
||||
token::get_ident(
|
||||
impl_item_ty.ident()),
|
||||
pprust::path_to_string(
|
||||
&ast_trait_ref.path))
|
||||
.as_slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
@@ -913,10 +933,57 @@ fn check_impl_items_against_trait(ccx: &CrateCtxt,
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::TypeImplItem(ref typedef) => {
|
||||
let typedef_def_id = local_def(typedef.id);
|
||||
let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
|
||||
typedef_def_id);
|
||||
|
||||
// If this is an impl of an associated type, find the
|
||||
// corresponding type definition in the trait.
|
||||
let opt_associated_type =
|
||||
trait_items.iter()
|
||||
.find(|ti| {
|
||||
ti.ident().name == typedef_ty.ident().name
|
||||
});
|
||||
match opt_associated_type {
|
||||
Some(associated_type) => {
|
||||
match (associated_type, &typedef_ty) {
|
||||
(&ty::TypeTraitItem(_),
|
||||
&ty::TypeTraitItem(_)) => {}
|
||||
_ => {
|
||||
// This is `span_bug` as it should have
|
||||
// already been caught in resolve.
|
||||
tcx.sess
|
||||
.span_bug(typedef.span,
|
||||
format!("item `{}` is of a \
|
||||
different kind from \
|
||||
its trait `{}`",
|
||||
token::get_ident(
|
||||
typedef_ty.ident()),
|
||||
pprust::path_to_string(
|
||||
&ast_trait_ref.path))
|
||||
.as_slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// This is `span_bug` as it should have already been
|
||||
// caught in resolve.
|
||||
tcx.sess.span_bug(
|
||||
typedef.span,
|
||||
format!(
|
||||
"associated type `{}` is not a member of \
|
||||
trait `{}`",
|
||||
token::get_ident(typedef_ty.ident()),
|
||||
pprust::path_to_string(
|
||||
&ast_trait_ref.path)).as_slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for missing methods from trait
|
||||
// Check for missing items from trait
|
||||
let provided_methods = ty::provided_trait_methods(tcx,
|
||||
impl_trait_ref.def_id);
|
||||
let mut missing_methods = Vec::new();
|
||||
@@ -929,6 +996,7 @@ fn check_impl_items_against_trait(ccx: &CrateCtxt,
|
||||
ast::MethodImplItem(ref m) => {
|
||||
m.pe_ident().name == trait_method.ident.name
|
||||
}
|
||||
ast::TypeImplItem(_) => false,
|
||||
}
|
||||
});
|
||||
let is_provided =
|
||||
@@ -940,12 +1008,27 @@ fn check_impl_items_against_trait(ccx: &CrateCtxt,
|
||||
token::get_ident(trait_method.ident)));
|
||||
}
|
||||
}
|
||||
ty::TypeTraitItem(ref associated_type) => {
|
||||
let is_implemented = impl_items.iter().any(|ii| {
|
||||
match *ii {
|
||||
ast::TypeImplItem(ref typedef) => {
|
||||
typedef.ident.name == associated_type.ident.name
|
||||
}
|
||||
ast::MethodImplItem(_) => false,
|
||||
}
|
||||
});
|
||||
if !is_implemented {
|
||||
missing_methods.push(
|
||||
format!("`{}`",
|
||||
token::get_ident(associated_type.ident)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !missing_methods.is_empty() {
|
||||
span_err!(tcx.sess, impl_span, E0046,
|
||||
"not all trait methods implemented, missing: {}",
|
||||
"not all trait items implemented, missing: {}",
|
||||
missing_methods.connect(", "));
|
||||
}
|
||||
}
|
||||
@@ -969,7 +1052,8 @@ fn compare_impl_method(tcx: &ty::ctxt,
|
||||
impl_m_body_id: ast::NodeId,
|
||||
trait_m: &ty::Method,
|
||||
trait_to_impl_substs: &subst::Substs) {
|
||||
debug!("compare_impl_method()");
|
||||
debug!("compare_impl_method(trait_to_impl_substs={})",
|
||||
trait_to_impl_substs.repr(tcx));
|
||||
let infcx = infer::new_infer_ctxt(tcx);
|
||||
|
||||
// Try to give more informative error messages about self typing
|
||||
@@ -1138,11 +1222,13 @@ fn compare_impl_method(tcx: &ty::ctxt,
|
||||
// FIXME(pcwalton): We could be laxer here regarding sub- and super-
|
||||
// traits, but I doubt that'll be wanted often, so meh.
|
||||
for impl_trait_bound in impl_param_def.bounds.trait_bounds.iter() {
|
||||
debug!("compare_impl_method(): impl-trait-bound subst");
|
||||
let impl_trait_bound =
|
||||
impl_trait_bound.subst(tcx, &impl_to_skol_substs);
|
||||
|
||||
let mut ok = false;
|
||||
for trait_bound in trait_param_def.bounds.trait_bounds.iter() {
|
||||
debug!("compare_impl_method(): trait-bound subst");
|
||||
let trait_bound =
|
||||
trait_bound.subst(tcx, &trait_to_skol_substs);
|
||||
let infcx = infer::new_infer_ctxt(tcx);
|
||||
@@ -1185,6 +1271,9 @@ fn compare_impl_method(tcx: &ty::ctxt,
|
||||
// other words, anyone expecting to call a method with the type
|
||||
// from the trait, can safely call a method with the type from the
|
||||
// impl instead.
|
||||
debug!("checking trait method for compatibility: impl ty {}, trait ty {}",
|
||||
impl_fty.repr(tcx),
|
||||
trait_fty.repr(tcx));
|
||||
match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
|
||||
impl_fty, trait_fty) {
|
||||
Ok(()) => {}
|
||||
@@ -1513,6 +1602,21 @@ fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
|
||||
fn ty_infer(&self, _span: Span) -> ty::t {
|
||||
self.infcx().next_ty_var()
|
||||
}
|
||||
|
||||
fn associated_types_of_trait_are_valid(&self, _: ty::t, _: ast::DefId)
|
||||
-> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn associated_type_binding(&self,
|
||||
span: Span,
|
||||
_: Option<ty::t>,
|
||||
_: ast::DefId,
|
||||
_: ast::DefId)
|
||||
-> ty::t {
|
||||
self.tcx().sess.span_err(span, "unsupported associated type binding");
|
||||
ty::mk_err()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
@@ -4938,6 +5042,7 @@ pub fn polytype_for_def(fcx: &FnCtxt,
|
||||
}
|
||||
def::DefTrait(_) |
|
||||
def::DefTy(..) |
|
||||
def::DefAssociatedTy(..) |
|
||||
def::DefPrimTy(_) |
|
||||
def::DefTyParam(..)=> {
|
||||
fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
|
||||
@@ -5048,6 +5153,7 @@ pub fn instantiate_path(fcx: &FnCtxt,
|
||||
def::DefVariant(..) |
|
||||
def::DefTyParamBinder(..) |
|
||||
def::DefTy(..) |
|
||||
def::DefAssociatedTy(..) |
|
||||
def::DefTrait(..) |
|
||||
def::DefPrimTy(..) |
|
||||
def::DefTyParam(..) => {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
use middle::subst::{Substs};
|
||||
use middle::ty::get;
|
||||
use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId};
|
||||
use middle::ty::{lookup_item_type};
|
||||
use middle::ty::{TypeTraitItemId, lookup_item_type};
|
||||
use middle::ty::{t, ty_bool, ty_char, ty_bot, ty_box, ty_enum, ty_err};
|
||||
use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_nil, ty_open};
|
||||
use middle::ty::{ty_param, Polytype, ty_ptr};
|
||||
@@ -332,6 +332,9 @@ fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
|
||||
MethodTraitItemId(
|
||||
local_def(ast_method.id))
|
||||
}
|
||||
ast::TypeImplItem(ref typedef) => {
|
||||
TypeTraitItemId(local_def(typedef.id))
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
|
||||
@@ -393,6 +396,7 @@ fn add_external_impl(&self,
|
||||
.insert(item_def_id.def_id(), source);
|
||||
}
|
||||
}
|
||||
ty::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1082
-186
@@ -138,7 +138,13 @@ pub trait ToTy {
|
||||
fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t;
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ToTy for CrateCtxt<'a, 'tcx> {
|
||||
impl<'a,'tcx> ToTy for ImplCtxt<'a,'tcx> {
|
||||
fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t {
|
||||
ast_ty_to_ty(self, rs, ast_ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'tcx> ToTy for CrateCtxt<'a,'tcx> {
|
||||
fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t {
|
||||
ast_ty_to_ty(self, rs, ast_ty)
|
||||
}
|
||||
@@ -158,6 +164,9 @@ fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
|
||||
let abi = self.tcx.map.get_foreign_abi(id.node);
|
||||
ty_of_foreign_item(self, &*foreign_item, abi)
|
||||
}
|
||||
Some(ast_map::NodeTraitItem(trait_item)) => {
|
||||
ty_of_trait_item(self, &*trait_item)
|
||||
}
|
||||
x => {
|
||||
self.tcx.sess.bug(format!("unexpected sort of node \
|
||||
in get_item_ty(): {:?}",
|
||||
@@ -175,6 +184,22 @@ fn ty_infer(&self, span: Span) -> ty::t {
|
||||
"the type placeholder `_` is not allowed within types on item signatures.");
|
||||
ty::mk_err()
|
||||
}
|
||||
|
||||
fn associated_types_of_trait_are_valid(&self, _: ty::t, _: ast::DefId)
|
||||
-> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn associated_type_binding(&self,
|
||||
span: Span,
|
||||
_: Option<ty::t>,
|
||||
_: ast::DefId,
|
||||
_: ast::DefId)
|
||||
-> ty::t {
|
||||
self.tcx().sess.span_err(span, "associated types may not be \
|
||||
referenced here");
|
||||
ty::mk_err()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_enum_variant_types(ccx: &CrateCtxt,
|
||||
@@ -201,7 +226,10 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
|
||||
|
||||
ast::StructVariantKind(ref struct_def) => {
|
||||
let pty = Polytype {
|
||||
generics: ty_generics_for_type(ccx, generics),
|
||||
generics: ty_generics_for_type(
|
||||
ccx,
|
||||
generics,
|
||||
DontCreateTypeParametersForAssociatedTypes),
|
||||
ty: enum_ty
|
||||
};
|
||||
|
||||
@@ -214,7 +242,10 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
|
||||
};
|
||||
|
||||
let pty = Polytype {
|
||||
generics: ty_generics_for_type(ccx, generics),
|
||||
generics: ty_generics_for_type(
|
||||
ccx,
|
||||
generics,
|
||||
DontCreateTypeParametersForAssociatedTypes),
|
||||
ty: result_ty
|
||||
};
|
||||
|
||||
@@ -244,6 +275,7 @@ fn collect_trait_methods(ccx: &CrateCtxt,
|
||||
ccx,
|
||||
trait_id,
|
||||
&trait_def.generics,
|
||||
trait_items.as_slice(),
|
||||
&m.id,
|
||||
&m.ident,
|
||||
&m.explicit_self,
|
||||
@@ -257,6 +289,7 @@ fn collect_trait_methods(ccx: &CrateCtxt,
|
||||
ccx,
|
||||
trait_id,
|
||||
&trait_def.generics,
|
||||
trait_items.as_slice(),
|
||||
&m.id,
|
||||
&m.pe_ident(),
|
||||
m.pe_explicit_self(),
|
||||
@@ -265,6 +298,12 @@ fn collect_trait_methods(ccx: &CrateCtxt,
|
||||
&m.pe_fn_style(),
|
||||
&*m.pe_fn_decl())
|
||||
}
|
||||
ast::TypeTraitItem(ref at) => {
|
||||
tcx.sess.span_bug(at.span,
|
||||
"there shouldn't \
|
||||
be a type trait \
|
||||
item here")
|
||||
}
|
||||
});
|
||||
|
||||
if ty_method.explicit_self ==
|
||||
@@ -277,6 +316,22 @@ fn collect_trait_methods(ccx: &CrateCtxt,
|
||||
.insert(ty_method.def_id,
|
||||
ty::MethodTraitItem(ty_method));
|
||||
}
|
||||
ast::TypeTraitItem(ref ast_associated_type) => {
|
||||
let trait_did = local_def(trait_id);
|
||||
let associated_type = ty::AssociatedType {
|
||||
ident: ast_associated_type.ident,
|
||||
vis: ast::Public,
|
||||
def_id: local_def(ast_associated_type.id),
|
||||
container: TraitContainer(trait_did),
|
||||
};
|
||||
|
||||
let trait_item = ty::TypeTraitItem(Rc::new(
|
||||
associated_type));
|
||||
tcx.impl_or_trait_items
|
||||
.borrow_mut()
|
||||
.insert(associated_type.def_id,
|
||||
trait_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,6 +348,9 @@ fn collect_trait_methods(ccx: &CrateCtxt,
|
||||
ty::MethodTraitItemId(local_def(
|
||||
method.id))
|
||||
}
|
||||
ast::TypeTraitItem(ref typedef) => {
|
||||
ty::TypeTraitItemId(local_def(typedef.id))
|
||||
}
|
||||
}
|
||||
}).collect());
|
||||
|
||||
@@ -314,9 +372,10 @@ fn make_static_method_ty(ccx: &CrateCtxt, m: &ty::Method) {
|
||||
ty: ty::mk_bare_fn(ccx.tcx, m.fty.clone()) });
|
||||
}
|
||||
|
||||
fn ty_method_of_trait_method(this: &CrateCtxt,
|
||||
fn ty_method_of_trait_method(ccx: &CrateCtxt,
|
||||
trait_id: ast::NodeId,
|
||||
trait_generics: &ty::Generics,
|
||||
trait_items: &[ast::TraitItem],
|
||||
m_id: &ast::NodeId,
|
||||
m_ident: &ast::Ident,
|
||||
m_explicit_self: &ast::ExplicitSelf,
|
||||
@@ -325,20 +384,31 @@ fn ty_method_of_trait_method(this: &CrateCtxt,
|
||||
m_fn_style: &ast::FnStyle,
|
||||
m_decl: &ast::FnDecl)
|
||||
-> ty::Method {
|
||||
let trait_self_ty = ty::mk_self_type(this.tcx, local_def(trait_id));
|
||||
let ty_generics =
|
||||
ty_generics_for_fn_or_method(
|
||||
ccx,
|
||||
m_generics,
|
||||
(*trait_generics).clone(),
|
||||
DontCreateTypeParametersForAssociatedTypes);
|
||||
|
||||
let (fty, explicit_self_category) =
|
||||
astconv::ty_of_method(this,
|
||||
let (fty, explicit_self_category) = {
|
||||
let tmcx = TraitMethodCtxt {
|
||||
ccx: ccx,
|
||||
trait_id: local_def(trait_id),
|
||||
trait_items: trait_items.as_slice(),
|
||||
method_generics: &ty_generics,
|
||||
};
|
||||
let trait_self_ty = ty::mk_self_type(tmcx.tcx(),
|
||||
local_def(trait_id));
|
||||
astconv::ty_of_method(&tmcx,
|
||||
*m_id,
|
||||
*m_fn_style,
|
||||
trait_self_ty,
|
||||
m_explicit_self,
|
||||
m_decl,
|
||||
m_abi);
|
||||
let ty_generics =
|
||||
ty_generics_for_fn_or_method(this,
|
||||
m_generics,
|
||||
(*trait_generics).clone());
|
||||
m_abi)
|
||||
};
|
||||
|
||||
ty::Method::new(
|
||||
*m_ident,
|
||||
ty_generics,
|
||||
@@ -386,12 +456,73 @@ pub fn convert_field(ccx: &CrateCtxt,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_methods<'a, I: Iterator<&'a ast::Method>>(ccx: &CrateCtxt,
|
||||
container: ImplOrTraitItemContainer,
|
||||
mut ms: I,
|
||||
untransformed_rcvr_ty: ty::t,
|
||||
rcvr_ty_generics: &ty::Generics,
|
||||
rcvr_visibility: ast::Visibility) {
|
||||
fn convert_associated_type(ccx: &CrateCtxt,
|
||||
trait_def: &ty::TraitDef,
|
||||
associated_type: &ast::AssociatedType)
|
||||
-> ty::Polytype {
|
||||
// Find the type parameter ID corresponding to this
|
||||
// associated type.
|
||||
let type_parameter_def = trait_def.generics
|
||||
.types
|
||||
.get_slice(subst::TypeSpace)
|
||||
.iter()
|
||||
.find(|def| {
|
||||
def.def_id == local_def(associated_type.id)
|
||||
});
|
||||
let type_parameter_def = match type_parameter_def {
|
||||
Some(type_parameter_def) => type_parameter_def,
|
||||
None => {
|
||||
ccx.tcx().sess.span_bug(associated_type.span,
|
||||
"`convert_associated_type()` didn't find \
|
||||
a type parameter ID corresponding to \
|
||||
this type")
|
||||
}
|
||||
};
|
||||
let param_type = ty::mk_param(ccx.tcx,
|
||||
subst::TypeSpace,
|
||||
type_parameter_def.index,
|
||||
local_def(associated_type.id));
|
||||
ccx.tcx.tcache.borrow_mut().insert(local_def(associated_type.id),
|
||||
Polytype {
|
||||
generics: ty::Generics::empty(),
|
||||
ty: param_type,
|
||||
});
|
||||
write_ty_to_tcx(ccx.tcx, associated_type.id, param_type);
|
||||
|
||||
let associated_type = Rc::new(ty::AssociatedType {
|
||||
ident: associated_type.ident,
|
||||
vis: ast::Public,
|
||||
def_id: local_def(associated_type.id),
|
||||
container: TraitContainer(trait_def.trait_ref.def_id),
|
||||
});
|
||||
ccx.tcx
|
||||
.impl_or_trait_items
|
||||
.borrow_mut()
|
||||
.insert(associated_type.def_id,
|
||||
ty::TypeTraitItem(associated_type));
|
||||
|
||||
Polytype {
|
||||
generics: ty::Generics::empty(),
|
||||
ty: param_type,
|
||||
}
|
||||
}
|
||||
|
||||
enum ConvertMethodContext<'a> {
|
||||
/// Used when converting implementation methods.
|
||||
ImplConvertMethodContext,
|
||||
/// Used when converting method signatures. The def ID is the def ID of
|
||||
/// the trait we're translating.
|
||||
TraitConvertMethodContext(ast::DefId, &'a [ast::TraitItem]),
|
||||
}
|
||||
|
||||
fn convert_methods<'a,I>(ccx: &CrateCtxt,
|
||||
convert_method_context: ConvertMethodContext,
|
||||
container: ImplOrTraitItemContainer,
|
||||
mut ms: I,
|
||||
untransformed_rcvr_ty: ty::t,
|
||||
rcvr_ty_generics: &ty::Generics,
|
||||
rcvr_visibility: ast::Visibility)
|
||||
where I: Iterator<&'a ast::Method> {
|
||||
debug!("convert_methods(untransformed_rcvr_ty={}, \
|
||||
rcvr_ty_generics={})",
|
||||
untransformed_rcvr_ty.repr(ccx.tcx),
|
||||
@@ -400,11 +531,12 @@ fn convert_methods<'a, I: Iterator<&'a ast::Method>>(ccx: &CrateCtxt,
|
||||
let tcx = ccx.tcx;
|
||||
let mut seen_methods = HashSet::new();
|
||||
for m in ms {
|
||||
if !seen_methods.insert(m.pe_ident().repr(ccx.tcx)) {
|
||||
if !seen_methods.insert(m.pe_ident().repr(tcx)) {
|
||||
tcx.sess.span_err(m.span, "duplicate method in trait impl");
|
||||
}
|
||||
|
||||
let mty = Rc::new(ty_of_method(ccx,
|
||||
convert_method_context,
|
||||
container,
|
||||
m,
|
||||
untransformed_rcvr_ty,
|
||||
@@ -412,9 +544,9 @@ fn convert_methods<'a, I: Iterator<&'a ast::Method>>(ccx: &CrateCtxt,
|
||||
rcvr_visibility));
|
||||
let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
|
||||
debug!("method {} (id {}) has type {}",
|
||||
m.pe_ident().repr(ccx.tcx),
|
||||
m.pe_ident().repr(tcx),
|
||||
m.id,
|
||||
fty.repr(ccx.tcx));
|
||||
fty.repr(tcx));
|
||||
tcx.tcache.borrow_mut().insert(
|
||||
local_def(m.id),
|
||||
Polytype {
|
||||
@@ -433,6 +565,7 @@ fn convert_methods<'a, I: Iterator<&'a ast::Method>>(ccx: &CrateCtxt,
|
||||
}
|
||||
|
||||
fn ty_of_method(ccx: &CrateCtxt,
|
||||
convert_method_context: ConvertMethodContext,
|
||||
container: ImplOrTraitItemContainer,
|
||||
m: &ast::Method,
|
||||
untransformed_rcvr_ty: ty::t,
|
||||
@@ -453,14 +586,43 @@ fn ty_of_method(ccx: &CrateCtxt,
|
||||
_ => m.pe_abi(),
|
||||
};
|
||||
|
||||
let (fty, explicit_self_category) =
|
||||
astconv::ty_of_method(ccx,
|
||||
m.id,
|
||||
m.pe_fn_style(),
|
||||
untransformed_rcvr_ty,
|
||||
m.pe_explicit_self(),
|
||||
&*m.pe_fn_decl(),
|
||||
real_abi);
|
||||
let m_ty_generics =
|
||||
ty_generics_for_fn_or_method(
|
||||
ccx,
|
||||
m.pe_generics(),
|
||||
(*rcvr_ty_generics).clone(),
|
||||
CreateTypeParametersForAssociatedTypes);
|
||||
|
||||
let (fty, explicit_self_category) = match convert_method_context {
|
||||
ImplConvertMethodContext => {
|
||||
let imcx = ImplMethodCtxt {
|
||||
ccx: ccx,
|
||||
method_generics: &m_ty_generics,
|
||||
};
|
||||
astconv::ty_of_method(&imcx,
|
||||
m.id,
|
||||
m.pe_fn_style(),
|
||||
untransformed_rcvr_ty,
|
||||
m.pe_explicit_self(),
|
||||
&*m.pe_fn_decl(),
|
||||
real_abi)
|
||||
}
|
||||
TraitConvertMethodContext(trait_id, trait_items) => {
|
||||
let tmcx = TraitMethodCtxt {
|
||||
ccx: ccx,
|
||||
trait_id: trait_id,
|
||||
trait_items: trait_items,
|
||||
method_generics: &m_ty_generics,
|
||||
};
|
||||
astconv::ty_of_method(&tmcx,
|
||||
m.id,
|
||||
m.pe_fn_style(),
|
||||
untransformed_rcvr_ty,
|
||||
m.pe_explicit_self(),
|
||||
&*m.pe_fn_decl(),
|
||||
real_abi)
|
||||
}
|
||||
};
|
||||
|
||||
// if the method specifies a visibility, use that, otherwise
|
||||
// inherit the visibility from the impl (so `foo` in `pub impl
|
||||
@@ -468,9 +630,6 @@ fn ty_of_method(ccx: &CrateCtxt,
|
||||
// foo(); }`).
|
||||
let method_vis = m.pe_vis().inherit_from(rcvr_visibility);
|
||||
|
||||
let m_ty_generics =
|
||||
ty_generics_for_fn_or_method(ccx, m.pe_generics(),
|
||||
(*rcvr_ty_generics).clone());
|
||||
ty::Method::new(m.pe_ident(),
|
||||
m_ty_generics,
|
||||
fty,
|
||||
@@ -507,6 +666,404 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_associated_type_valid_for_param(ty: ty::t,
|
||||
trait_id: ast::DefId,
|
||||
generics: &ty::Generics)
|
||||
-> bool {
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_param(param_ty) => {
|
||||
let type_parameter = generics.types.get(param_ty.space,
|
||||
param_ty.idx);
|
||||
for trait_bound in type_parameter.bounds.trait_bounds.iter() {
|
||||
if trait_bound.def_id == trait_id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn find_associated_type_in_generics(tcx: &ty::ctxt,
|
||||
span: Span,
|
||||
ty: Option<ty::t>,
|
||||
associated_type_id: ast::DefId,
|
||||
generics: &ty::Generics)
|
||||
-> ty::t {
|
||||
let ty = match ty {
|
||||
None => {
|
||||
tcx.sess.span_bug(span,
|
||||
"find_associated_type_in_generics(): no self \
|
||||
type")
|
||||
}
|
||||
Some(ty) => ty,
|
||||
};
|
||||
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_param(ref param_ty) => {
|
||||
/*let type_parameter = generics.types.get(param_ty.space,
|
||||
param_ty.idx);
|
||||
let param_id = type_parameter.def_id;*/
|
||||
let param_id = param_ty.def_id;
|
||||
for type_parameter in generics.types.iter() {
|
||||
if type_parameter.def_id == associated_type_id
|
||||
&& type_parameter.associated_with == Some(param_id) {
|
||||
return ty::mk_param_from_def(tcx, type_parameter)
|
||||
}
|
||||
}
|
||||
|
||||
tcx.sess.span_bug(span,
|
||||
"find_associated_type_in_generics(): didn't \
|
||||
find associated type anywhere in the generics \
|
||||
list")
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.span_bug(span,
|
||||
"find_associated_type_in_generics(): self type \
|
||||
is not a parameter")
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn type_is_self(ty: ty::t) -> bool {
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_param(ref param_ty) if param_ty.is_self() => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
struct ImplCtxt<'a,'tcx:'a> {
|
||||
ccx: &'a CrateCtxt<'a,'tcx>,
|
||||
opt_trait_ref_id: Option<ast::DefId>,
|
||||
impl_items: &'a [ast::ImplItem],
|
||||
impl_generics: &'a ty::Generics,
|
||||
}
|
||||
|
||||
impl<'a,'tcx> AstConv<'tcx> for ImplCtxt<'a,'tcx> {
|
||||
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
|
||||
self.ccx.tcx
|
||||
}
|
||||
|
||||
fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
|
||||
self.ccx.get_item_ty(id)
|
||||
}
|
||||
|
||||
fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
|
||||
self.ccx.get_trait_def(id)
|
||||
}
|
||||
|
||||
fn ty_infer(&self, span: Span) -> ty::t {
|
||||
self.ccx.ty_infer(span)
|
||||
}
|
||||
|
||||
fn associated_types_of_trait_are_valid(&self,
|
||||
ty: ty::t,
|
||||
trait_id: ast::DefId)
|
||||
-> bool {
|
||||
// OK if the trait with the associated type is the trait we're
|
||||
// implementing.
|
||||
match self.opt_trait_ref_id {
|
||||
Some(trait_ref_id) if trait_ref_id == trait_id => {
|
||||
if type_is_self(ty) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
Some(_) | None => {}
|
||||
}
|
||||
|
||||
// OK if the trait with the associated type is one of the traits in
|
||||
// our bounds.
|
||||
is_associated_type_valid_for_param(ty, trait_id, self.impl_generics)
|
||||
}
|
||||
|
||||
fn associated_type_binding(&self,
|
||||
span: Span,
|
||||
ty: Option<ty::t>,
|
||||
trait_id: ast::DefId,
|
||||
associated_type_id: ast::DefId)
|
||||
-> ty::t {
|
||||
ensure_associated_types(self, trait_id);
|
||||
let associated_type_ids = ty::associated_types_for_trait(self.ccx.tcx,
|
||||
trait_id);
|
||||
match self.opt_trait_ref_id {
|
||||
Some(trait_ref_id) if trait_ref_id == trait_id => {
|
||||
// It's an associated type on the trait that we're
|
||||
// implementing.
|
||||
let associated_type_id =
|
||||
associated_type_ids.iter()
|
||||
.find(|id| {
|
||||
id.def_id == associated_type_id
|
||||
})
|
||||
.expect("associated_type_binding(): \
|
||||
expected associated type ID \
|
||||
in trait");
|
||||
let associated_type =
|
||||
ty::impl_or_trait_item(self.ccx.tcx,
|
||||
associated_type_id.def_id);
|
||||
for impl_item in self.impl_items.iter() {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(_) => {}
|
||||
ast::TypeImplItem(ref typedef) => {
|
||||
if associated_type.ident().name == typedef.ident
|
||||
.name {
|
||||
return self.ccx.to_ty(&ExplicitRscope,
|
||||
&*typedef.typ)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.ccx
|
||||
.tcx
|
||||
.sess
|
||||
.span_bug(span,
|
||||
"ImplCtxt::associated_type_binding(): didn't \
|
||||
find associated type")
|
||||
}
|
||||
Some(_) | None => {}
|
||||
}
|
||||
|
||||
// OK then, it should be an associated type on one of the traits in
|
||||
// our bounds.
|
||||
find_associated_type_in_generics(self.ccx.tcx,
|
||||
span,
|
||||
ty,
|
||||
associated_type_id,
|
||||
self.impl_generics)
|
||||
}
|
||||
}
|
||||
|
||||
struct FnCtxt<'a,'tcx:'a> {
|
||||
ccx: &'a CrateCtxt<'a,'tcx>,
|
||||
generics: &'a ty::Generics,
|
||||
}
|
||||
|
||||
impl<'a,'tcx> AstConv<'tcx> for FnCtxt<'a,'tcx> {
|
||||
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
|
||||
self.ccx.tcx
|
||||
}
|
||||
|
||||
fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
|
||||
self.ccx.get_item_ty(id)
|
||||
}
|
||||
|
||||
fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
|
||||
self.ccx.get_trait_def(id)
|
||||
}
|
||||
|
||||
fn ty_infer(&self, span: Span) -> ty::t {
|
||||
self.ccx.ty_infer(span)
|
||||
}
|
||||
|
||||
fn associated_types_of_trait_are_valid(&self,
|
||||
ty: ty::t,
|
||||
trait_id: ast::DefId)
|
||||
-> bool {
|
||||
// OK if the trait with the associated type is one of the traits in
|
||||
// our bounds.
|
||||
is_associated_type_valid_for_param(ty, trait_id, self.generics)
|
||||
}
|
||||
|
||||
fn associated_type_binding(&self,
|
||||
span: Span,
|
||||
ty: Option<ty::t>,
|
||||
_: ast::DefId,
|
||||
associated_type_id: ast::DefId)
|
||||
-> ty::t {
|
||||
debug!("collect::FnCtxt::associated_type_binding()");
|
||||
|
||||
// The ID should map to an associated type on one of the traits in
|
||||
// our bounds.
|
||||
find_associated_type_in_generics(self.ccx.tcx,
|
||||
span,
|
||||
ty,
|
||||
associated_type_id,
|
||||
self.generics)
|
||||
}
|
||||
}
|
||||
|
||||
struct ImplMethodCtxt<'a,'tcx:'a> {
|
||||
ccx: &'a CrateCtxt<'a,'tcx>,
|
||||
method_generics: &'a ty::Generics,
|
||||
}
|
||||
|
||||
impl<'a,'tcx> AstConv<'tcx> for ImplMethodCtxt<'a,'tcx> {
|
||||
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
|
||||
self.ccx.tcx
|
||||
}
|
||||
|
||||
fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
|
||||
self.ccx.get_item_ty(id)
|
||||
}
|
||||
|
||||
fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
|
||||
self.ccx.get_trait_def(id)
|
||||
}
|
||||
|
||||
fn ty_infer(&self, span: Span) -> ty::t {
|
||||
self.ccx.ty_infer(span)
|
||||
}
|
||||
|
||||
fn associated_types_of_trait_are_valid(&self,
|
||||
ty: ty::t,
|
||||
trait_id: ast::DefId)
|
||||
-> bool {
|
||||
is_associated_type_valid_for_param(ty, trait_id, self.method_generics)
|
||||
}
|
||||
|
||||
fn associated_type_binding(&self,
|
||||
span: Span,
|
||||
ty: Option<ty::t>,
|
||||
_: ast::DefId,
|
||||
associated_type_id: ast::DefId)
|
||||
-> ty::t {
|
||||
debug!("collect::ImplMethodCtxt::associated_type_binding()");
|
||||
|
||||
// The ID should map to an associated type on one of the traits in
|
||||
// our bounds.
|
||||
find_associated_type_in_generics(self.ccx.tcx,
|
||||
span,
|
||||
ty,
|
||||
associated_type_id,
|
||||
self.method_generics)
|
||||
}
|
||||
}
|
||||
|
||||
struct TraitMethodCtxt<'a,'tcx:'a> {
|
||||
ccx: &'a CrateCtxt<'a,'tcx>,
|
||||
trait_id: ast::DefId,
|
||||
trait_items: &'a [ast::TraitItem],
|
||||
method_generics: &'a ty::Generics,
|
||||
}
|
||||
|
||||
impl<'a,'tcx> AstConv<'tcx> for TraitMethodCtxt<'a,'tcx> {
|
||||
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
|
||||
self.ccx.tcx
|
||||
}
|
||||
|
||||
fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
|
||||
self.ccx.get_item_ty(id)
|
||||
}
|
||||
|
||||
fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
|
||||
self.ccx.get_trait_def(id)
|
||||
}
|
||||
|
||||
fn ty_infer(&self, span: Span) -> ty::t {
|
||||
self.ccx.ty_infer(span)
|
||||
}
|
||||
|
||||
fn associated_types_of_trait_are_valid(&self,
|
||||
ty: ty::t,
|
||||
trait_id: ast::DefId)
|
||||
-> bool {
|
||||
// OK if the trait with the associated type is this trait.
|
||||
if self.trait_id == trait_id && type_is_self(ty) {
|
||||
return true
|
||||
}
|
||||
|
||||
// OK if the trait with the associated type is one of the traits in
|
||||
// our bounds.
|
||||
is_associated_type_valid_for_param(ty, trait_id, self.method_generics)
|
||||
}
|
||||
|
||||
fn associated_type_binding(&self,
|
||||
span: Span,
|
||||
ty: Option<ty::t>,
|
||||
trait_id: ast::DefId,
|
||||
associated_type_id: ast::DefId)
|
||||
-> ty::t {
|
||||
debug!("collect::TraitMethodCtxt::associated_type_binding()");
|
||||
|
||||
// If this is one of our own associated types, return it.
|
||||
if trait_id == self.trait_id {
|
||||
let mut index = 0;
|
||||
for item in self.trait_items.iter() {
|
||||
match *item {
|
||||
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
|
||||
ast::TypeTraitItem(ref item) => {
|
||||
if local_def(item.id) == associated_type_id {
|
||||
return ty::mk_param(self.tcx(),
|
||||
subst::TypeSpace,
|
||||
index,
|
||||
associated_type_id)
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.ccx
|
||||
.tcx
|
||||
.sess
|
||||
.span_bug(span,
|
||||
"TraitMethodCtxt::associated_type_binding(): \
|
||||
didn't find associated type anywhere in the item \
|
||||
list")
|
||||
}
|
||||
|
||||
// The ID should map to an associated type on one of the traits in
|
||||
// our bounds.
|
||||
find_associated_type_in_generics(self.ccx.tcx,
|
||||
span,
|
||||
ty,
|
||||
associated_type_id,
|
||||
self.method_generics)
|
||||
}
|
||||
}
|
||||
|
||||
struct GenericsCtxt<'a,AC:'a> {
|
||||
chain: &'a AC,
|
||||
associated_types_generics: &'a ty::Generics,
|
||||
}
|
||||
|
||||
impl<'a,'tcx,AC:AstConv<'tcx>> AstConv<'tcx> for GenericsCtxt<'a,AC> {
|
||||
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
|
||||
self.chain.tcx()
|
||||
}
|
||||
|
||||
fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
|
||||
self.chain.get_item_ty(id)
|
||||
}
|
||||
|
||||
fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
|
||||
self.chain.get_trait_def(id)
|
||||
}
|
||||
|
||||
fn ty_infer(&self, span: Span) -> ty::t {
|
||||
self.chain.ty_infer(span)
|
||||
}
|
||||
|
||||
fn associated_types_of_trait_are_valid(&self,
|
||||
ty: ty::t,
|
||||
trait_id: ast::DefId)
|
||||
-> bool {
|
||||
// OK if the trait with the associated type is one of the traits in
|
||||
// our bounds.
|
||||
is_associated_type_valid_for_param(ty,
|
||||
trait_id,
|
||||
self.associated_types_generics)
|
||||
}
|
||||
|
||||
fn associated_type_binding(&self,
|
||||
span: Span,
|
||||
ty: Option<ty::t>,
|
||||
_: ast::DefId,
|
||||
associated_type_id: ast::DefId)
|
||||
-> ty::t {
|
||||
debug!("collect::GenericsCtxt::associated_type_binding()");
|
||||
|
||||
// The ID should map to an associated type on one of the traits in
|
||||
// our bounds.
|
||||
find_associated_type_in_generics(self.chain.tcx(),
|
||||
span,
|
||||
ty,
|
||||
associated_type_id,
|
||||
self.associated_types_generics)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
let tcx = ccx.tcx;
|
||||
debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
|
||||
@@ -525,14 +1082,22 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
ref opt_trait_ref,
|
||||
ref selfty,
|
||||
ref impl_items) => {
|
||||
let ty_generics = ty_generics_for_type(ccx, generics);
|
||||
// Create generics from the generics specified in the impl head.
|
||||
let ty_generics = ty_generics_for_type(
|
||||
ccx,
|
||||
generics,
|
||||
CreateTypeParametersForAssociatedTypes);
|
||||
|
||||
let selfty = ccx.to_ty(&ExplicitRscope, &**selfty);
|
||||
write_ty_to_tcx(tcx, it.id, selfty);
|
||||
|
||||
tcx.tcache.borrow_mut().insert(local_def(it.id),
|
||||
Polytype {
|
||||
generics: ty_generics.clone(),
|
||||
ty: selfty});
|
||||
tcx.tcache
|
||||
.borrow_mut()
|
||||
.insert(local_def(it.id),
|
||||
Polytype {
|
||||
generics: ty_generics.clone(),
|
||||
ty: selfty,
|
||||
});
|
||||
|
||||
// If there is a trait reference, treat the methods as always public.
|
||||
// This is to work around some incorrect behavior in privacy checking:
|
||||
@@ -545,6 +1110,20 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
it.vis
|
||||
};
|
||||
|
||||
let icx = ImplCtxt {
|
||||
ccx: ccx,
|
||||
opt_trait_ref_id: match *opt_trait_ref {
|
||||
None => None,
|
||||
Some(ref ast_trait_ref) => {
|
||||
Some(lookup_def_tcx(tcx,
|
||||
ast_trait_ref.path.span,
|
||||
ast_trait_ref.ref_id).def_id())
|
||||
}
|
||||
},
|
||||
impl_items: impl_items.as_slice(),
|
||||
impl_generics: &ty_generics,
|
||||
};
|
||||
|
||||
let mut methods = Vec::new();
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
@@ -555,10 +1134,33 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
method.pe_explicit_self());
|
||||
methods.push(&**method);
|
||||
}
|
||||
ast::TypeImplItem(ref typedef) => {
|
||||
let typ = icx.to_ty(&ExplicitRscope, &*typedef.typ);
|
||||
tcx.tcache
|
||||
.borrow_mut()
|
||||
.insert(local_def(typedef.id),
|
||||
Polytype {
|
||||
generics: ty::Generics::empty(),
|
||||
ty: typ,
|
||||
});
|
||||
write_ty_to_tcx(ccx.tcx, typedef.id, typ);
|
||||
|
||||
let associated_type = Rc::new(ty::AssociatedType {
|
||||
ident: typedef.ident,
|
||||
vis: typedef.vis,
|
||||
def_id: local_def(typedef.id),
|
||||
container: ty::ImplContainer(local_def(it.id)),
|
||||
});
|
||||
tcx.impl_or_trait_items
|
||||
.borrow_mut()
|
||||
.insert(local_def(typedef.id),
|
||||
ty::TypeTraitItem(associated_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
convert_methods(ccx,
|
||||
ImplConvertMethodContext,
|
||||
ImplContainer(local_def(it.id)),
|
||||
methods.into_iter(),
|
||||
selfty,
|
||||
@@ -566,7 +1168,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
parent_visibility);
|
||||
|
||||
for trait_ref in opt_trait_ref.iter() {
|
||||
instantiate_trait_ref(ccx, trait_ref, selfty);
|
||||
instantiate_trait_ref(&icx, trait_ref, selfty, None);
|
||||
}
|
||||
},
|
||||
ast::ItemTrait(_, _, _, ref trait_methods) => {
|
||||
@@ -595,16 +1197,27 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
self_type,
|
||||
method.pe_explicit_self())
|
||||
}
|
||||
ast::TypeTraitItem(ref associated_type) => {
|
||||
convert_associated_type(ccx,
|
||||
&*trait_def,
|
||||
&**associated_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run convert_methods on the provided methods.
|
||||
let untransformed_rcvr_ty = ty::mk_self_type(tcx, local_def(it.id));
|
||||
let untransformed_rcvr_ty = ty::mk_self_type(tcx,
|
||||
local_def(it.id));
|
||||
let convert_method_context =
|
||||
TraitConvertMethodContext(local_def(it.id),
|
||||
trait_methods.as_slice());
|
||||
convert_methods(ccx,
|
||||
convert_method_context,
|
||||
TraitContainer(local_def(it.id)),
|
||||
trait_methods.iter().filter_map(|m| match *m {
|
||||
ast::RequiredMethod(_) => None,
|
||||
ast::ProvidedMethod(ref m) => Some(&**m)
|
||||
ast::ProvidedMethod(ref m) => Some(&**m),
|
||||
ast::TypeTraitItem(_) => None,
|
||||
}),
|
||||
untransformed_rcvr_ty,
|
||||
&trait_def.generics,
|
||||
@@ -765,9 +1378,12 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
|
||||
ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), pty);
|
||||
}
|
||||
|
||||
pub fn instantiate_trait_ref(ccx: &CrateCtxt,
|
||||
ast_trait_ref: &ast::TraitRef,
|
||||
self_ty: ty::t) -> Rc<ty::TraitRef> {
|
||||
pub fn instantiate_trait_ref<'tcx,AC>(this: &AC,
|
||||
ast_trait_ref: &ast::TraitRef,
|
||||
self_ty: ty::t,
|
||||
associated_type: Option<ty::t>)
|
||||
-> Rc<ty::TraitRef>
|
||||
where AC: AstConv<'tcx> {
|
||||
/*!
|
||||
* 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
|
||||
@@ -777,18 +1393,24 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt,
|
||||
// FIXME(#5121) -- distinguish early vs late lifetime params
|
||||
let rscope = ExplicitRscope;
|
||||
|
||||
match lookup_def_tcx(ccx.tcx, ast_trait_ref.path.span, ast_trait_ref.ref_id) {
|
||||
match lookup_def_tcx(this.tcx(),
|
||||
ast_trait_ref.path.span,
|
||||
ast_trait_ref.ref_id) {
|
||||
def::DefTrait(trait_did) => {
|
||||
let trait_ref =
|
||||
astconv::ast_path_to_trait_ref(
|
||||
ccx, &rscope, trait_did, Some(self_ty), &ast_trait_ref.path);
|
||||
astconv::ast_path_to_trait_ref(this,
|
||||
&rscope,
|
||||
trait_did,
|
||||
Some(self_ty),
|
||||
associated_type,
|
||||
&ast_trait_ref.path);
|
||||
|
||||
ccx.tcx.trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
|
||||
trait_ref.clone());
|
||||
this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
|
||||
trait_ref.clone());
|
||||
trait_ref
|
||||
}
|
||||
_ => {
|
||||
ccx.tcx.sess.span_fatal(
|
||||
this.tcx().sess.span_fatal(
|
||||
ast_trait_ref.path.span,
|
||||
format!("`{}` is not a trait",
|
||||
path_to_string(&ast_trait_ref.path)).as_slice());
|
||||
@@ -796,14 +1418,14 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn instantiate_unboxed_fn_ty(ccx: &CrateCtxt,
|
||||
unboxed_function: &ast::UnboxedFnTy,
|
||||
param_ty: ty::ParamTy)
|
||||
-> Rc<ty::TraitRef>
|
||||
{
|
||||
pub fn instantiate_unboxed_fn_ty<'tcx,AC>(this: &AC,
|
||||
unboxed_function: &ast::UnboxedFnTy,
|
||||
param_ty: ty::ParamTy)
|
||||
-> Rc<ty::TraitRef>
|
||||
where AC: AstConv<'tcx> {
|
||||
let rscope = ExplicitRscope;
|
||||
let param_ty = param_ty.to_ty(ccx.tcx);
|
||||
Rc::new(astconv::trait_ref_for_unboxed_function(ccx,
|
||||
let param_ty = param_ty.to_ty(this.tcx());
|
||||
Rc::new(astconv::trait_ref_for_unboxed_function(this,
|
||||
&rscope,
|
||||
unboxed_function,
|
||||
Some(param_ty)))
|
||||
@@ -831,9 +1453,12 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let (generics, unbound, bounds) = match it.node {
|
||||
ast::ItemTrait(ref generics, ref unbound, ref bounds, _) => {
|
||||
(generics, unbound, bounds)
|
||||
let (generics, unbound, bounds, items) = match it.node {
|
||||
ast::ItemTrait(ref generics,
|
||||
ref unbound,
|
||||
ref supertraits,
|
||||
ref items) => {
|
||||
(generics, unbound, supertraits, items.as_slice())
|
||||
}
|
||||
ref s => {
|
||||
tcx.sess.span_bug(
|
||||
@@ -842,12 +1467,13 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
|
||||
}
|
||||
};
|
||||
|
||||
let substs = mk_trait_substs(ccx, it.id, generics);
|
||||
let substs = mk_trait_substs(ccx, it.id, generics, items);
|
||||
|
||||
let ty_generics = ty_generics_for_trait(ccx,
|
||||
it.id,
|
||||
&substs,
|
||||
generics);
|
||||
generics,
|
||||
items);
|
||||
|
||||
let self_param_ty = ty::ParamTy::for_self(def_id);
|
||||
|
||||
@@ -870,9 +1496,9 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
|
||||
|
||||
fn mk_trait_substs(ccx: &CrateCtxt,
|
||||
trait_id: ast::NodeId,
|
||||
generics: &ast::Generics)
|
||||
-> subst::Substs
|
||||
{
|
||||
generics: &ast::Generics,
|
||||
items: &[ast::TraitItem])
|
||||
-> subst::Substs {
|
||||
// Creates a no-op substitution for the trait's type parameters.
|
||||
let regions =
|
||||
generics.lifetimes
|
||||
@@ -884,7 +1510,8 @@ fn mk_trait_substs(ccx: &CrateCtxt,
|
||||
def.lifetime.name))
|
||||
.collect();
|
||||
|
||||
let types =
|
||||
// Start with the generics in the type parameters...
|
||||
let mut types: Vec<_> =
|
||||
generics.ty_params
|
||||
.iter()
|
||||
.enumerate()
|
||||
@@ -892,6 +1519,20 @@ fn mk_trait_substs(ccx: &CrateCtxt,
|
||||
i, local_def(def.id)))
|
||||
.collect();
|
||||
|
||||
// ...and add generics synthesized from the associated types.
|
||||
for item in items.iter() {
|
||||
match *item {
|
||||
ast::TypeTraitItem(ref trait_item) => {
|
||||
let index = types.len();
|
||||
types.push(ty::mk_param(ccx.tcx,
|
||||
subst::TypeSpace,
|
||||
index,
|
||||
local_def(trait_item.id)))
|
||||
}
|
||||
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
let self_ty =
|
||||
ty::mk_param(ccx.tcx, subst::SelfSpace, 0, local_def(trait_id));
|
||||
|
||||
@@ -916,13 +1557,22 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
|
||||
return pty;
|
||||
}
|
||||
ast::ItemFn(ref decl, fn_style, abi, ref generics, _) => {
|
||||
let ty_generics = ty_generics_for_fn_or_method(ccx, generics,
|
||||
ty::Generics::empty());
|
||||
let tofd = astconv::ty_of_bare_fn(ccx,
|
||||
it.id,
|
||||
fn_style,
|
||||
abi,
|
||||
&**decl);
|
||||
let ty_generics = ty_generics_for_fn_or_method(
|
||||
ccx,
|
||||
generics,
|
||||
ty::Generics::empty(),
|
||||
CreateTypeParametersForAssociatedTypes);
|
||||
let tofd = {
|
||||
let fcx = FnCtxt {
|
||||
ccx: ccx,
|
||||
generics: &ty_generics,
|
||||
};
|
||||
astconv::ty_of_bare_fn(&fcx,
|
||||
it.id,
|
||||
fn_style,
|
||||
abi,
|
||||
&**decl)
|
||||
};
|
||||
let pty = Polytype {
|
||||
generics: ty_generics,
|
||||
ty: ty::mk_bare_fn(ccx.tcx, tofd)
|
||||
@@ -930,7 +1580,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
|
||||
debug!("type of {} (id {}) is {}",
|
||||
token::get_ident(it.ident),
|
||||
it.id,
|
||||
ppaux::ty_to_string(tcx, pty.ty));
|
||||
pty.repr(tcx));
|
||||
|
||||
ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
|
||||
return pty;
|
||||
@@ -944,7 +1594,10 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
|
||||
let pty = {
|
||||
let ty = ccx.to_ty(&ExplicitRscope, &**t);
|
||||
Polytype {
|
||||
generics: ty_generics_for_type(ccx, generics),
|
||||
generics: ty_generics_for_type(
|
||||
ccx,
|
||||
generics,
|
||||
DontCreateTypeParametersForAssociatedTypes),
|
||||
ty: ty
|
||||
}
|
||||
};
|
||||
@@ -954,7 +1607,10 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
|
||||
}
|
||||
ast::ItemEnum(_, ref generics) => {
|
||||
// Create a new generic polytype.
|
||||
let ty_generics = ty_generics_for_type(ccx, generics);
|
||||
let ty_generics = ty_generics_for_type(
|
||||
ccx,
|
||||
generics,
|
||||
DontCreateTypeParametersForAssociatedTypes);
|
||||
let substs = mk_item_substs(ccx, &ty_generics);
|
||||
let t = ty::mk_enum(tcx, local_def(it.id), substs);
|
||||
let pty = Polytype {
|
||||
@@ -969,7 +1625,10 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
|
||||
tcx.sess.span_bug(it.span, "invoked ty_of_item on trait");
|
||||
}
|
||||
ast::ItemStruct(_, ref generics) => {
|
||||
let ty_generics = ty_generics_for_type(ccx, generics);
|
||||
let ty_generics = ty_generics_for_type(
|
||||
ccx,
|
||||
generics,
|
||||
DontCreateTypeParametersForAssociatedTypes);
|
||||
let substs = mk_item_substs(ccx, &ty_generics);
|
||||
let t = ty::mk_struct(tcx, local_def(it.id), substs);
|
||||
let pty = Polytype {
|
||||
@@ -1006,30 +1665,88 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt,
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_of_trait_item(ccx: &CrateCtxt, trait_item: &ast::TraitItem)
|
||||
-> ty::Polytype {
|
||||
match *trait_item {
|
||||
ast::RequiredMethod(ref m) => {
|
||||
ccx.tcx.sess.span_bug(m.span,
|
||||
"ty_of_trait_item() on required method")
|
||||
}
|
||||
ast::ProvidedMethod(ref m) => {
|
||||
ccx.tcx.sess.span_bug(m.span,
|
||||
"ty_of_trait_item() on provided method")
|
||||
}
|
||||
ast::TypeTraitItem(ref associated_type) => {
|
||||
let parent = ccx.tcx.map.get_parent(associated_type.id);
|
||||
let trait_def = match ccx.tcx.map.get(parent) {
|
||||
ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
|
||||
_ => {
|
||||
ccx.tcx.sess.span_bug(associated_type.span,
|
||||
"associated type's parent wasn't \
|
||||
an item?!")
|
||||
}
|
||||
};
|
||||
convert_associated_type(ccx, &*trait_def, &**associated_type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_generics_for_type(ccx: &CrateCtxt,
|
||||
generics: &ast::Generics)
|
||||
-> ty::Generics
|
||||
{
|
||||
generics: &ast::Generics,
|
||||
create_type_parameters_for_associated_types:
|
||||
CreateTypeParametersForAssociatedTypesFlag)
|
||||
-> ty::Generics {
|
||||
ty_generics(ccx,
|
||||
subst::TypeSpace,
|
||||
generics.lifetimes.as_slice(),
|
||||
generics.ty_params.as_slice(),
|
||||
ty::Generics::empty(),
|
||||
&generics.where_clause)
|
||||
&generics.where_clause,
|
||||
create_type_parameters_for_associated_types)
|
||||
}
|
||||
|
||||
fn ty_generics_for_trait(ccx: &CrateCtxt,
|
||||
trait_id: ast::NodeId,
|
||||
substs: &subst::Substs,
|
||||
generics: &ast::Generics)
|
||||
generics: &ast::Generics,
|
||||
items: &[ast::TraitItem])
|
||||
-> ty::Generics {
|
||||
let mut generics = ty_generics(ccx,
|
||||
subst::TypeSpace,
|
||||
generics.lifetimes.as_slice(),
|
||||
generics.ty_params.as_slice(),
|
||||
ty::Generics::empty(),
|
||||
&generics.where_clause);
|
||||
let mut generics =
|
||||
ty_generics(ccx,
|
||||
subst::TypeSpace,
|
||||
generics.lifetimes.as_slice(),
|
||||
generics.ty_params.as_slice(),
|
||||
ty::Generics::empty(),
|
||||
&generics.where_clause,
|
||||
DontCreateTypeParametersForAssociatedTypes);
|
||||
|
||||
// Add in type parameters for any associated types.
|
||||
for item in items.iter() {
|
||||
match *item {
|
||||
ast::TypeTraitItem(ref associated_type) => {
|
||||
let def = ty::TypeParameterDef {
|
||||
space: subst::TypeSpace,
|
||||
index: generics.types.len(subst::TypeSpace),
|
||||
ident: associated_type.ident,
|
||||
def_id: local_def(associated_type.id),
|
||||
bounds: ty::ParamBounds {
|
||||
builtin_bounds: ty::empty_builtin_bounds(),
|
||||
trait_bounds: Vec::new(),
|
||||
region_bounds: Vec::new(),
|
||||
},
|
||||
associated_with: Some(local_def(trait_id)),
|
||||
default: None,
|
||||
};
|
||||
ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.id,
|
||||
def.clone());
|
||||
generics.types.push(subst::TypeSpace, def);
|
||||
}
|
||||
ast::ProvidedMethod(_) | ast::RequiredMethod(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
// Add in the self type parameter.
|
||||
//
|
||||
// Something of a hack: use the node id for the trait, also as
|
||||
// the node id for the Self type parameter.
|
||||
let param_id = trait_id;
|
||||
@@ -1048,6 +1765,7 @@ fn ty_generics_for_trait(ccx: &CrateCtxt,
|
||||
builtin_bounds: ty::empty_builtin_bounds(),
|
||||
trait_bounds: vec!(self_trait_ref),
|
||||
},
|
||||
associated_with: None,
|
||||
default: None
|
||||
};
|
||||
|
||||
@@ -1058,41 +1776,48 @@ fn ty_generics_for_trait(ccx: &CrateCtxt,
|
||||
generics
|
||||
}
|
||||
|
||||
fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
|
||||
generics: &ast::Generics,
|
||||
base_generics: ty::Generics)
|
||||
-> ty::Generics {
|
||||
fn ty_generics_for_fn_or_method<'tcx,AC>(
|
||||
this: &AC,
|
||||
generics: &ast::Generics,
|
||||
base_generics: ty::Generics,
|
||||
create_type_parameters_for_associated_types:
|
||||
CreateTypeParametersForAssociatedTypesFlag)
|
||||
-> ty::Generics
|
||||
where AC: AstConv<'tcx> {
|
||||
let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
|
||||
ty_generics(ccx,
|
||||
ty_generics(this,
|
||||
subst::FnSpace,
|
||||
early_lifetimes.as_slice(),
|
||||
generics.ty_params.as_slice(),
|
||||
base_generics,
|
||||
&generics.where_clause)
|
||||
&generics.where_clause,
|
||||
create_type_parameters_for_associated_types)
|
||||
}
|
||||
|
||||
// Add the Sized bound, unless the type parameter is marked as `Sized?`.
|
||||
fn add_unsized_bound(ccx: &CrateCtxt,
|
||||
unbound: &Option<ast::TyParamBound>,
|
||||
bounds: &mut ty::BuiltinBounds,
|
||||
desc: &str,
|
||||
span: Span) {
|
||||
let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
|
||||
|
||||
fn add_unsized_bound<'tcx,AC>(this: &AC,
|
||||
unbound: &Option<ast::TyParamBound>,
|
||||
bounds: &mut ty::BuiltinBounds,
|
||||
desc: &str,
|
||||
span: Span)
|
||||
where AC: AstConv<'tcx> {
|
||||
let kind_id = this.tcx().lang_items.require(SizedTraitLangItem);
|
||||
match unbound {
|
||||
&Some(ast::TraitTyParamBound(ref tpb)) => {
|
||||
// FIXME(#8559) currently requires the unbound to be built-in.
|
||||
let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, tpb);
|
||||
let trait_def_id = ty::trait_ref_to_def_id(this.tcx(), tpb);
|
||||
match kind_id {
|
||||
Ok(kind_id) if trait_def_id != kind_id => {
|
||||
ccx.tcx.sess.span_warn(span,
|
||||
format!("default bound relaxed \
|
||||
for a {}, but this does \
|
||||
nothing because the given \
|
||||
bound is not a default. \
|
||||
Only `Sized?` is supported.",
|
||||
desc).as_slice());
|
||||
ty::try_add_builtin_trait(ccx.tcx,
|
||||
this.tcx().sess.span_warn(span,
|
||||
format!("default bound relaxed \
|
||||
for a {}, but this \
|
||||
does nothing because \
|
||||
the given bound is not \
|
||||
a default. \
|
||||
Only `Sized?` is \
|
||||
supported.",
|
||||
desc).as_slice());
|
||||
ty::try_add_builtin_trait(this.tcx(),
|
||||
kind_id,
|
||||
bounds);
|
||||
}
|
||||
@@ -1100,28 +1825,104 @@ fn add_unsized_bound(ccx: &CrateCtxt,
|
||||
}
|
||||
}
|
||||
_ if kind_id.is_ok() => {
|
||||
ty::try_add_builtin_trait(ccx.tcx,
|
||||
kind_id.unwrap(),
|
||||
bounds);
|
||||
ty::try_add_builtin_trait(this.tcx(), kind_id.unwrap(), bounds);
|
||||
}
|
||||
// No lang item for Sized, so we can't add it as a bound.
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_generics(ccx: &CrateCtxt,
|
||||
space: subst::ParamSpace,
|
||||
lifetime_defs: &[ast::LifetimeDef],
|
||||
types: &[ast::TyParam],
|
||||
base_generics: ty::Generics,
|
||||
where_clause: &ast::WhereClause)
|
||||
-> ty::Generics
|
||||
{
|
||||
#[deriving(Clone, PartialEq, Eq)]
|
||||
enum CreateTypeParametersForAssociatedTypesFlag {
|
||||
DontCreateTypeParametersForAssociatedTypes,
|
||||
CreateTypeParametersForAssociatedTypes,
|
||||
}
|
||||
|
||||
fn ensure_associated_types<'tcx,AC>(this: &AC, trait_id: ast::DefId)
|
||||
where AC: AstConv<'tcx> {
|
||||
if this.tcx().trait_associated_types.borrow().contains_key(&trait_id) {
|
||||
return
|
||||
}
|
||||
|
||||
if trait_id.krate == ast::LOCAL_CRATE {
|
||||
match this.tcx().map.find(trait_id.node) {
|
||||
Some(ast_map::NodeItem(item)) => {
|
||||
match item.node {
|
||||
ast::ItemTrait(_, _, _, ref trait_items) => {
|
||||
let mut result = Vec::new();
|
||||
let mut index = 0;
|
||||
for trait_item in trait_items.iter() {
|
||||
match *trait_item {
|
||||
ast::RequiredMethod(_) |
|
||||
ast::ProvidedMethod(_) => {}
|
||||
ast::TypeTraitItem(ref associated_type) => {
|
||||
let info = ty::AssociatedTypeInfo {
|
||||
def_id: local_def(associated_type.id),
|
||||
index: index,
|
||||
ident: associated_type.ident,
|
||||
};
|
||||
result.push(info);
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.tcx()
|
||||
.trait_associated_types
|
||||
.borrow_mut()
|
||||
.insert(trait_id, Rc::new(result));
|
||||
return
|
||||
}
|
||||
_ => {
|
||||
this.tcx().sess.bug("ensure_associated_types() \
|
||||
called on non-trait")
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
this.tcx().sess.bug("ensure_associated_types() called on \
|
||||
non-trait")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Cross-crate case.
|
||||
let mut result = Vec::new();
|
||||
let mut index = 0;
|
||||
let trait_items = ty::trait_items(this.tcx(), trait_id);
|
||||
for trait_item in trait_items.iter() {
|
||||
match *trait_item {
|
||||
ty::MethodTraitItem(_) => {}
|
||||
ty::TypeTraitItem(ref associated_type) => {
|
||||
let info = ty::AssociatedTypeInfo {
|
||||
def_id: associated_type.def_id,
|
||||
index: index,
|
||||
ident: associated_type.ident
|
||||
};
|
||||
result.push(info);
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.tcx().trait_associated_types.borrow_mut().insert(trait_id,
|
||||
Rc::new(result));
|
||||
}
|
||||
|
||||
fn ty_generics<'tcx,AC>(this: &AC,
|
||||
space: subst::ParamSpace,
|
||||
lifetime_defs: &[ast::LifetimeDef],
|
||||
types: &[ast::TyParam],
|
||||
base_generics: ty::Generics,
|
||||
where_clause: &ast::WhereClause,
|
||||
create_type_parameters_for_associated_types:
|
||||
CreateTypeParametersForAssociatedTypesFlag)
|
||||
-> ty::Generics
|
||||
where AC: AstConv<'tcx> {
|
||||
let mut result = base_generics;
|
||||
|
||||
for (i, l) in lifetime_defs.iter().enumerate() {
|
||||
let bounds = l.bounds.iter()
|
||||
.map(|l| ast_region_to_region(ccx.tcx, l))
|
||||
.map(|l| ast_region_to_region(this.tcx(), l))
|
||||
.collect();
|
||||
let def = ty::RegionParameterDef { name: l.lifetime.name,
|
||||
space: space,
|
||||
@@ -1132,80 +1933,170 @@ fn ty_generics(ccx: &CrateCtxt,
|
||||
result.regions.push(space, def);
|
||||
}
|
||||
|
||||
assert!(result.types.is_empty_in(space));
|
||||
|
||||
// First, create the virtual type parameters for associated types if
|
||||
// necessary.
|
||||
let mut associated_types_generics = ty::Generics::empty();
|
||||
match create_type_parameters_for_associated_types {
|
||||
DontCreateTypeParametersForAssociatedTypes => {}
|
||||
CreateTypeParametersForAssociatedTypes => {
|
||||
let mut index = 0;
|
||||
for param in types.iter() {
|
||||
for bound in param.bounds.iter() {
|
||||
match *bound {
|
||||
ast::TraitTyParamBound(ref trait_bound) => {
|
||||
match lookup_def_tcx(this.tcx(),
|
||||
trait_bound.path.span,
|
||||
trait_bound.ref_id) {
|
||||
def::DefTrait(trait_did) => {
|
||||
ensure_associated_types(this, trait_did);
|
||||
let associated_types =
|
||||
ty::associated_types_for_trait(
|
||||
this.tcx(),
|
||||
trait_did);
|
||||
for associated_type_info in
|
||||
associated_types.iter() {
|
||||
let associated_type_trait_item =
|
||||
ty::impl_or_trait_item(
|
||||
this.tcx(),
|
||||
associated_type_info.def_id);
|
||||
let def = ty::TypeParameterDef {
|
||||
ident: associated_type_trait_item
|
||||
.ident(),
|
||||
def_id:
|
||||
associated_type_info.def_id,
|
||||
space: space,
|
||||
index: types.len() + index,
|
||||
bounds: ty::ParamBounds {
|
||||
builtin_bounds:
|
||||
ty::empty_builtin_bounds(),
|
||||
trait_bounds: Vec::new(),
|
||||
region_bounds: Vec::new(),
|
||||
},
|
||||
associated_with: {
|
||||
Some(local_def(param.id))
|
||||
},
|
||||
default: None,
|
||||
};
|
||||
associated_types_generics.types
|
||||
.push(space,
|
||||
def);
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
this.tcx().sess.span_bug(trait_bound.path
|
||||
.span,
|
||||
"not a trait?!")
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now create the real type parameters.
|
||||
let gcx = GenericsCtxt {
|
||||
chain: this,
|
||||
associated_types_generics: &associated_types_generics,
|
||||
};
|
||||
for (i, param) in types.iter().enumerate() {
|
||||
let def = get_or_create_type_parameter_def(ccx,
|
||||
let def = get_or_create_type_parameter_def(&gcx,
|
||||
space,
|
||||
param,
|
||||
i,
|
||||
where_clause);
|
||||
debug!("ty_generics: def for type param: {}", def.repr(ccx.tcx));
|
||||
debug!("ty_generics: def for type param: {}, {}",
|
||||
def.repr(this.tcx()),
|
||||
space);
|
||||
result.types.push(space, def);
|
||||
}
|
||||
|
||||
// Append the associated types to the result.
|
||||
for associated_type_param in associated_types_generics.types
|
||||
.get_slice(space)
|
||||
.iter() {
|
||||
assert!(result.types.get_slice(space).len() ==
|
||||
associated_type_param.index);
|
||||
debug!("ty_generics: def for associated type: {}, {}",
|
||||
associated_type_param.repr(this.tcx()),
|
||||
space);
|
||||
result.types.push(space, (*associated_type_param).clone());
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
fn get_or_create_type_parameter_def(ccx: &CrateCtxt,
|
||||
fn get_or_create_type_parameter_def<'tcx,AC>(
|
||||
this: &AC,
|
||||
space: subst::ParamSpace,
|
||||
param: &ast::TyParam,
|
||||
index: uint,
|
||||
where_clause: &ast::WhereClause)
|
||||
-> ty::TypeParameterDef {
|
||||
match ccx.tcx.ty_param_defs.borrow().find(¶m.id) {
|
||||
-> ty::TypeParameterDef
|
||||
where AC: AstConv<'tcx> {
|
||||
match this.tcx().ty_param_defs.borrow().find(¶m.id) {
|
||||
Some(d) => { return (*d).clone(); }
|
||||
None => { }
|
||||
}
|
||||
|
||||
let param_ty = ty::ParamTy::new(space, index, local_def(param.id));
|
||||
let bounds = compute_bounds(ccx,
|
||||
let bounds = compute_bounds(this,
|
||||
param.ident.name,
|
||||
param_ty,
|
||||
param.bounds.as_slice(),
|
||||
¶m.unbound,
|
||||
param.span,
|
||||
where_clause);
|
||||
let default = param.default.as_ref().map(|path| {
|
||||
let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &**path);
|
||||
let cur_idx = index;
|
||||
let default = match param.default {
|
||||
None => None,
|
||||
Some(ref path) => {
|
||||
let ty = ast_ty_to_ty(this, &ExplicitRscope, &**path);
|
||||
let cur_idx = index;
|
||||
|
||||
ty::walk_ty(ty, |t| {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_param(p) => if p.idx > cur_idx {
|
||||
span_err!(ccx.tcx.sess, path.span, E0128,
|
||||
"type parameters with a default cannot use \
|
||||
forward declared identifiers");
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
ty::walk_ty(ty, |t| {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_param(p) => if p.idx > cur_idx {
|
||||
span_err!(this.tcx().sess, path.span, E0128,
|
||||
"type parameters with a default cannot use \
|
||||
forward declared identifiers");
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
|
||||
ty
|
||||
});
|
||||
Some(ty)
|
||||
}
|
||||
};
|
||||
|
||||
let def = ty::TypeParameterDef {
|
||||
space: space,
|
||||
index: index,
|
||||
ident: param.ident,
|
||||
def_id: local_def(param.id),
|
||||
associated_with: None,
|
||||
bounds: bounds,
|
||||
default: default
|
||||
};
|
||||
|
||||
ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
|
||||
this.tcx().ty_param_defs.borrow_mut().insert(param.id, def.clone());
|
||||
|
||||
def
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_bounds(
|
||||
ccx: &CrateCtxt,
|
||||
name_of_bounded_thing: ast::Name,
|
||||
param_ty: ty::ParamTy,
|
||||
ast_bounds: &[ast::TyParamBound],
|
||||
unbound: &Option<ast::TyParamBound>,
|
||||
span: Span,
|
||||
where_clause: &ast::WhereClause)
|
||||
-> ty::ParamBounds
|
||||
{
|
||||
fn compute_bounds<'tcx,AC>(this: &AC,
|
||||
name_of_bounded_thing: ast::Name,
|
||||
param_ty: ty::ParamTy,
|
||||
ast_bounds: &[ast::TyParamBound],
|
||||
unbound: &Option<ast::TyParamBound>,
|
||||
span: Span,
|
||||
where_clause: &ast::WhereClause)
|
||||
-> ty::ParamBounds
|
||||
where AC: AstConv<'tcx> {
|
||||
/*!
|
||||
* Translate the AST's notion of ty param bounds (which are an
|
||||
* enum consisting of a newtyped Ty or a region) to ty's
|
||||
@@ -1213,21 +2104,23 @@ fn compute_bounds(
|
||||
* traits, or the built-in trait (formerly known as kind): Send.
|
||||
*/
|
||||
|
||||
let mut param_bounds = conv_param_bounds(ccx,
|
||||
let mut param_bounds = conv_param_bounds(this,
|
||||
span,
|
||||
param_ty,
|
||||
ast_bounds,
|
||||
where_clause);
|
||||
|
||||
|
||||
add_unsized_bound(ccx,
|
||||
add_unsized_bound(this,
|
||||
unbound,
|
||||
&mut param_bounds.builtin_bounds,
|
||||
"type parameter",
|
||||
span);
|
||||
|
||||
check_bounds_compatible(ccx.tcx, name_of_bounded_thing,
|
||||
¶m_bounds, span);
|
||||
check_bounds_compatible(this.tcx(),
|
||||
name_of_bounded_thing,
|
||||
¶m_bounds,
|
||||
span);
|
||||
|
||||
param_bounds.trait_bounds.sort_by(|a,b| a.def_id.cmp(&b.def_id));
|
||||
|
||||
@@ -1258,31 +2151,36 @@ fn check_bounds_compatible(tcx: &ty::ctxt,
|
||||
}
|
||||
}
|
||||
|
||||
fn conv_param_bounds(ccx: &CrateCtxt,
|
||||
span: Span,
|
||||
param_ty: ty::ParamTy,
|
||||
ast_bounds: &[ast::TyParamBound],
|
||||
where_clause: &ast::WhereClause)
|
||||
-> ty::ParamBounds
|
||||
{
|
||||
fn conv_param_bounds<'tcx,AC>(this: &AC,
|
||||
span: Span,
|
||||
param_ty: ty::ParamTy,
|
||||
ast_bounds: &[ast::TyParamBound],
|
||||
where_clause: &ast::WhereClause)
|
||||
-> ty::ParamBounds
|
||||
where AC: AstConv<'tcx> {
|
||||
let all_bounds =
|
||||
merge_param_bounds(ccx, param_ty, ast_bounds, where_clause);
|
||||
merge_param_bounds(this.tcx(), param_ty, ast_bounds, where_clause);
|
||||
let astconv::PartitionedBounds { builtin_bounds,
|
||||
trait_bounds,
|
||||
region_bounds,
|
||||
unboxed_fn_ty_bounds } =
|
||||
astconv::partition_bounds(ccx.tcx, span, all_bounds.as_slice());
|
||||
astconv::partition_bounds(this.tcx(), span, all_bounds.as_slice());
|
||||
let unboxed_fn_ty_bounds =
|
||||
unboxed_fn_ty_bounds.into_iter()
|
||||
.map(|b| instantiate_unboxed_fn_ty(ccx, b, param_ty));
|
||||
.map(|b| instantiate_unboxed_fn_ty(this, b, param_ty));
|
||||
let trait_bounds: Vec<Rc<ty::TraitRef>> =
|
||||
trait_bounds.into_iter()
|
||||
.map(|b| instantiate_trait_ref(ccx, b, param_ty.to_ty(ccx.tcx)))
|
||||
.map(|b| {
|
||||
instantiate_trait_ref(this,
|
||||
b,
|
||||
param_ty.to_ty(this.tcx()),
|
||||
Some(param_ty.to_ty(this.tcx())))
|
||||
})
|
||||
.chain(unboxed_fn_ty_bounds)
|
||||
.collect();
|
||||
let region_bounds: Vec<ty::Region> =
|
||||
region_bounds.move_iter()
|
||||
.map(|r| ast_region_to_region(ccx.tcx, r))
|
||||
.map(|r| ast_region_to_region(this.tcx(), r))
|
||||
.collect();
|
||||
ty::ParamBounds {
|
||||
region_bounds: region_bounds,
|
||||
@@ -1291,12 +2189,11 @@ fn conv_param_bounds(ccx: &CrateCtxt,
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_param_bounds<'a>(ccx: &CrateCtxt,
|
||||
fn merge_param_bounds<'a>(tcx: &ty::ctxt,
|
||||
param_ty: ty::ParamTy,
|
||||
ast_bounds: &'a [ast::TyParamBound],
|
||||
where_clause: &'a ast::WhereClause)
|
||||
-> Vec<&'a ast::TyParamBound>
|
||||
{
|
||||
-> Vec<&'a ast::TyParamBound> {
|
||||
/*!
|
||||
* Merges the bounds declared on a type parameter with those
|
||||
* found from where clauses into a single list.
|
||||
@@ -1309,15 +2206,13 @@ fn merge_param_bounds<'a>(ccx: &CrateCtxt,
|
||||
}
|
||||
|
||||
for predicate in where_clause.predicates.iter() {
|
||||
let predicate_param_id = ccx.tcx
|
||||
.def_map
|
||||
.borrow()
|
||||
.find(&predicate.id)
|
||||
.expect("compute_bounds(): resolve \
|
||||
didn't resolve the type \
|
||||
parameter identifier in a \
|
||||
`where` clause")
|
||||
.def_id();
|
||||
let predicate_param_id =
|
||||
tcx.def_map
|
||||
.borrow()
|
||||
.find(&predicate.id)
|
||||
.expect("compute_bounds(): resolve didn't resolve the type \
|
||||
parameter identifier in a `where` clause")
|
||||
.def_id();
|
||||
if param_ty.def_id != predicate_param_id {
|
||||
continue
|
||||
}
|
||||
@@ -1334,8 +2229,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
|
||||
def_id: ast::DefId,
|
||||
ast_generics: &ast::Generics,
|
||||
abi: abi::Abi)
|
||||
-> ty::Polytype {
|
||||
|
||||
-> ty::Polytype {
|
||||
for i in decl.inputs.iter() {
|
||||
match (*i).pat.node {
|
||||
ast::PatIdent(_, _, _) => (),
|
||||
@@ -1347,9 +2241,11 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
|
||||
}
|
||||
}
|
||||
|
||||
let ty_generics_for_fn_or_method =
|
||||
ty_generics_for_fn_or_method(ccx, ast_generics,
|
||||
ty::Generics::empty());
|
||||
let ty_generics_for_fn_or_method = ty_generics_for_fn_or_method(
|
||||
ccx,
|
||||
ast_generics,
|
||||
ty::Generics::empty(),
|
||||
DontCreateTypeParametersForAssociatedTypes);
|
||||
let rb = BindingRscope::new(def_id.node);
|
||||
let input_tys = decl.inputs
|
||||
.iter()
|
||||
|
||||
@@ -871,6 +871,7 @@ fn give_suggestion(&self, same_regions: &[SameRegions]) {
|
||||
Some(&m.pe_explicit_self().node),
|
||||
m.span))
|
||||
}
|
||||
ast::TypeImplItem(_) => None,
|
||||
}
|
||||
},
|
||||
_ => None
|
||||
@@ -1687,6 +1688,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
|
||||
taken.push_all(m.pe_generics().lifetimes.as_slice());
|
||||
Some(m.id)
|
||||
}
|
||||
ast::TypeImplItem(_) => None,
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
|
||||
@@ -522,6 +522,7 @@ fn visit_item(&mut self, item: &ast::Item) {
|
||||
self.add_constraints_from_sig(&method.fty.sig,
|
||||
self.covariant);
|
||||
}
|
||||
ty::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -603,9 +603,11 @@ fn repr(&self, _tcx: &ctxt) -> String {
|
||||
|
||||
impl Repr for ty::TypeParameterDef {
|
||||
fn repr(&self, tcx: &ctxt) -> String {
|
||||
format!("TypeParameterDef({}, {})",
|
||||
self.def_id.repr(tcx),
|
||||
self.bounds.repr(tcx))
|
||||
format!("TypeParameterDef({}, {}, {}/{})",
|
||||
self.def_id,
|
||||
self.bounds.repr(tcx),
|
||||
self.space,
|
||||
self.index)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -316,6 +316,10 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
|
||||
};
|
||||
Some(item)
|
||||
}
|
||||
ty::TypeTraitItem(_) => {
|
||||
// FIXME(pcwalton): Implement.
|
||||
None
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
return Some(clean::Item {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
use syntax::ast_util::PostExpansionMethod;
|
||||
use syntax::attr;
|
||||
use syntax::attr::{AttributeMethods, AttrMetaMethods};
|
||||
use syntax::codemap::Pos;
|
||||
use syntax::codemap::{DUMMY_SP, Pos};
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax::parse::token;
|
||||
use syntax::ptr::P;
|
||||
@@ -317,6 +317,7 @@ pub enum ItemEnum {
|
||||
ForeignStaticItem(Static),
|
||||
MacroItem(Macro),
|
||||
PrimitiveItem(Primitive),
|
||||
AssociatedTypeItem,
|
||||
}
|
||||
|
||||
#[deriving(Clone, Encodable, Decodable)]
|
||||
@@ -933,6 +934,7 @@ fn clean(&self, cx: &DocContext) -> Type {
|
||||
pub enum TraitItem {
|
||||
RequiredMethod(Item),
|
||||
ProvidedMethod(Item),
|
||||
TypeTraitItem(Item),
|
||||
}
|
||||
|
||||
impl TraitItem {
|
||||
@@ -952,6 +954,7 @@ pub fn item<'a>(&'a self) -> &'a Item {
|
||||
match *self {
|
||||
RequiredMethod(ref item) => item,
|
||||
ProvidedMethod(ref item) => item,
|
||||
TypeTraitItem(ref item) => item,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -961,6 +964,7 @@ fn clean(&self, cx: &DocContext) -> TraitItem {
|
||||
match self {
|
||||
&ast::RequiredMethod(ref t) => RequiredMethod(t.clean(cx)),
|
||||
&ast::ProvidedMethod(ref t) => ProvidedMethod(t.clean(cx)),
|
||||
&ast::TypeTraitItem(ref t) => TypeTraitItem(t.clean(cx)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -968,12 +972,14 @@ fn clean(&self, cx: &DocContext) -> TraitItem {
|
||||
#[deriving(Clone, Encodable, Decodable)]
|
||||
pub enum ImplItem {
|
||||
MethodImplItem(Item),
|
||||
TypeImplItem(Item),
|
||||
}
|
||||
|
||||
impl Clean<ImplItem> for ast::ImplItem {
|
||||
fn clean(&self, cx: &DocContext) -> ImplItem {
|
||||
match self {
|
||||
&ast::MethodImplItem(ref t) => MethodImplItem(t.clean(cx)),
|
||||
&ast::TypeImplItem(ref t) => TypeImplItem(t.clean(cx)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1028,6 +1034,7 @@ impl Clean<Item> for ty::ImplOrTraitItem {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
match *self {
|
||||
ty::MethodTraitItem(ref mti) => mti.clean(cx),
|
||||
ty::TypeTraitItem(ref tti) => tti.clean(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1743,6 +1750,7 @@ fn clean(&self, cx: &DocContext) -> Item {
|
||||
items: self.items.clean(cx).into_iter().map(|ti| {
|
||||
match ti {
|
||||
MethodImplItem(i) => i,
|
||||
TypeImplItem(i) => i,
|
||||
}
|
||||
}).collect(),
|
||||
derived: detect_derived(self.attrs.as_slice()),
|
||||
@@ -2125,6 +2133,54 @@ fn clean(&self, _: &DocContext) -> Stability {
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<Item> for ast::AssociatedType {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
Item {
|
||||
source: self.span.clean(cx),
|
||||
name: Some(self.ident.clean(cx)),
|
||||
attrs: self.attrs.clean(cx),
|
||||
inner: AssociatedTypeItem,
|
||||
visibility: None,
|
||||
def_id: ast_util::local_def(self.id),
|
||||
stability: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<Item> for ty::AssociatedType {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
Item {
|
||||
source: DUMMY_SP.clean(cx),
|
||||
name: Some(self.ident.clean(cx)),
|
||||
attrs: Vec::new(),
|
||||
inner: AssociatedTypeItem,
|
||||
visibility: None,
|
||||
def_id: self.def_id,
|
||||
stability: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<Item> for ast::Typedef {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
Item {
|
||||
source: self.span.clean(cx),
|
||||
name: Some(self.ident.clean(cx)),
|
||||
attrs: self.attrs.clean(cx),
|
||||
inner: TypedefItem(Typedef {
|
||||
type_: self.typ.clean(cx),
|
||||
generics: Generics {
|
||||
lifetimes: Vec::new(),
|
||||
type_params: Vec::new(),
|
||||
},
|
||||
}),
|
||||
visibility: None,
|
||||
def_id: ast_util::local_def(self.id),
|
||||
stability: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lang_struct(cx: &DocContext, did: Option<ast::DefId>,
|
||||
t: ty::t, name: &str,
|
||||
fallback: fn(Box<Type>) -> Type) -> Type {
|
||||
|
||||
@@ -55,6 +55,12 @@ fn vtrm<T: DocFolder>(this: &mut T, trm: TraitItem)
|
||||
None => return None,
|
||||
}
|
||||
},
|
||||
TypeTraitItem(it) => {
|
||||
match this.fold_item(it) {
|
||||
Some(x) => return Some(TypeTraitItem(x)),
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut foo = Vec::new(); swap(&mut foo, &mut i.items);
|
||||
|
||||
@@ -38,6 +38,7 @@ pub enum ItemType {
|
||||
ForeignStatic = 14,
|
||||
Macro = 15,
|
||||
Primitive = 16,
|
||||
AssociatedType = 17,
|
||||
}
|
||||
|
||||
impl ItemType {
|
||||
@@ -60,6 +61,7 @@ pub fn to_static_str(&self) -> &'static str {
|
||||
ForeignStatic => "ffs",
|
||||
Macro => "macro",
|
||||
Primitive => "primitive",
|
||||
AssociatedType => "associatedtype",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,6 +97,7 @@ pub fn shortty(item: &clean::Item) -> ItemType {
|
||||
clean::ForeignStaticItem(..) => ForeignStatic,
|
||||
clean::MacroItem(..) => Macro,
|
||||
clean::PrimitiveItem(..) => Primitive,
|
||||
clean::AssociatedTypeItem => AssociatedType,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1512,6 +1512,7 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: uint, idx2: uint) -> Ordering {
|
||||
clean::ForeignStaticItem(..) => ("ffi-statics", "Foreign Statics"),
|
||||
clean::MacroItem(..) => ("macros", "Macros"),
|
||||
clean::PrimitiveItem(..) => ("primitives", "Primitive Types"),
|
||||
clean::AssociatedTypeItem(..) => ("associated-types", "Associated Types"),
|
||||
};
|
||||
try!(write!(w,
|
||||
"<h2 id='{id}' class='section-header'>\
|
||||
|
||||
@@ -175,6 +175,9 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
|
||||
|
||||
// Primitives are never stripped
|
||||
clean::PrimitiveItem(..) => {}
|
||||
|
||||
// Associated types are never stripped
|
||||
clean::AssociatedTypeItem(..) => {}
|
||||
}
|
||||
|
||||
let fastreturn = match i.inner {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
use clean::{Crate, Item, ModuleItem, Module, StructItem, Struct, EnumItem, Enum};
|
||||
use clean::{ImplItem, Impl, Trait, TraitItem, ProvidedMethod, RequiredMethod};
|
||||
use clean::{ViewItemItem, PrimitiveItem};
|
||||
use clean::{TypeTraitItem, ViewItemItem, PrimitiveItem};
|
||||
|
||||
#[deriving(Zero, Encodable, Decodable, PartialEq, Eq)]
|
||||
/// The counts for each stability level.
|
||||
@@ -131,7 +131,8 @@ fn summarize_item(item: &Item) -> (Counts, Option<ModuleSummary>) {
|
||||
fn extract_item<'a>(trait_item: &'a TraitItem) -> &'a Item {
|
||||
match *trait_item {
|
||||
ProvidedMethod(ref item) |
|
||||
RequiredMethod(ref item) => item
|
||||
RequiredMethod(ref item) |
|
||||
TypeTraitItem(ref item) => item
|
||||
}
|
||||
}
|
||||
let subcounts = trait_items.iter()
|
||||
|
||||
@@ -555,6 +555,18 @@ pub enum Expr_ {
|
||||
ExprParen(P<Expr>)
|
||||
}
|
||||
|
||||
/// A "qualified path":
|
||||
///
|
||||
/// <Vec<T> as SomeTrait>::SomeAssociatedItem
|
||||
/// ^~~~~ ^~~~~~~~~ ^~~~~~~~~~~~~~~~~~
|
||||
/// for_type trait_name item_name
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct QPath {
|
||||
pub for_type: P<Ty>,
|
||||
pub trait_name: Path,
|
||||
pub item_name: Ident,
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub enum CaptureClause {
|
||||
CaptureByValue,
|
||||
@@ -766,11 +778,31 @@ pub struct TypeMethod {
|
||||
pub enum TraitItem {
|
||||
RequiredMethod(TypeMethod),
|
||||
ProvidedMethod(P<Method>),
|
||||
TypeTraitItem(P<AssociatedType>),
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub enum ImplItem {
|
||||
MethodImplItem(P<Method>),
|
||||
TypeImplItem(P<Typedef>),
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct AssociatedType {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub ident: Ident,
|
||||
pub attrs: Vec<Attribute>,
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct Typedef {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub ident: Ident,
|
||||
pub vis: Visibility,
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub typ: P<Ty>,
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
|
||||
@@ -917,6 +949,8 @@ pub enum Ty_ {
|
||||
TyUnboxedFn(P<UnboxedFnTy>),
|
||||
TyTup(Vec<P<Ty>> ),
|
||||
TyPath(Path, Option<TyParamBounds>, NodeId), // for #7264; see above
|
||||
/// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
|
||||
TyQPath(P<QPath>),
|
||||
/// No-op; kept solely so that we can pretty-print faithfully
|
||||
TyParen(P<Ty>),
|
||||
TyTypeof(P<Expr>),
|
||||
|
||||
@@ -207,6 +207,9 @@ fn handle<A>(self,
|
||||
ast_map::NodeImplItem(ii) => {
|
||||
match *ii {
|
||||
ast::MethodImplItem(ref m) => method(&**m),
|
||||
ast::TypeImplItem(_) => {
|
||||
fail!("impl method FnLikeNode that is not fn-like")
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_map::NodeExpr(e) => match e.node {
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
use abi;
|
||||
use ast::*;
|
||||
use ast_util;
|
||||
use ast_util::PostExpansionMethod;
|
||||
use codemap::{DUMMY_SP, Span, Spanned};
|
||||
use fold::Folder;
|
||||
use parse::token;
|
||||
use print::pprust;
|
||||
use ptr::P;
|
||||
use visit::{mod, Visitor};
|
||||
|
||||
use arena::TypedArena;
|
||||
@@ -391,16 +391,20 @@ pub fn get_path_elem(&self, id: NodeId) -> PathElem {
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeImplItem(ref t) => PathName(t.ident.name),
|
||||
}
|
||||
},
|
||||
NodeTraitItem(tm) => match *tm {
|
||||
RequiredMethod(ref m) => PathName(m.ident.name),
|
||||
ProvidedMethod(ref m) => match m.node {
|
||||
MethDecl(ident, _, _, _, _, _, _, _) => {
|
||||
PathName(ident.name)
|
||||
ProvidedMethod(ref m) => {
|
||||
match m.node {
|
||||
MethDecl(ident, _, _, _, _, _, _, _) => {
|
||||
PathName(ident.name)
|
||||
}
|
||||
MethMac(_) => fail!("no path elem for {:?}", node),
|
||||
}
|
||||
MethMac(_) => fail!("no path elem for {:?}", node),
|
||||
}
|
||||
TypeTraitItem(ref m) => PathName(m.ident.name),
|
||||
},
|
||||
NodeVariant(v) => PathName(v.node.name.name),
|
||||
_ => fail!("no path elem for {:?}", node)
|
||||
@@ -459,11 +463,13 @@ pub fn with_attrs<T>(&self, id: NodeId, f: |Option<&[Attribute]>| -> T) -> T {
|
||||
NodeForeignItem(fi) => Some(fi.attrs.as_slice()),
|
||||
NodeTraitItem(ref tm) => match **tm {
|
||||
RequiredMethod(ref type_m) => Some(type_m.attrs.as_slice()),
|
||||
ProvidedMethod(ref m) => Some(m.attrs.as_slice())
|
||||
ProvidedMethod(ref m) => Some(m.attrs.as_slice()),
|
||||
TypeTraitItem(ref typ) => Some(typ.attrs.as_slice()),
|
||||
},
|
||||
NodeImplItem(ref ii) => {
|
||||
match **ii {
|
||||
MethodImplItem(ref m) => Some(m.attrs.as_slice()),
|
||||
TypeImplItem(ref t) => Some(t.attrs.as_slice()),
|
||||
}
|
||||
}
|
||||
NodeVariant(ref v) => Some(v.node.attrs.as_slice()),
|
||||
@@ -503,11 +509,13 @@ pub fn opt_span(&self, id: NodeId) -> Option<Span> {
|
||||
match *trait_method {
|
||||
RequiredMethod(ref type_method) => type_method.span,
|
||||
ProvidedMethod(ref method) => method.span,
|
||||
TypeTraitItem(ref typedef) => typedef.span,
|
||||
}
|
||||
}
|
||||
Some(NodeImplItem(ref impl_item)) => {
|
||||
match **impl_item {
|
||||
MethodImplItem(ref method) => method.span,
|
||||
TypeImplItem(ref typedef) => typedef.span,
|
||||
}
|
||||
}
|
||||
Some(NodeVariant(variant)) => variant.span,
|
||||
@@ -633,6 +641,7 @@ fn name(&self) -> Name {
|
||||
match *self {
|
||||
RequiredMethod(ref tm) => tm.ident.name,
|
||||
ProvidedMethod(ref m) => m.name(),
|
||||
TypeTraitItem(ref at) => at.ident.name,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -640,6 +649,7 @@ impl Named for ImplItem {
|
||||
fn name(&self) -> Name {
|
||||
match *self {
|
||||
MethodImplItem(ref m) => m.name(),
|
||||
TypeImplItem(ref td) => td.ident.name,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -712,10 +722,14 @@ fn visit_item(&mut self, i: &'ast Item) {
|
||||
match i.node {
|
||||
ItemImpl(_, _, _, ref impl_items) => {
|
||||
for impl_item in impl_items.iter() {
|
||||
let id = match *impl_item {
|
||||
MethodImplItem(ref m) => m.id
|
||||
};
|
||||
self.insert(id, NodeImplItem(impl_item));
|
||||
match *impl_item {
|
||||
MethodImplItem(ref m) => {
|
||||
self.insert(m.id, NodeImplItem(impl_item));
|
||||
}
|
||||
TypeImplItem(ref t) => {
|
||||
self.insert(t.id, NodeImplItem(impl_item));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemEnum(ref enum_definition, _) => {
|
||||
@@ -737,13 +751,28 @@ fn visit_item(&mut self, i: &'ast Item) {
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
ItemTrait(_, _, _, ref methods) => {
|
||||
for tm in methods.iter() {
|
||||
let id = match *tm {
|
||||
RequiredMethod(ref m) => m.id,
|
||||
ProvidedMethod(ref m) => m.id
|
||||
};
|
||||
self.insert(id, NodeTraitItem(tm));
|
||||
ItemTrait(_, _, ref bounds, ref trait_items) => {
|
||||
for b in bounds.iter() {
|
||||
match *b {
|
||||
TraitTyParamBound(ref t) => {
|
||||
self.insert(t.ref_id, NodeItem(i));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
for tm in trait_items.iter() {
|
||||
match *tm {
|
||||
RequiredMethod(ref m) => {
|
||||
self.insert(m.id, NodeTraitItem(tm));
|
||||
}
|
||||
ProvidedMethod(ref m) => {
|
||||
self.insert(m.id, NodeTraitItem(tm));
|
||||
}
|
||||
TypeTraitItem(ref typ) => {
|
||||
self.insert(typ.id, NodeTraitItem(tm));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@@ -892,6 +921,11 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
|
||||
IITraitItem(fld.fold_ops.new_def_id(d),
|
||||
RequiredMethod(fld.fold_type_method(ty_m)))
|
||||
}
|
||||
TypeTraitItem(at) => {
|
||||
IITraitItem(
|
||||
fld.fold_ops.new_def_id(d),
|
||||
TypeTraitItem(P(fld.fold_associated_type((*at).clone()))))
|
||||
}
|
||||
},
|
||||
IIImplItem(d, m) => match m {
|
||||
MethodImplItem(m) => {
|
||||
@@ -899,6 +933,10 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
|
||||
MethodImplItem(fld.fold_method(m)
|
||||
.expect_one("expected one method")))
|
||||
}
|
||||
TypeImplItem(t) => {
|
||||
IIImplItem(fld.fold_ops.new_def_id(d),
|
||||
TypeImplItem(P(fld.fold_typedef((*t).clone()))))
|
||||
}
|
||||
},
|
||||
IIForeign(i) => IIForeign(fld.fold_foreign_item(i))
|
||||
};
|
||||
@@ -924,14 +962,16 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
|
||||
IITraitItem(_, ref trait_item) => {
|
||||
let trait_item_id = match *trait_item {
|
||||
ProvidedMethod(ref m) => m.id,
|
||||
RequiredMethod(ref m) => m.id
|
||||
RequiredMethod(ref m) => m.id,
|
||||
TypeTraitItem(ref ty) => ty.id,
|
||||
};
|
||||
|
||||
collector.insert(trait_item_id, NodeTraitItem(trait_item));
|
||||
}
|
||||
IIImplItem(_, ref impl_item) => {
|
||||
let impl_item_id = match *impl_item {
|
||||
MethodImplItem(ref m) => m.id
|
||||
MethodImplItem(ref m) => m.id,
|
||||
TypeImplItem(ref ti) => ti.id,
|
||||
};
|
||||
|
||||
collector.insert(impl_item_id, NodeImplItem(impl_item));
|
||||
@@ -1007,16 +1047,30 @@ fn node_id_to_string(map: &Map, id: NodeId) -> String {
|
||||
pprust::mac_to_string(mac), id)
|
||||
}
|
||||
}
|
||||
TypeImplItem(ref t) => {
|
||||
format!("typedef {} in {} (id={})",
|
||||
token::get_ident(t.ident),
|
||||
map.path_to_string(id),
|
||||
id)
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(NodeTraitItem(ref ti)) => {
|
||||
let ident = match **ti {
|
||||
ProvidedMethod(ref m) => m.pe_ident(),
|
||||
RequiredMethod(ref m) => m.ident
|
||||
};
|
||||
format!("method {} in {} (id={})",
|
||||
token::get_ident(ident),
|
||||
map.path_to_string(id), id)
|
||||
Some(NodeTraitItem(ref tm)) => {
|
||||
match **tm {
|
||||
RequiredMethod(_) | ProvidedMethod(_) => {
|
||||
let m = ast_util::trait_item_to_ty_method(&**tm);
|
||||
format!("method {} in {} (id={})",
|
||||
token::get_ident(m.ident),
|
||||
map.path_to_string(id),
|
||||
id)
|
||||
}
|
||||
TypeTraitItem(ref t) => {
|
||||
format!("type item {} in {} (id={})",
|
||||
token::get_ident(t.ident),
|
||||
map.path_to_string(id),
|
||||
id)
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(NodeVariant(ref variant)) => {
|
||||
format!("variant {} in {} (id={})",
|
||||
|
||||
@@ -213,6 +213,62 @@ pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident {
|
||||
token::gensym_ident(pretty.as_slice())
|
||||
}
|
||||
|
||||
pub fn trait_method_to_ty_method(method: &Method) -> TypeMethod {
|
||||
match method.node {
|
||||
MethDecl(ident,
|
||||
ref generics,
|
||||
abi,
|
||||
ref explicit_self,
|
||||
fn_style,
|
||||
ref decl,
|
||||
_,
|
||||
vis) => {
|
||||
TypeMethod {
|
||||
ident: ident,
|
||||
attrs: method.attrs.clone(),
|
||||
fn_style: fn_style,
|
||||
decl: (*decl).clone(),
|
||||
generics: generics.clone(),
|
||||
explicit_self: (*explicit_self).clone(),
|
||||
id: method.id,
|
||||
span: method.span,
|
||||
vis: vis,
|
||||
abi: abi,
|
||||
}
|
||||
},
|
||||
MethMac(_) => fail!("expected non-macro method declaration")
|
||||
}
|
||||
}
|
||||
|
||||
/// extract a TypeMethod from a TraitItem. if the TraitItem is
|
||||
/// a default, pull out the useful fields to make a TypeMethod
|
||||
//
|
||||
// NB: to be used only after expansion is complete, and macros are gone.
|
||||
pub fn trait_item_to_ty_method(method: &TraitItem) -> TypeMethod {
|
||||
match *method {
|
||||
RequiredMethod(ref m) => (*m).clone(),
|
||||
ProvidedMethod(ref m) => trait_method_to_ty_method(&**m),
|
||||
TypeTraitItem(_) => {
|
||||
fail!("trait_method_to_ty_method(): expected method but found \
|
||||
typedef")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn split_trait_methods(trait_methods: &[TraitItem])
|
||||
-> (Vec<TypeMethod>, Vec<P<Method>> ) {
|
||||
let mut reqd = Vec::new();
|
||||
let mut provd = Vec::new();
|
||||
for trt_method in trait_methods.iter() {
|
||||
match *trt_method {
|
||||
RequiredMethod(ref tm) => reqd.push((*tm).clone()),
|
||||
ProvidedMethod(ref m) => provd.push((*m).clone()),
|
||||
TypeTraitItem(_) => {}
|
||||
}
|
||||
};
|
||||
(reqd, provd)
|
||||
}
|
||||
|
||||
pub fn struct_field_visibility(field: ast::StructField) -> Visibility {
|
||||
match field.node.kind {
|
||||
ast::NamedField(_, v) | ast::UnnamedField(v) => v
|
||||
@@ -471,6 +527,7 @@ fn visit_trait_item(&mut self, tm: &ast::TraitItem) {
|
||||
match *tm {
|
||||
ast::RequiredMethod(ref m) => self.operation.visit_id(m.id),
|
||||
ast::ProvidedMethod(ref m) => self.operation.visit_id(m.id),
|
||||
ast::TypeTraitItem(ref typ) => self.operation.visit_id(typ.id),
|
||||
}
|
||||
visit::walk_trait_item(self, tm);
|
||||
}
|
||||
|
||||
@@ -235,13 +235,15 @@ fn view_item_in_cfg(cx: &mut Context, item: &ast::ViewItem) -> bool {
|
||||
fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitItem) -> bool {
|
||||
match *meth {
|
||||
ast::RequiredMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
|
||||
ast::ProvidedMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice())
|
||||
ast::ProvidedMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
|
||||
ast::TypeTraitItem(ref typ) => (cx.in_cfg)(typ.attrs.as_slice()),
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_item_in_cfg(cx: &mut Context, impl_item: &ast::ImplItem) -> bool {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
|
||||
ast::TypeImplItem(ref typ) => (cx.in_cfg)(typ.attrs.as_slice()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,10 @@ fn make_methods(self: Box<ParserAnyMacro<'a>>) -> Option<SmallVector<P<ast::Meth
|
||||
let mut parser = self.parser.borrow_mut();
|
||||
match parser.token {
|
||||
EOF => break,
|
||||
_ => ret.push(parser.parse_method(None))
|
||||
_ => {
|
||||
let attrs = parser.parse_outer_attributes();
|
||||
ret.push(parser.parse_method(attrs, ast::Inherited))
|
||||
}
|
||||
}
|
||||
}
|
||||
self.ensure_complete_parse(false);
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
("import_shadowing", Active),
|
||||
("advanced_slice_patterns", Active),
|
||||
("tuple_indexing", Active),
|
||||
("associated_types", Active),
|
||||
|
||||
// if you change this list without updating src/doc/rust.md, cmr will be sad
|
||||
|
||||
@@ -235,7 +236,7 @@ fn visit_item(&mut self, i: &ast::Item) {
|
||||
}
|
||||
}
|
||||
|
||||
ast::ItemImpl(..) => {
|
||||
ast::ItemImpl(_, _, _, ref items) => {
|
||||
if attr::contains_name(i.attrs.as_slice(),
|
||||
"unsafe_destructor") {
|
||||
self.gate_feature("unsafe_destructor",
|
||||
@@ -244,6 +245,18 @@ fn visit_item(&mut self, i: &ast::Item) {
|
||||
many unsafe patterns and may be \
|
||||
removed in the future");
|
||||
}
|
||||
|
||||
for item in items.iter() {
|
||||
match *item {
|
||||
ast::MethodImplItem(_) => {}
|
||||
ast::TypeImplItem(ref typedef) => {
|
||||
self.gate_feature("associated_types",
|
||||
typedef.span,
|
||||
"associated types are \
|
||||
experimental")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
@@ -252,6 +265,17 @@ fn visit_item(&mut self, i: &ast::Item) {
|
||||
visit::walk_item(self, i);
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
|
||||
match *trait_item {
|
||||
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
|
||||
ast::TypeTraitItem(ref ti) => {
|
||||
self.gate_feature("associated_types",
|
||||
ti.span,
|
||||
"associated types are experimental")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mac(&mut self, macro: &ast::Mac) {
|
||||
let ast::MacInvocTT(ref path, _, _) = macro.node;
|
||||
let id = path.segments.last().unwrap().identifier;
|
||||
|
||||
+115
-22
@@ -287,6 +287,15 @@ fn fold_where_predicate(&mut self, where_predicate: WherePredicate)
|
||||
noop_fold_where_predicate(where_predicate, self)
|
||||
}
|
||||
|
||||
fn fold_typedef(&mut self, typedef: Typedef) -> Typedef {
|
||||
noop_fold_typedef(typedef, self)
|
||||
}
|
||||
|
||||
fn fold_associated_type(&mut self, associated_type: AssociatedType)
|
||||
-> AssociatedType {
|
||||
noop_fold_associated_type(associated_type, self)
|
||||
}
|
||||
|
||||
fn new_id(&mut self, i: NodeId) -> NodeId {
|
||||
i
|
||||
}
|
||||
@@ -414,6 +423,13 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
|
||||
fld.fold_opt_bounds(bounds),
|
||||
id)
|
||||
}
|
||||
TyQPath(ref qpath) => {
|
||||
TyQPath(P(QPath {
|
||||
for_type: fld.fold_ty(qpath.for_type.clone()),
|
||||
trait_name: fld.fold_path(qpath.trait_name.clone()),
|
||||
item_name: fld.fold_ident(qpath.item_name.clone()),
|
||||
}))
|
||||
}
|
||||
TyFixedLengthVec(ty, e) => {
|
||||
TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
|
||||
}
|
||||
@@ -735,6 +751,44 @@ pub fn noop_fold_where_predicate<T: Folder>(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_typedef<T>(t: Typedef, folder: &mut T)
|
||||
-> Typedef
|
||||
where T: Folder {
|
||||
let new_id = folder.new_id(t.id);
|
||||
let new_span = folder.new_span(t.span);
|
||||
let new_attrs = t.attrs.iter().map(|attr| {
|
||||
folder.fold_attribute((*attr).clone())
|
||||
}).collect();
|
||||
let new_ident = folder.fold_ident(t.ident);
|
||||
let new_type = folder.fold_ty(t.typ);
|
||||
ast::Typedef {
|
||||
ident: new_ident,
|
||||
typ: new_type,
|
||||
id: new_id,
|
||||
span: new_span,
|
||||
vis: t.vis,
|
||||
attrs: new_attrs,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_associated_type<T>(at: AssociatedType, folder: &mut T)
|
||||
-> AssociatedType
|
||||
where T: Folder {
|
||||
let new_id = folder.new_id(at.id);
|
||||
let new_span = folder.new_span(at.span);
|
||||
let new_ident = folder.fold_ident(at.ident);
|
||||
let new_attrs = at.attrs
|
||||
.iter()
|
||||
.map(|attr| folder.fold_attribute((*attr).clone()))
|
||||
.collect();
|
||||
ast::AssociatedType {
|
||||
ident: new_ident,
|
||||
attrs: new_attrs,
|
||||
id: new_id,
|
||||
span: new_span,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_struct_def<T: Folder>(struct_def: P<StructDef>, fld: &mut T) -> P<StructDef> {
|
||||
struct_def.map(|StructDef {fields, ctor_id, super_struct, is_virtual}| StructDef {
|
||||
fields: fields.move_map(|f| fld.fold_struct_field(f)),
|
||||
@@ -857,31 +911,59 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
|
||||
ItemStruct(struct_def, folder.fold_generics(generics))
|
||||
}
|
||||
ItemImpl(generics, ifce, ty, impl_items) => {
|
||||
ItemImpl(folder.fold_generics(generics),
|
||||
ifce.map(|p| folder.fold_trait_ref(p)),
|
||||
folder.fold_ty(ty),
|
||||
impl_items.into_iter().flat_map(|impl_item| match impl_item {
|
||||
MethodImplItem(x) => {
|
||||
folder.fold_method(x).into_iter().map(|x| MethodImplItem(x))
|
||||
let mut new_impl_items = Vec::new();
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
MethodImplItem(ref x) => {
|
||||
for method in folder.fold_method((*x).clone())
|
||||
.move_iter() {
|
||||
new_impl_items.push(MethodImplItem(method))
|
||||
}
|
||||
}).collect())
|
||||
}
|
||||
TypeImplItem(ref t) => {
|
||||
new_impl_items.push(TypeImplItem(
|
||||
P(folder.fold_typedef((**t).clone()))));
|
||||
}
|
||||
}
|
||||
}
|
||||
let ifce = match ifce {
|
||||
None => None,
|
||||
Some(ref trait_ref) => {
|
||||
Some(folder.fold_trait_ref((*trait_ref).clone()))
|
||||
}
|
||||
};
|
||||
ItemImpl(folder.fold_generics(generics),
|
||||
ifce,
|
||||
folder.fold_ty(ty),
|
||||
new_impl_items)
|
||||
}
|
||||
ItemTrait(generics, unbound, bounds, methods) => {
|
||||
let bounds = folder.fold_bounds(bounds);
|
||||
let methods = methods.into_iter().flat_map(|method| match method {
|
||||
RequiredMethod(m) => {
|
||||
SmallVector::one(RequiredMethod(folder.fold_type_method(m))).into_iter()
|
||||
}
|
||||
ProvidedMethod(method) => {
|
||||
// the awkward collect/iter idiom here is because
|
||||
// even though an iter and a map satisfy the same trait bound,
|
||||
// they're not actually the same type, so the method arms
|
||||
// don't unify.
|
||||
let methods: SmallVector<ast::TraitItem> =
|
||||
folder.fold_method(method).into_iter()
|
||||
.map(|m| ProvidedMethod(m)).collect();
|
||||
methods.into_iter()
|
||||
}
|
||||
let methods = methods.into_iter().flat_map(|method| {
|
||||
let r = match method {
|
||||
RequiredMethod(m) => {
|
||||
SmallVector::one(RequiredMethod(
|
||||
folder.fold_type_method(m)))
|
||||
.move_iter()
|
||||
}
|
||||
ProvidedMethod(method) => {
|
||||
// the awkward collect/iter idiom here is because
|
||||
// even though an iter and a map satisfy the same
|
||||
// trait bound, they're not actually the same type, so
|
||||
// the method arms don't unify.
|
||||
let methods: SmallVector<ast::TraitItem> =
|
||||
folder.fold_method(method).move_iter()
|
||||
.map(|m| ProvidedMethod(m)).collect();
|
||||
methods.move_iter()
|
||||
}
|
||||
TypeTraitItem(at) => {
|
||||
SmallVector::one(TypeTraitItem(P(
|
||||
folder.fold_associated_type(
|
||||
(*at).clone()))))
|
||||
.move_iter()
|
||||
}
|
||||
};
|
||||
r
|
||||
}).collect();
|
||||
ItemTrait(folder.fold_generics(generics),
|
||||
unbound,
|
||||
@@ -893,7 +975,18 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
|
||||
}
|
||||
|
||||
pub fn noop_fold_type_method<T: Folder>(m: TypeMethod, fld: &mut T) -> TypeMethod {
|
||||
let TypeMethod {id, ident, attrs, fn_style, abi, decl, generics, explicit_self, vis, span} = m;
|
||||
let TypeMethod {
|
||||
id,
|
||||
ident,
|
||||
attrs,
|
||||
fn_style,
|
||||
abi,
|
||||
decl,
|
||||
generics,
|
||||
explicit_self,
|
||||
vis,
|
||||
span
|
||||
} = m;
|
||||
TypeMethod {
|
||||
id: fld.new_id(id),
|
||||
ident: fld.fold_ident(ident),
|
||||
|
||||
+149
-93
@@ -11,11 +11,11 @@
|
||||
#![macro_escape]
|
||||
|
||||
use abi;
|
||||
use ast::{BareFnTy, ClosureTy};
|
||||
use ast::{AssociatedType, BareFnTy, ClosureTy};
|
||||
use ast::{RegionTyParamBound, TraitTyParamBound};
|
||||
use ast::{ProvidedMethod, Public, FnStyle};
|
||||
use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
|
||||
use ast::{BiBitAnd, BiBitOr, BiBitXor, Block};
|
||||
use ast::{BiBitAnd, BiBitOr, BiBitXor, BiRem, Block};
|
||||
use ast::{BlockCheckMode, UnBox};
|
||||
use ast::{CaptureByRef, CaptureByValue, CaptureClause};
|
||||
use ast::{Crate, CrateConfig, Decl, DeclItem};
|
||||
@@ -42,7 +42,7 @@
|
||||
use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot};
|
||||
use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct};
|
||||
use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle};
|
||||
use ast::{BiRem, RequiredMethod};
|
||||
use ast::{QPath, RequiredMethod};
|
||||
use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl};
|
||||
use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
|
||||
use ast::{StructVariantKind, BiSub};
|
||||
@@ -52,10 +52,10 @@
|
||||
use ast::{TTNonterminal, TupleVariantKind, Ty, Ty_, TyBot, TyBox};
|
||||
use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
|
||||
use ast::{TyTypeof, TyInfer, TypeMethod};
|
||||
use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPtr, TyRptr};
|
||||
use ast::{TyTup, TyU32, TyUnboxedFn, TyUniq, TyVec, UnUniq};
|
||||
use ast::{UnboxedClosureKind, UnboxedFnTy, UnboxedFnTyParamBound};
|
||||
use ast::{UnnamedField, UnsafeBlock};
|
||||
use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPtr, TyQPath};
|
||||
use ast::{TyRptr, TyTup, TyU32, TyUnboxedFn, TyUniq, TyVec, UnUniq};
|
||||
use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind};
|
||||
use ast::{UnboxedFnTy, UnboxedFnTyParamBound, UnnamedField, UnsafeBlock};
|
||||
use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
|
||||
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
|
||||
use ast::{Visibility, WhereClause, WherePredicate};
|
||||
@@ -1235,86 +1235,125 @@ pub fn parse_ty_fn_decl(&mut self, allow_variadic: bool)
|
||||
(decl, lifetime_defs)
|
||||
}
|
||||
|
||||
/// Parse the methods in a trait declaration
|
||||
pub fn parse_trait_methods(&mut self) -> Vec<TraitItem> {
|
||||
/// Parses `type Foo;` in a trait declaration only. The `type` keyword has
|
||||
/// already been parsed.
|
||||
fn parse_associated_type(&mut self, attrs: Vec<Attribute>)
|
||||
-> AssociatedType {
|
||||
let lo = self.span.lo;
|
||||
let ident = self.parse_ident();
|
||||
let hi = self.span.hi;
|
||||
self.expect(&token::SEMI);
|
||||
AssociatedType {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: mk_sp(lo, hi),
|
||||
ident: ident,
|
||||
attrs: attrs,
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses `type Foo = TYPE;` in an implementation declaration only. The
|
||||
/// `type` keyword has already been parsed.
|
||||
fn parse_typedef(&mut self, attrs: Vec<Attribute>, vis: Visibility)
|
||||
-> Typedef {
|
||||
let lo = self.span.lo;
|
||||
let ident = self.parse_ident();
|
||||
self.expect(&token::EQ);
|
||||
let typ = self.parse_ty(true);
|
||||
let hi = self.span.hi;
|
||||
self.expect(&token::SEMI);
|
||||
Typedef {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: mk_sp(lo, hi),
|
||||
ident: ident,
|
||||
vis: vis,
|
||||
attrs: attrs,
|
||||
typ: typ,
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse the items in a trait declaration
|
||||
pub fn parse_trait_items(&mut self) -> Vec<TraitItem> {
|
||||
self.parse_unspanned_seq(
|
||||
&token::LBRACE,
|
||||
&token::RBRACE,
|
||||
seq_sep_none(),
|
||||
|p| {
|
||||
let attrs = p.parse_outer_attributes();
|
||||
let lo = p.span.lo;
|
||||
|
||||
// NB: at the moment, trait methods are public by default; this
|
||||
// could change.
|
||||
let vis = p.parse_visibility();
|
||||
let abi = if p.eat_keyword(keywords::Extern) {
|
||||
p.parse_opt_abi().unwrap_or(abi::C)
|
||||
} else if attr::contains_name(attrs.as_slice(),
|
||||
"rust_call_abi_hack") {
|
||||
// FIXME(stage0, pcwalton): Remove this awful hack after a
|
||||
// snapshot, and change to `extern "rust-call" fn`.
|
||||
abi::RustCall
|
||||
if p.eat_keyword(keywords::Type) {
|
||||
TypeTraitItem(P(p.parse_associated_type(attrs)))
|
||||
} else {
|
||||
abi::Rust
|
||||
};
|
||||
let style = p.parse_fn_style();
|
||||
let ident = p.parse_ident();
|
||||
let lo = p.span.lo;
|
||||
|
||||
let mut generics = p.parse_generics();
|
||||
let vis = p.parse_visibility();
|
||||
let abi = if p.eat_keyword(keywords::Extern) {
|
||||
p.parse_opt_abi().unwrap_or(abi::C)
|
||||
} else if attr::contains_name(attrs.as_slice(),
|
||||
"rust_call_abi_hack") {
|
||||
// FIXME(stage0, pcwalton): Remove this awful hack after a
|
||||
// snapshot, and change to `extern "rust-call" fn`.
|
||||
abi::RustCall
|
||||
} else {
|
||||
abi::Rust
|
||||
};
|
||||
|
||||
let (explicit_self, d) = p.parse_fn_decl_with_self(|p| {
|
||||
// This is somewhat dubious; We don't want to allow argument
|
||||
// names to be left off if there is a definition...
|
||||
p.parse_arg_general(false)
|
||||
});
|
||||
let style = p.parse_fn_style();
|
||||
let ident = p.parse_ident();
|
||||
let mut generics = p.parse_generics();
|
||||
|
||||
p.parse_where_clause(&mut generics);
|
||||
let (explicit_self, d) = p.parse_fn_decl_with_self(|p| {
|
||||
// This is somewhat dubious; We don't want to allow
|
||||
// argument names to be left off if there is a
|
||||
// definition...
|
||||
p.parse_arg_general(false)
|
||||
});
|
||||
|
||||
let hi = p.last_span.hi;
|
||||
match p.token {
|
||||
token::SEMI => {
|
||||
p.bump();
|
||||
debug!("parse_trait_methods(): parsing required method");
|
||||
RequiredMethod(TypeMethod {
|
||||
ident: ident,
|
||||
attrs: attrs,
|
||||
fn_style: style,
|
||||
decl: d,
|
||||
generics: generics,
|
||||
abi: abi,
|
||||
explicit_self: explicit_self,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: mk_sp(lo, hi),
|
||||
vis: vis,
|
||||
})
|
||||
}
|
||||
token::LBRACE => {
|
||||
debug!("parse_trait_methods(): parsing provided method");
|
||||
let (inner_attrs, body) =
|
||||
p.parse_inner_attrs_and_block();
|
||||
let mut attrs = attrs;
|
||||
attrs.extend(inner_attrs.into_iter());
|
||||
ProvidedMethod(P(ast::Method {
|
||||
attrs: attrs,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: mk_sp(lo, hi),
|
||||
node: ast::MethDecl(ident,
|
||||
generics,
|
||||
abi,
|
||||
explicit_self,
|
||||
style,
|
||||
d,
|
||||
body,
|
||||
vis)
|
||||
}))
|
||||
}
|
||||
p.parse_where_clause(&mut generics);
|
||||
|
||||
_ => {
|
||||
let token_str = p.this_token_to_string();
|
||||
p.fatal((format!("expected `;` or `{{`, found `{}`",
|
||||
token_str)).as_slice())
|
||||
}
|
||||
let hi = p.last_span.hi;
|
||||
match p.token {
|
||||
token::SEMI => {
|
||||
p.bump();
|
||||
debug!("parse_trait_methods(): parsing required method");
|
||||
RequiredMethod(TypeMethod {
|
||||
ident: ident,
|
||||
attrs: attrs,
|
||||
fn_style: style,
|
||||
decl: d,
|
||||
generics: generics,
|
||||
abi: abi,
|
||||
explicit_self: explicit_self,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: mk_sp(lo, hi),
|
||||
vis: vis,
|
||||
})
|
||||
}
|
||||
token::LBRACE => {
|
||||
debug!("parse_trait_methods(): parsing provided method");
|
||||
let (inner_attrs, body) =
|
||||
p.parse_inner_attrs_and_block();
|
||||
let attrs = attrs.append(inner_attrs.as_slice());
|
||||
ProvidedMethod(P(ast::Method {
|
||||
attrs: attrs,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: mk_sp(lo, hi),
|
||||
node: ast::MethDecl(ident,
|
||||
generics,
|
||||
abi,
|
||||
explicit_self,
|
||||
style,
|
||||
d,
|
||||
body,
|
||||
vis)
|
||||
}))
|
||||
}
|
||||
|
||||
_ => {
|
||||
let token_str = p.this_token_to_string();
|
||||
p.fatal((format!("expected `;` or `{{`, found `{}`",
|
||||
token_str)).as_slice())
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1455,12 +1494,11 @@ pub fn parse_ty(&mut self, plus_allowed: bool) -> P<Ty> {
|
||||
} else if self.token_is_closure_keyword() ||
|
||||
self.token == token::BINOP(token::OR) ||
|
||||
self.token == token::OROR ||
|
||||
self.token == token::LT {
|
||||
(self.token == token::LT &&
|
||||
self.look_ahead(1, |t| {
|
||||
*t == token::GT || Parser::token_is_lifetime(t)
|
||||
})) {
|
||||
// CLOSURE
|
||||
//
|
||||
// FIXME(pcwalton): Eventually `token::LT` will not unambiguously
|
||||
// introduce a closure, once procs can have lifetime bounds. We
|
||||
// will need to refactor the grammar a little bit at that point.
|
||||
|
||||
self.parse_ty_closure()
|
||||
} else if self.eat_keyword(keywords::Typeof) {
|
||||
@@ -1472,6 +1510,20 @@ pub fn parse_ty(&mut self, plus_allowed: bool) -> P<Ty> {
|
||||
TyTypeof(e)
|
||||
} else if self.eat_keyword(keywords::Proc) {
|
||||
self.parse_proc_type()
|
||||
} else if self.token == token::LT {
|
||||
// QUALIFIED PATH
|
||||
self.bump();
|
||||
let for_type = self.parse_ty(true);
|
||||
self.expect_keyword(keywords::As);
|
||||
let trait_name = self.parse_path(LifetimeAndTypesWithoutColons);
|
||||
self.expect(&token::GT);
|
||||
self.expect(&token::MOD_SEP);
|
||||
let item_name = self.parse_ident();
|
||||
TyQPath(P(QPath {
|
||||
for_type: for_type,
|
||||
trait_name: trait_name.path,
|
||||
item_name: item_name,
|
||||
}))
|
||||
} else if self.token == token::MOD_SEP
|
||||
|| is_ident_or_path(&self.token) {
|
||||
// NAMED TYPE
|
||||
@@ -2071,7 +2123,7 @@ pub fn parse_bottom_expr(&mut self) -> P<Expr> {
|
||||
}
|
||||
}
|
||||
hi = self.last_span.hi;
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
if self.eat_keyword(keywords::Ref) {
|
||||
return self.parse_lambda_expr(CaptureByRef);
|
||||
@@ -4215,14 +4267,9 @@ fn parse_item_fn(&mut self, fn_style: FnStyle, abi: abi::Abi) -> ItemInfo {
|
||||
|
||||
/// Parse a method in a trait impl, starting with `attrs` attributes.
|
||||
pub fn parse_method(&mut self,
|
||||
already_parsed_attrs: Option<Vec<Attribute>>)
|
||||
attrs: Vec<Attribute>,
|
||||
visa: Visibility)
|
||||
-> P<Method> {
|
||||
let next_attrs = self.parse_outer_attributes();
|
||||
let attrs = match already_parsed_attrs {
|
||||
Some(mut a) => { a.push_all_move(next_attrs); a }
|
||||
None => next_attrs
|
||||
};
|
||||
|
||||
let lo = self.span.lo;
|
||||
|
||||
// code copied from parse_macro_use_or_failure... abstraction!
|
||||
@@ -4251,7 +4298,6 @@ pub fn parse_method(&mut self,
|
||||
self.span.hi) };
|
||||
(ast::MethMac(m), self.span.hi, attrs)
|
||||
} else {
|
||||
let visa = self.parse_visibility();
|
||||
let abi = if self.eat_keyword(keywords::Extern) {
|
||||
self.parse_opt_abi().unwrap_or(abi::C)
|
||||
} else if attr::contains_name(attrs.as_slice(),
|
||||
@@ -4302,18 +4348,28 @@ fn parse_item_trait(&mut self) -> ItemInfo {
|
||||
|
||||
self.parse_where_clause(&mut tps);
|
||||
|
||||
let meths = self.parse_trait_methods();
|
||||
let meths = self.parse_trait_items();
|
||||
(ident, ItemTrait(tps, sized, bounds, meths), None)
|
||||
}
|
||||
|
||||
fn parse_impl_items(&mut self) -> (Vec<ImplItem>, Vec<Attribute>) {
|
||||
let mut impl_items = Vec::new();
|
||||
self.expect(&token::LBRACE);
|
||||
let (inner_attrs, next) = self.parse_inner_attrs_and_next();
|
||||
let mut method_attrs = Some(next);
|
||||
let (inner_attrs, mut method_attrs) =
|
||||
self.parse_inner_attrs_and_next();
|
||||
while !self.eat(&token::RBRACE) {
|
||||
impl_items.push(MethodImplItem(self.parse_method(method_attrs)));
|
||||
method_attrs = None;
|
||||
method_attrs.push_all_move(self.parse_outer_attributes());
|
||||
let vis = self.parse_visibility();
|
||||
if self.eat_keyword(keywords::Type) {
|
||||
impl_items.push(TypeImplItem(P(self.parse_typedef(
|
||||
method_attrs,
|
||||
vis))))
|
||||
} else {
|
||||
impl_items.push(MethodImplItem(self.parse_method(
|
||||
method_attrs,
|
||||
vis)));
|
||||
}
|
||||
method_attrs = self.parse_outer_attributes();
|
||||
}
|
||||
(impl_items, inner_attrs)
|
||||
}
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
// except according to those terms.
|
||||
|
||||
use abi;
|
||||
use ast::{FnMutUnboxedClosureKind, FnOnceUnboxedClosureKind};
|
||||
use ast::{FnUnboxedClosureKind, MethodImplItem};
|
||||
use ast::{RegionTyParamBound, TraitTyParamBound, UnboxedClosureKind};
|
||||
use ast::{UnboxedFnTyParamBound, RequiredMethod, ProvidedMethod};
|
||||
use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
|
||||
use ast::{FnOnceUnboxedClosureKind};
|
||||
use ast::{MethodImplItem, RegionTyParamBound, TraitTyParamBound};
|
||||
use ast::{RequiredMethod, ProvidedMethod, TypeImplItem, TypeTraitItem};
|
||||
use ast::{UnboxedClosureKind, UnboxedFnTyParamBound};
|
||||
use ast;
|
||||
use ast_util;
|
||||
use owned_slice::OwnedSlice;
|
||||
@@ -660,6 +661,16 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
|
||||
ast::TyPath(ref path, ref bounds, _) => {
|
||||
try!(self.print_bounded_path(path, bounds));
|
||||
}
|
||||
ast::TyQPath(ref qpath) => {
|
||||
try!(word(&mut self.s, "<"));
|
||||
try!(self.print_type(&*qpath.for_type));
|
||||
try!(space(&mut self.s));
|
||||
try!(self.word_space("as"));
|
||||
try!(self.print_path(&qpath.trait_name, false));
|
||||
try!(word(&mut self.s, ">"));
|
||||
try!(word(&mut self.s, "::"));
|
||||
try!(self.print_ident(qpath.item_name));
|
||||
}
|
||||
ast::TyFixedLengthVec(ref ty, ref v) => {
|
||||
try!(word(&mut self.s, "["));
|
||||
try!(self.print_type(&**ty));
|
||||
@@ -708,6 +719,22 @@ pub fn print_foreign_item(&mut self,
|
||||
}
|
||||
}
|
||||
|
||||
fn print_associated_type(&mut self, typedef: &ast::AssociatedType)
|
||||
-> IoResult<()> {
|
||||
try!(self.word_space("type"));
|
||||
try!(self.print_ident(typedef.ident));
|
||||
word(&mut self.s, ";")
|
||||
}
|
||||
|
||||
fn print_typedef(&mut self, typedef: &ast::Typedef) -> IoResult<()> {
|
||||
try!(self.word_space("type"));
|
||||
try!(self.print_ident(typedef.ident));
|
||||
try!(space(&mut self.s));
|
||||
try!(self.word_space("="));
|
||||
try!(self.print_type(&*typedef.typ));
|
||||
word(&mut self.s, ";")
|
||||
}
|
||||
|
||||
/// Pretty-print an item
|
||||
pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
|
||||
try!(self.hardbreak_if_not_bol());
|
||||
@@ -825,6 +852,9 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
|
||||
ast::MethodImplItem(ref meth) => {
|
||||
try!(self.print_method(&**meth));
|
||||
}
|
||||
ast::TypeImplItem(ref typ) => {
|
||||
try!(self.print_typedef(&**typ));
|
||||
}
|
||||
}
|
||||
}
|
||||
try!(self.bclose(item.span));
|
||||
@@ -1071,13 +1101,15 @@ pub fn print_trait_method(&mut self,
|
||||
m: &ast::TraitItem) -> IoResult<()> {
|
||||
match *m {
|
||||
RequiredMethod(ref ty_m) => self.print_ty_method(ty_m),
|
||||
ProvidedMethod(ref m) => self.print_method(&**m)
|
||||
ProvidedMethod(ref m) => self.print_method(&**m),
|
||||
TypeTraitItem(ref t) => self.print_associated_type(&**t),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> IoResult<()> {
|
||||
match *ii {
|
||||
MethodImplItem(ref m) => self.print_method(&**m),
|
||||
TypeImplItem(ref td) => self.print_typedef(&**td),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+22
-5
@@ -116,12 +116,19 @@ fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) {
|
||||
fn visit_attribute(&mut self, _attr: &'v Attribute) {}
|
||||
}
|
||||
|
||||
pub fn walk_inlined_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v InlinedItem) {
|
||||
pub fn walk_inlined_item<'v,V>(visitor: &mut V, item: &'v InlinedItem)
|
||||
where V: Visitor<'v> {
|
||||
match *item {
|
||||
IIItem(ref i) => visitor.visit_item(&**i),
|
||||
IIForeign(ref i) => visitor.visit_foreign_item(&**i),
|
||||
IITraitItem(_, ref ti) => visitor.visit_trait_item(ti),
|
||||
IIImplItem(_, MethodImplItem(ref m)) => walk_method_helper(visitor, &**m)
|
||||
IIImplItem(_, MethodImplItem(ref m)) => {
|
||||
walk_method_helper(visitor, &**m)
|
||||
}
|
||||
IIImplItem(_, TypeImplItem(ref typedef)) => {
|
||||
visitor.visit_ident(typedef.span, typedef.ident);
|
||||
visitor.visit_ty(&*typedef.typ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,6 +255,10 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
|
||||
MethodImplItem(ref method) => {
|
||||
walk_method_helper(visitor, &**method)
|
||||
}
|
||||
TypeImplItem(ref typedef) => {
|
||||
visitor.visit_ident(typedef.span, typedef.ident);
|
||||
visitor.visit_ty(&*typedef.typ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -366,6 +377,11 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
|
||||
None => { }
|
||||
}
|
||||
}
|
||||
TyQPath(ref qpath) => {
|
||||
visitor.visit_ty(&*qpath.for_type);
|
||||
visitor.visit_path(&qpath.trait_name, typ.id);
|
||||
visitor.visit_ident(typ.span, qpath.item_name);
|
||||
}
|
||||
TyFixedLengthVec(ref ty, ref expression) => {
|
||||
visitor.visit_ty(&**ty);
|
||||
visitor.visit_expr(&**expression)
|
||||
@@ -573,10 +589,11 @@ pub fn walk_ty_method<'v, V: Visitor<'v>>(visitor: &mut V, method_type: &'v Type
|
||||
|
||||
pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_method: &'v TraitItem) {
|
||||
match *trait_method {
|
||||
RequiredMethod(ref method_type) => {
|
||||
visitor.visit_ty_method(method_type)
|
||||
}
|
||||
RequiredMethod(ref method_type) => visitor.visit_ty_method(method_type),
|
||||
ProvidedMethod(ref method) => walk_method_helper(visitor, &**method),
|
||||
TypeTraitItem(ref associated_type) => {
|
||||
visitor.visit_ident(associated_type.span, associated_type.ident)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
trait Get {
|
||||
type Value; //~ ERROR associated types are experimental
|
||||
fn get(&self) -> Get::Value;
|
||||
}
|
||||
|
||||
struct Struct {
|
||||
x: int,
|
||||
}
|
||||
|
||||
impl Get for Struct {
|
||||
type Value = int; //~ ERROR associated types are experimental
|
||||
fn get(&self) -> int {
|
||||
self.x
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = Struct {
|
||||
x: 100,
|
||||
};
|
||||
assert_eq!(s.get(), 100);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
trait Get {
|
||||
type Value;
|
||||
fn get(&self) -> <Self as Get>::Value;
|
||||
}
|
||||
|
||||
fn get<T:Get,U:Get>(x: T, y: U) -> Get::Value {}
|
||||
//~^ ERROR ambiguous associated type
|
||||
|
||||
trait Other {
|
||||
fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
|
||||
//~^ ERROR this associated type is not allowed in this context
|
||||
}
|
||||
|
||||
impl<T:Get> Other for T {
|
||||
fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
|
||||
//~^ ERROR this associated type is not allowed in this context
|
||||
}
|
||||
|
||||
trait Grab {
|
||||
type Value;
|
||||
fn grab(&self) -> Grab::Value;
|
||||
//~^ ERROR ambiguous associated type
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
trait Get {
|
||||
type Value;
|
||||
fn get(&self) -> <Self as Get>::Value;
|
||||
}
|
||||
|
||||
fn get(x: int) -> <int as Get>::Value {}
|
||||
//~^ ERROR this associated type is not allowed in this context
|
||||
|
||||
struct Struct {
|
||||
x: int,
|
||||
}
|
||||
|
||||
impl Struct {
|
||||
fn uhoh<T>(foo: <T as Get>::Value) {}
|
||||
//~^ ERROR this associated type is not allowed in this context
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ struct cat {
|
||||
}
|
||||
|
||||
impl animal for cat {
|
||||
//~^ ERROR not all trait methods implemented, missing: `eat`
|
||||
//~^ ERROR not all trait items implemented, missing: `eat`
|
||||
}
|
||||
|
||||
fn cat(in_x : uint) -> cat {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#[deriving(PartialEq)]
|
||||
struct thing(uint);
|
||||
impl PartialOrd for thing { //~ ERROR not all trait methods implemented, missing: `partial_cmp`
|
||||
impl PartialOrd for thing { //~ ERROR not all trait items implemented, missing: `partial_cmp`
|
||||
fn le(&self, other: &thing) -> bool { true }
|
||||
fn ge(&self, other: &thing) -> bool { true }
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ impl MyEq for int {
|
||||
fn eq(&self, other: &int) -> bool { *self == *other }
|
||||
}
|
||||
|
||||
impl MyEq for A {} //~ ERROR not all trait methods implemented, missing: `eq`
|
||||
impl MyEq for A {} //~ ERROR not all trait items implemented, missing: `eq`
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
trait Get {
|
||||
type Value;
|
||||
fn get(&self) -> &<Self as Get>::Value;
|
||||
fn grab(&self) -> &<Self as Get>::Value {
|
||||
self.get()
|
||||
}
|
||||
}
|
||||
|
||||
struct Struct {
|
||||
x: int,
|
||||
}
|
||||
|
||||
impl Get for Struct {
|
||||
type Value = int;
|
||||
fn get(&self) -> &int {
|
||||
&self.x
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = Struct {
|
||||
x: 100,
|
||||
};
|
||||
assert_eq!(*s.grab(), 100);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
trait Get {
|
||||
type Value;
|
||||
fn get(&self) -> &<Self as Get>::Value;
|
||||
}
|
||||
|
||||
struct Struct {
|
||||
x: int,
|
||||
}
|
||||
|
||||
impl Get for Struct {
|
||||
type Value = int;
|
||||
fn get(&self) -> &int {
|
||||
&self.x
|
||||
}
|
||||
}
|
||||
|
||||
fn grab<T:Get>(x: &T) -> &<T as Get>::Value {
|
||||
x.get()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = Struct {
|
||||
x: 100,
|
||||
};
|
||||
assert_eq!(*grab(&s), 100);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
trait Get {
|
||||
type Value;
|
||||
fn get(&self) -> &<Self as Get>::Value;
|
||||
}
|
||||
|
||||
struct Struct {
|
||||
x: int,
|
||||
}
|
||||
|
||||
impl Get for Struct {
|
||||
type Value = int;
|
||||
fn get(&self) -> &int {
|
||||
&self.x
|
||||
}
|
||||
}
|
||||
|
||||
trait Grab {
|
||||
type U;
|
||||
fn grab(&self) -> &<Self as Grab>::U;
|
||||
}
|
||||
|
||||
impl<T:Get> Grab for T {
|
||||
type U = <T as Get>::Value;
|
||||
fn grab(&self) -> &<T as Get>::Value {
|
||||
self.get()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = Struct {
|
||||
x: 100,
|
||||
};
|
||||
assert_eq!(*s.grab(), 100);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
trait Get {
|
||||
type Value;
|
||||
fn get(&self) -> &<Self as Get>::Value;
|
||||
}
|
||||
|
||||
struct Struct {
|
||||
x: int,
|
||||
}
|
||||
|
||||
impl Get for Struct {
|
||||
type Value = int;
|
||||
fn get(&self) -> &int {
|
||||
&self.x
|
||||
}
|
||||
}
|
||||
|
||||
impl Struct {
|
||||
fn grab<T:Get>(x: &T) -> &<T as Get>::Value {
|
||||
x.get()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = Struct {
|
||||
x: 100,
|
||||
};
|
||||
assert_eq!(*Struct::grab(&s), 100);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
trait Get {
|
||||
type Value;
|
||||
fn get(&self) -> &<Self as Get>::Value;
|
||||
}
|
||||
|
||||
struct Struct {
|
||||
x: int,
|
||||
}
|
||||
|
||||
impl Get for Struct {
|
||||
type Value = int;
|
||||
fn get(&self) -> &int {
|
||||
&self.x
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = Struct {
|
||||
x: 100,
|
||||
};
|
||||
assert_eq!(*s.get(), 100);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
struct A;
|
||||
|
||||
macro_rules! make_thirteen_method {() => (pub fn thirteen(&self)->int {13})}
|
||||
macro_rules! make_thirteen_method {() => (fn thirteen(&self)->int {13})}
|
||||
impl A { make_thirteen_method!() }
|
||||
|
||||
fn main() {
|
||||
|
||||
Reference in New Issue
Block a user