mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-04 19:12:50 +00: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:
parent
8067f4425d
commit
78a841810e
@ -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 @@
|
||||
Subproject commit 2dba541881fb8e35246d653bbe2e7c7088777a4a
|
||||
Subproject commit aae04170ccbfeea620502106b581c3c216cd132a
|
@ -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 @@ impl LintPass for Stability {
|
||||
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 @@ impl<'a, 'tcx> AstConv<'tcx> for Context<'a, 'tcx>{
|
||||
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 @@ use metadata::tydecode::{parse_ty_data, parse_region_data, parse_def_id,
|
||||
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 encode_info_for_item(ecx: &EncodeContext,
|
||||
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 encode_info_for_item(ecx: &EncodeContext,
|
||||
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 encode_info_for_item(ecx: &EncodeContext,
|
||||
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 encode_info_for_item(ecx: &EncodeContext,
|
||||
|
||||
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 encode_info_for_item(ecx: &EncodeContext,
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ impl tr for 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 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
||||
ty::MethodTraitItem(method) => {
|
||||
self.check_def_id(method.def_id);
|
||||
}
|
||||
ty::TypeTraitItem(typedef) => {
|
||||
self.check_def_id(typedef.def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -226,6 +229,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
||||
ast::MethodImplItem(ref method) => {
|
||||
visit::walk_block(self, method.pe_body());
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
ast_map::NodeForeignItem(foreign_item) => {
|
||||
@ -341,6 +345,7 @@ impl<'v> Visitor<'v> for LifeSeeder {
|
||||
ast::MethodImplItem(ref method) => {
|
||||
self.worklist.push(method.id);
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -544,7 +549,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
|
||||
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 @@ impl Def {
|
||||
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 @@ impl Def {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,6 +134,9 @@ impl OverloadedCallType {
|
||||
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 @@ impl 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 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||
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 @@ impl<'v> Visitor<'v> for ParentVisitor {
|
||||
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 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
|
||||
self.exported_items.insert(method.id);
|
||||
}
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -290,6 +296,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
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 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||
_ => m.pe_vis()
|
||||
}
|
||||
}
|
||||
ast::TypeImplItem(_) => return Allowable,
|
||||
}
|
||||
}
|
||||
Some(ast_map::NodeTraitItem(_)) => {
|
||||
@ -670,6 +706,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
|
||||
ast::MethodImplItem(ref m) => {
|
||||
check_inherited(m.span, m.pe_vis(), "");
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1149,6 +1187,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
|
||||
check_inherited(m.span, m.vis,
|
||||
"unnecessary visibility");
|
||||
}
|
||||
ast::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1184,6 +1223,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
|
||||
ast::MethodImplItem(ref m) => {
|
||||
check_inherited(tcx, m.span, m.pe_vis());
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1211,6 +1251,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
|
||||
ast::RequiredMethod(..) => {}
|
||||
ast::ProvidedMethod(ref m) => check_inherited(tcx, m.span,
|
||||
m.pe_vis()),
|
||||
ast::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1351,6 +1392,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
|
||||
ast::MethodImplItem(ref m) => {
|
||||
self.exported_items.contains(&m.id)
|
||||
}
|
||||
ast::TypeImplItem(_) => false,
|
||||
}
|
||||
});
|
||||
|
||||
@ -1367,6 +1409,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
|
||||
ast::MethodImplItem(ref method) => {
|
||||
visit::walk_method_helper(self, &**method)
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1401,6 +1444,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
|
||||
visit::walk_method_helper(self, &**method);
|
||||
}
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
if found_pub_static {
|
||||
|
@ -197,6 +197,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||
match *trait_method {
|
||||
ast::RequiredMethod(_) => false,
|
||||
ast::ProvidedMethod(_) => true,
|
||||
ast::TypeTraitItem(_) => false,
|
||||
}
|
||||
}
|
||||
Some(ast_map::NodeImplItem(impl_item)) => {
|
||||
@ -225,6 +226,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::TypeImplItem(_) => false,
|
||||
}
|
||||
}
|
||||
Some(_) => false,
|
||||
@ -327,8 +329,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||
// 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 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||
visit::walk_block(self, method.pe_body())
|
||||
}
|
||||
}
|
||||
ast::TypeImplItem(_) => {}
|
||||
}
|
||||
}
|
||||
// Nothing to recurse on for these
|
||||
|
@ -37,13 +37,15 @@ use syntax::ast::{RegionTyParamBound, StmtDecl, StructField};
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
// 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 @@ impl<'a> Resolver<'a> {
|
||||
is_public,
|
||||
DUMMY_SP)
|
||||
}
|
||||
DefTy(..) => {
|
||||
DefTy(..) | DefAssociatedTy(..) => {
|
||||
debug!("(building reduced graph for external \
|
||||
crate) building type {}", final_ident);
|
||||
|
||||
@ -4065,6 +4110,9 @@ impl<'a> Resolver<'a> {
|
||||
ProvidedMethod(m.id)),
|
||||
&**m)
|
||||
}
|
||||
ast::TypeTraitItem(_) => {
|
||||
visit::walk_trait_item(this, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -4509,6 +4557,14 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
});
|
||||
}
|
||||
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||
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 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||
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 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||
ast::MethodImplItem(ref method) => {
|
||||
visit::walk_method_helper(self, &**method)
|
||||
}
|
||||
ast::TypeImplItem(ref typedef) => {
|
||||
visit::walk_ty(self, &*typedef.typ)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -764,12 +769,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||
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 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||
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 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||
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 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||
ty::MethodTraitItem(method) => {
|
||||
method.provided_source.unwrap_or(def_id)
|
||||
}
|
||||
ty::TypeTraitItem(_) => def_id,
|
||||
};
|
||||
(Some(def_id), decl_id)
|
||||
}
|
||||
@ -913,23 +909,15 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||
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 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
|
||||
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::codemap::Span;
|
||||
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 @@ impl<'v> Visitor<'v> for Annotator {
|
||||
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 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
|
||||
|
||||
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 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
|
||||
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<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
|
||||
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 @@ impl<'a, 'blk, 'tcx> Reflector<'a, 'blk, 'tcx> {
|
||||
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));
|
||||
|
@ -97,30 +97,37 @@ impl ImplOrTraitItemContainer {
|
||||
#[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 @@ impl ImplOrTraitItem {
|
||||
#[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 @@ impl Method {
|
||||
}
|
||||
}
|
||||
|
||||
#[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 @@ impl 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 @@ impl 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 @@ impl 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 @@ pub fn construct_parameter_environment(
|
||||
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 @@ impl TypeFoldable for ty::TypeParameterDef {
|
||||
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 std::rc::Rc;
|
||||
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 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
|
||||
.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 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
|
||||
// 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::mem::replace;
|
||||
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 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
|
||||
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;
|
||||
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 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
||||
MethodTraitItemId(
|
||||
local_def(ast_method.id))
|
||||
}
|
||||
ast::TypeImplItem(ref typedef) => {
|
||||
TypeTraitItemId(local_def(typedef.id))
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
|
||||
@ -393,6 +396,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
||||
.insert(item_def_id.def_id(), source);
|
||||
}
|
||||
}
|
||||
ty::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -871,6 +871,7 @@ impl<'a, 'tcx> ErrorReporting for InferCtxt<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
|
||||
self.add_constraints_from_sig(&method.fty.sig,
|
||||
self.covariant);
|
||||
}
|
||||
ty::TypeTraitItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -603,9 +603,11 @@ impl Repr for def::Def {
|
||||
|
||||
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;
|
||||
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 @@ impl Clean<Type> for ast::TraitRef {
|
||||
pub enum TraitItem {
|
||||
RequiredMethod(Item),
|
||||
ProvidedMethod(Item),
|
||||
TypeTraitItem(Item),
|
||||
}
|
||||
|
||||
impl TraitItem {
|
||||
@ -952,6 +954,7 @@ impl TraitItem {
|
||||
match *self {
|
||||
RequiredMethod(ref item) => item,
|
||||
ProvidedMethod(ref item) => item,
|
||||
TypeTraitItem(ref item) => item,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -961,6 +964,7 @@ impl Clean<TraitItem> for ast::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 @@ impl Clean<TraitItem> for ast::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 @@ impl Clean<Item> for doctree::Impl {
|
||||
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 @@ impl Clean<Stability> for attr::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 @@ pub trait DocFolder {
|
||||
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 @@ impl ItemType {
|
||||
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 item_module(w: &mut fmt::Formatter, cx: &Context,
|
||||
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 @@ impl<'a> fold::DocFolder for Stripper<'a> {
|
||||
|
||||
// Primitives are never stripped
|
||||
clean::PrimitiveItem(..) => {}
|
||||
|
||||
// Associated types are never stripped
|
||||
clean::AssociatedTypeItem(..) => {}
|
||||
}
|
||||
|
||||
let fastreturn = match i.inner {
|
||||
|
@ -22,7 +22,7 @@ use syntax::ast::Public;
|
||||
|
||||
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 @@ impl<'a> FnLikeNode<'a> {
|
||||
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 @@ impl<'ast> Map<'ast> {
|
||||
}
|
||||
}
|
||||
}
|
||||
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 @@ impl<'ast> Map<'ast> {
|
||||
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 @@ impl<'ast> Map<'ast> {
|
||||
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 @@ impl Named for TraitItem {
|
||||
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 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
||||
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 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
||||
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 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
|
||||
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 @@ impl<'a> MacResult for ParserAnyMacro<'a> {
|
||||
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 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
|
||||
("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 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
|
||||
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 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
|
||||
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;
|
||||
|
@ -287,6 +287,15 @@ pub trait Folder {
|
||||
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),
|
||||
|
@ -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::{MatchSeq, MatchTok, Method, MutTy, BiMul, Mutability};
|
||||
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::{TokenTree, TraitItem, TraitRef, TTDelim, TTSeq, TTTok};
|
||||
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 @@ impl<'a> Parser<'a> {
|
||||
(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 @@ impl<'a> Parser<'a> {
|
||||
} 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 @@ impl<'a> Parser<'a> {
|
||||
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 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
hi = self.last_span.hi;
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
if self.eat_keyword(keywords::Ref) {
|
||||
return self.parse_lambda_expr(CaptureByRef);
|
||||
@ -4215,14 +4267,9 @@ impl<'a> Parser<'a> {
|
||||
|
||||
/// 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 @@ impl<'a> Parser<'a> {
|
||||
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 @@ impl<'a> Parser<'a> {
|
||||
|
||||
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 @@ impl<'a> State<'a> {
|
||||
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 @@ impl<'a> State<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ impl<'a> State<'a> {
|
||||
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 @@ impl<'a> State<'a> {
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,12 +116,19 @@ pub trait Visitor<'v> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
33
src/test/compile-fail/associated-types-feature-gate.rs
Normal file
33
src/test/compile-fail/associated-types-feature-gate.rs
Normal file
@ -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() {
|
||||
}
|
||||
|
32
src/test/compile-fail/associated-types-in-wrong-context.rs
Normal file
32
src/test/compile-fail/associated-types-in-wrong-context.rs
Normal file
@ -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() {
|
||||
}
|
||||
|
39
src/test/run-pass/associated-types-in-default-method.rs
Normal file
39
src/test/run-pass/associated-types-in-default-method.rs
Normal file
@ -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);
|
||||
}
|
||||
|
||||
|
39
src/test/run-pass/associated-types-in-fn.rs
Normal file
39
src/test/run-pass/associated-types-in-fn.rs
Normal file
@ -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);
|
||||
}
|
||||
|
47
src/test/run-pass/associated-types-in-impl-generics.rs
Normal file
47
src/test/run-pass/associated-types-in-impl-generics.rs
Normal file
@ -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);
|
||||
}
|
||||
|
41
src/test/run-pass/associated-types-in-inherent-method.rs
Normal file
41
src/test/run-pass/associated-types-in-inherent-method.rs
Normal file
@ -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);
|
||||
}
|
||||
|
35
src/test/run-pass/associated-types-simple.rs
Normal file
35
src/test/run-pass/associated-types-simple.rs
Normal file
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user