auto merge of #16377 : pcwalton/rust/associated-items, r=nikomatsakis

This is waiting on an RFC, but this basic functionality should be
straightforward. The implementation essentially desugars during type
collection and AST type conversion time into the parameter scheme we
have now.

r? @nikomatsakis
This commit is contained in:
bors 2014-09-17 23:45:36 +00:00
commit 9508faa227
67 changed files with 3031 additions and 550 deletions

View file

@ -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

View file

@ -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()
}
}
}

View file

@ -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> {

View file

@ -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)
}

View file

@ -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',
}
}

View file

@ -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');
}
}

View file

@ -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
}

View file

@ -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));
}

View file

@ -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),

View file

@ -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(_) => {}
}
}
}

View file

@ -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 {
}
}
}

View file

@ -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(_) => {

View file

@ -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,

View file

@ -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 {

View file

@ -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

View file

@ -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;

View file

@ -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(_) => {}
}
}

View file

@ -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));
}

View file

@ -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());
}
}

View file

@ -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()")
}
}
}

View file

@ -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?!")
}
}
}
};

View file

@ -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) => {

View file

@ -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")
}
}
}
};

View file

@ -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()
}

View file

@ -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) => {

View file

@ -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));

View file

@ -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);
}

View file

@ -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),
}

View file

@ -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) => {

View file

@ -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

View file

@ -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(..) => {

View file

@ -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

View file

@ -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

View file

@ -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(_) => {}
}
}
}

View file

@ -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)
}
}

View file

@ -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 {

View file

@ -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 {

View file

@ -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);

View file

@ -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,
}
}

View file

@ -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'>\

View file

@ -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 {

View file

@ -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()

View file

@ -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>),

View file

@ -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 {

View file

@ -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={})",

View file

@ -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);
}

View file

@ -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()),
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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),

View file

@ -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)
}

View file

@ -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),
}
}

View file

@ -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)
}
}
}

View 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);
}

View 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 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() {
}

View 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() {
}

View file

@ -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 {

View file

@ -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 }
}

View file

@ -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() {
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View file

@ -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() {