1
Fork 0

Restructure AST so that the associated type definition carries

bounds like any other "type parameter".
This commit is contained in:
Niko Matsakis 2014-10-28 14:48:52 -04:00
parent 01b81c0ebb
commit 319d778ed3
13 changed files with 105 additions and 98 deletions

View file

@ -81,7 +81,7 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
e::IIForeignRef(i) => i.id, e::IIForeignRef(i) => i.id,
e::IITraitItemRef(_, &ast::ProvidedMethod(ref m)) => m.id, e::IITraitItemRef(_, &ast::ProvidedMethod(ref m)) => m.id,
e::IITraitItemRef(_, &ast::RequiredMethod(ref m)) => m.id, e::IITraitItemRef(_, &ast::RequiredMethod(ref m)) => m.id,
e::IITraitItemRef(_, &ast::TypeTraitItem(ref ti)) => ti.id, e::IITraitItemRef(_, &ast::TypeTraitItem(ref ti)) => ti.ty_param.id,
e::IIImplItemRef(_, &ast::MethodImplItem(ref m)) => m.id, e::IIImplItemRef(_, &ast::MethodImplItem(ref m)) => m.id,
e::IIImplItemRef(_, &ast::TypeImplItem(ref ti)) => ti.id, e::IIImplItemRef(_, &ast::TypeImplItem(ref ti)) => ti.id,
}; };
@ -156,7 +156,7 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
match *ti { match *ti {
ast::ProvidedMethod(ref m) => m.pe_ident(), 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::TypeTraitItem(ref ti) => ti.ty_param.ident,
} }
}, },
ast::IIImplItem(_, ref m) => { ast::IIImplItem(_, ref m) => {

View file

@ -296,8 +296,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
self.exported_items.insert(m.id); self.exported_items.insert(m.id);
} }
ast::TypeTraitItem(ref t) => { ast::TypeTraitItem(ref t) => {
debug!("typedef {}", t.id); debug!("typedef {}", t.ty_param.id);
self.exported_items.insert(t.id); self.exported_items.insert(t.ty_param.id);
} }
} }
} }

View file

@ -1559,19 +1559,19 @@ impl<'a> Resolver<'a> {
} }
ast::TypeTraitItem(ref associated_type) => { ast::TypeTraitItem(ref associated_type) => {
let def = DefAssociatedTy(local_def( let def = DefAssociatedTy(local_def(
associated_type.id)); associated_type.ty_param.id));
let name_bindings = let name_bindings =
self.add_child(associated_type.ident.name, self.add_child(associated_type.ty_param.ident.name,
module_parent.clone(), module_parent.clone(),
ForbidDuplicateTypesAndValues, ForbidDuplicateTypesAndValues,
associated_type.span); associated_type.ty_param.span);
// NB: not IMPORTABLE // NB: not IMPORTABLE
name_bindings.define_type(def, name_bindings.define_type(def,
associated_type.span, associated_type.ty_param.span,
PUBLIC); PUBLIC);
(associated_type.ident.name, TypeTraitItemKind) (associated_type.ty_param.ident.name, TypeTraitItemKind)
} }
}; };
@ -4218,7 +4218,7 @@ impl<'a> Resolver<'a> {
impl_items.as_slice()); impl_items.as_slice());
} }
ItemTrait(ref generics, ref unbound, ref bounds, ref methods) => { ItemTrait(ref generics, ref unbound, ref bounds, ref trait_items) => {
// Create a new rib for the self type. // Create a new rib for the self type.
let mut self_type_rib = Rib::new(ItemRibKind); let mut self_type_rib = Rib::new(ItemRibKind);
@ -4246,13 +4246,13 @@ impl<'a> Resolver<'a> {
_ => {} _ => {}
} }
for method in (*methods).iter() { for trait_item in (*trait_items).iter() {
// Create a new rib for the method-specific type // Create a new rib for the trait_item-specific type
// parameters. // parameters.
// //
// FIXME #4951: Do we need a node ID here? // FIXME #4951: Do we need a node ID here?
match *method { match *trait_item {
ast::RequiredMethod(ref ty_m) => { ast::RequiredMethod(ref ty_m) => {
this.with_type_parameter_rib this.with_type_parameter_rib
(HasTypeParameters(&ty_m.generics, (HasTypeParameters(&ty_m.generics,
@ -4287,8 +4287,9 @@ impl<'a> Resolver<'a> {
ProvidedMethod(m.id)), ProvidedMethod(m.id)),
&**m) &**m)
} }
ast::TypeTraitItem(_) => { ast::TypeTraitItem(ref data) => {
visit::walk_trait_item(this, method); this.resolve_type_parameter(&data.ty_param);
visit::walk_trait_item(this, trait_item);
} }
} }
} }
@ -4477,6 +4478,12 @@ impl<'a> Resolver<'a> {
fn resolve_type_parameters(&mut self, fn resolve_type_parameters(&mut self,
type_parameters: &OwnedSlice<TyParam>) { type_parameters: &OwnedSlice<TyParam>) {
for type_parameter in type_parameters.iter() { for type_parameter in type_parameters.iter() {
self.resolve_type_parameter(type_parameter);
}
}
fn resolve_type_parameter(&mut self,
type_parameter: &TyParam) {
for bound in type_parameter.bounds.iter() { for bound in type_parameter.bounds.iter() {
self.resolve_type_parameter_bound(type_parameter.id, bound, self.resolve_type_parameter_bound(type_parameter.id, bound,
TraitBoundingTypeParameter); TraitBoundingTypeParameter);
@ -4492,7 +4499,6 @@ impl<'a> Resolver<'a> {
None => {} None => {}
} }
} }
}
fn resolve_type_parameter_bounds(&mut self, fn resolve_type_parameter_bounds(&mut self,
id: NodeId, id: NodeId,

View file

@ -86,7 +86,7 @@ impl<'v> Visitor<'v> for Annotator {
} }
} }
TypeTraitItem(ref typedef) => (typedef.id, &typedef.attrs), TypeTraitItem(ref typedef) => (typedef.ty_param.id, &typedef.attrs),
}; };
self.annotate(id, attrs, |v| visit::walk_trait_item(v, t)); self.annotate(id, attrs, |v| visit::walk_trait_item(v, t));
} }

View file

@ -298,7 +298,7 @@ fn collect_trait_methods(ccx: &CrateCtxt,
&*m.pe_fn_decl()) &*m.pe_fn_decl())
} }
ast::TypeTraitItem(ref at) => { ast::TypeTraitItem(ref at) => {
tcx.sess.span_bug(at.span, tcx.sess.span_bug(at.ty_param.span,
"there shouldn't \ "there shouldn't \
be a type trait \ be a type trait \
item here") item here")
@ -315,9 +315,9 @@ fn collect_trait_methods(ccx: &CrateCtxt,
ast::TypeTraitItem(ref ast_associated_type) => { ast::TypeTraitItem(ref ast_associated_type) => {
let trait_did = local_def(trait_id); let trait_did = local_def(trait_id);
let associated_type = ty::AssociatedType { let associated_type = ty::AssociatedType {
name: ast_associated_type.ident.name, name: ast_associated_type.ty_param.ident.name,
vis: ast::Public, vis: ast::Public,
def_id: local_def(ast_associated_type.id), def_id: local_def(ast_associated_type.ty_param.id),
container: TraitContainer(trait_did), container: TraitContainer(trait_did),
}; };
@ -345,7 +345,7 @@ fn collect_trait_methods(ccx: &CrateCtxt,
method.id)) method.id))
} }
ast::TypeTraitItem(ref typedef) => { ast::TypeTraitItem(ref typedef) => {
ty::TypeTraitItemId(local_def(typedef.id)) ty::TypeTraitItemId(local_def(typedef.ty_param.id))
} }
} }
}).collect()); }).collect());
@ -463,12 +463,12 @@ fn convert_associated_type(ccx: &CrateCtxt,
.get_slice(subst::TypeSpace) .get_slice(subst::TypeSpace)
.iter() .iter()
.find(|def| { .find(|def| {
def.def_id == local_def(associated_type.id) def.def_id == local_def(associated_type.ty_param.id)
}); });
let type_parameter_def = match type_parameter_def { let type_parameter_def = match type_parameter_def {
Some(type_parameter_def) => type_parameter_def, Some(type_parameter_def) => type_parameter_def,
None => { None => {
ccx.tcx().sess.span_bug(associated_type.span, ccx.tcx().sess.span_bug(associated_type.ty_param.span,
"`convert_associated_type()` didn't find \ "`convert_associated_type()` didn't find \
a type parameter ID corresponding to \ a type parameter ID corresponding to \
this type") this type")
@ -477,18 +477,18 @@ fn convert_associated_type(ccx: &CrateCtxt,
let param_type = ty::mk_param(ccx.tcx, let param_type = ty::mk_param(ccx.tcx,
subst::TypeSpace, subst::TypeSpace,
type_parameter_def.index, type_parameter_def.index,
local_def(associated_type.id)); local_def(associated_type.ty_param.id));
ccx.tcx.tcache.borrow_mut().insert(local_def(associated_type.id), ccx.tcx.tcache.borrow_mut().insert(local_def(associated_type.ty_param.id),
Polytype { Polytype {
generics: ty::Generics::empty(), generics: ty::Generics::empty(),
ty: param_type, ty: param_type,
}); });
write_ty_to_tcx(ccx.tcx, associated_type.id, param_type); write_ty_to_tcx(ccx.tcx, associated_type.ty_param.id, param_type);
let associated_type = Rc::new(ty::AssociatedType { let associated_type = Rc::new(ty::AssociatedType {
name: associated_type.ident.name, name: associated_type.ty_param.ident.name,
vis: ast::Public, vis: ast::Public,
def_id: local_def(associated_type.id), def_id: local_def(associated_type.ty_param.id),
container: TraitContainer(trait_def.trait_ref.def_id), container: TraitContainer(trait_def.trait_ref.def_id),
}); });
ccx.tcx ccx.tcx
@ -978,7 +978,7 @@ impl<'a,'tcx> AstConv<'tcx> for TraitMethodCtxt<'a,'tcx> {
match *item { match *item {
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {} ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
ast::TypeTraitItem(ref item) => { ast::TypeTraitItem(ref item) => {
if local_def(item.id) == associated_type_id { if local_def(item.ty_param.id) == associated_type_id {
return ty::mk_param(self.tcx(), return ty::mk_param(self.tcx(),
subst::TypeSpace, subst::TypeSpace,
index, index,
@ -1480,7 +1480,7 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
types.push(ty::mk_param(ccx.tcx, types.push(ty::mk_param(ccx.tcx,
subst::TypeSpace, subst::TypeSpace,
index, index,
local_def(trait_item.id))) local_def(trait_item.ty_param.id)))
} }
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {} ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
} }
@ -1630,11 +1630,11 @@ fn ty_of_trait_item(ccx: &CrateCtxt, trait_item: &ast::TraitItem)
"ty_of_trait_item() on provided method") "ty_of_trait_item() on provided method")
} }
ast::TypeTraitItem(ref associated_type) => { ast::TypeTraitItem(ref associated_type) => {
let parent = ccx.tcx.map.get_parent(associated_type.id); let parent = ccx.tcx.map.get_parent(associated_type.ty_param.id);
let trait_def = match ccx.tcx.map.get(parent) { let trait_def = match ccx.tcx.map.get(parent) {
ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item), ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
_ => { _ => {
ccx.tcx.sess.span_bug(associated_type.span, ccx.tcx.sess.span_bug(associated_type.ty_param.span,
"associated type's parent wasn't \ "associated type's parent wasn't \
an item?!") an item?!")
} }
@ -1680,8 +1680,8 @@ fn ty_generics_for_trait(ccx: &CrateCtxt,
let def = ty::TypeParameterDef { let def = ty::TypeParameterDef {
space: subst::TypeSpace, space: subst::TypeSpace,
index: generics.types.len(subst::TypeSpace), index: generics.types.len(subst::TypeSpace),
name: associated_type.ident.name, name: associated_type.ty_param.ident.name,
def_id: local_def(associated_type.id), def_id: local_def(associated_type.ty_param.id),
bounds: ty::ParamBounds { bounds: ty::ParamBounds {
builtin_bounds: ty::empty_builtin_bounds(), builtin_bounds: ty::empty_builtin_bounds(),
trait_bounds: Vec::new(), trait_bounds: Vec::new(),
@ -1690,7 +1690,7 @@ fn ty_generics_for_trait(ccx: &CrateCtxt,
associated_with: Some(local_def(trait_id)), associated_with: Some(local_def(trait_id)),
default: None, default: None,
}; };
ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.id, ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.ty_param.id,
def.clone()); def.clone());
generics.types.push(subst::TypeSpace, def); generics.types.push(subst::TypeSpace, def);
} }
@ -1810,9 +1810,9 @@ fn ensure_associated_types<'tcx,AC>(this: &AC, trait_id: ast::DefId)
ast::ProvidedMethod(_) => {} ast::ProvidedMethod(_) => {}
ast::TypeTraitItem(ref associated_type) => { ast::TypeTraitItem(ref associated_type) => {
let info = ty::AssociatedTypeInfo { let info = ty::AssociatedTypeInfo {
def_id: local_def(associated_type.id), def_id: local_def(associated_type.ty_param.id),
index: index, index: index,
name: associated_type.ident.name, name: associated_type.ty_param.ident.name,
}; };
result.push(info); result.push(info);
index += 1; index += 1;

View file

@ -861,10 +861,8 @@ pub enum ImplItem {
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub struct AssociatedType { pub struct AssociatedType {
pub id: NodeId,
pub span: Span,
pub ident: Ident,
pub attrs: Vec<Attribute>, pub attrs: Vec<Attribute>,
pub ty_param: TyParam,
} }
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]

View file

@ -405,7 +405,9 @@ impl<'ast> Map<'ast> {
MethMac(_) => panic!("no path elem for {}", node), MethMac(_) => panic!("no path elem for {}", node),
} }
} }
TypeTraitItem(ref m) => PathName(m.ident.name), TypeTraitItem(ref m) => {
PathName(m.ty_param.ident.name)
}
}, },
NodeVariant(v) => PathName(v.node.name.name), NodeVariant(v) => PathName(v.node.name.name),
_ => panic!("no path elem for {}", node) _ => panic!("no path elem for {}", node)
@ -510,7 +512,7 @@ impl<'ast> Map<'ast> {
match *trait_method { match *trait_method {
RequiredMethod(ref type_method) => type_method.span, RequiredMethod(ref type_method) => type_method.span,
ProvidedMethod(ref method) => method.span, ProvidedMethod(ref method) => method.span,
TypeTraitItem(ref typedef) => typedef.span, TypeTraitItem(ref typedef) => typedef.ty_param.span,
} }
} }
Some(NodeImplItem(ref impl_item)) => { Some(NodeImplItem(ref impl_item)) => {
@ -650,7 +652,7 @@ impl Named for TraitItem {
match *self { match *self {
RequiredMethod(ref tm) => tm.ident.name, RequiredMethod(ref tm) => tm.ident.name,
ProvidedMethod(ref m) => m.name(), ProvidedMethod(ref m) => m.name(),
TypeTraitItem(ref at) => at.ident.name, TypeTraitItem(ref at) => at.ty_param.ident.name,
} }
} }
} }
@ -783,7 +785,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
self.insert(m.id, NodeTraitItem(tm)); self.insert(m.id, NodeTraitItem(tm));
} }
TypeTraitItem(ref typ) => { TypeTraitItem(ref typ) => {
self.insert(typ.id, NodeTraitItem(tm)); self.insert(typ.ty_param.id, NodeTraitItem(tm));
} }
} }
} }
@ -976,7 +978,7 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
let trait_item_id = match *trait_item { let trait_item_id = match *trait_item {
ProvidedMethod(ref m) => m.id, ProvidedMethod(ref m) => m.id,
RequiredMethod(ref m) => m.id, RequiredMethod(ref m) => m.id,
TypeTraitItem(ref ty) => ty.id, TypeTraitItem(ref ty) => ty.ty_param.id,
}; };
collector.insert(trait_item_id, NodeTraitItem(trait_item)); collector.insert(trait_item_id, NodeTraitItem(trait_item));
@ -1080,7 +1082,7 @@ fn node_id_to_string(map: &Map, id: NodeId) -> String {
} }
TypeTraitItem(ref t) => { TypeTraitItem(ref t) => {
format!("type item {} in {} (id={})", format!("type item {} in {} (id={})",
token::get_ident(t.ident), token::get_ident(t.ty_param.ident),
map.path_to_string(id), map.path_to_string(id),
id) id)
} }

View file

@ -525,7 +525,7 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
match *tm { match *tm {
ast::RequiredMethod(ref m) => self.operation.visit_id(m.id), ast::RequiredMethod(ref m) => self.operation.visit_id(m.id),
ast::ProvidedMethod(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), ast::TypeTraitItem(ref typ) => self.operation.visit_id(typ.ty_param.id),
} }
visit::walk_trait_item(self, tm); visit::walk_trait_item(self, tm);
} }

View file

@ -260,7 +260,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {} ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
ast::TypeTraitItem(ref ti) => { ast::TypeTraitItem(ref ti) => {
self.gate_feature("associated_types", self.gate_feature("associated_types",
ti.span, ti.ty_param.span,
"associated types are experimental") "associated types are experimental")
} }
} }

View file

@ -793,19 +793,16 @@ pub fn noop_fold_typedef<T>(t: Typedef, folder: &mut T)
pub fn noop_fold_associated_type<T>(at: AssociatedType, folder: &mut T) pub fn noop_fold_associated_type<T>(at: AssociatedType, folder: &mut T)
-> AssociatedType -> AssociatedType
where T: Folder { 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 let new_attrs = at.attrs
.iter() .iter()
.map(|attr| folder.fold_attribute((*attr).clone())) .map(|attr| folder.fold_attribute((*attr).clone()))
.collect(); .collect();
let new_param = folder.fold_ty_param(at.ty_param);
ast::AssociatedType { ast::AssociatedType {
ident: new_ident,
attrs: new_attrs, attrs: new_attrs,
id: new_id, ty_param: new_param,
span: new_span,
} }
} }

View file

@ -1229,16 +1229,13 @@ impl<'a> Parser<'a> {
/// Parses `type Foo;` in a trait declaration only. The `type` keyword has /// Parses `type Foo;` in a trait declaration only. The `type` keyword has
/// already been parsed. /// already been parsed.
fn parse_associated_type(&mut self, attrs: Vec<Attribute>) fn parse_associated_type(&mut self, attrs: Vec<Attribute>)
-> AssociatedType { -> AssociatedType
let lo = self.span.lo; {
let ident = self.parse_ident(); let ty_param = self.parse_ty_param();
let hi = self.span.hi;
self.expect(&token::Semi); self.expect(&token::Semi);
AssociatedType { AssociatedType {
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, hi),
ident: ident,
attrs: attrs, attrs: attrs,
ty_param: ty_param,
} }
} }

View file

@ -818,9 +818,11 @@ impl<'a> State<'a> {
} }
fn print_associated_type(&mut self, typedef: &ast::AssociatedType) fn print_associated_type(&mut self, typedef: &ast::AssociatedType)
-> IoResult<()> { -> IoResult<()>
{
try!(self.print_outer_attributes(typedef.attrs[]));
try!(self.word_space("type")); try!(self.word_space("type"));
try!(self.print_ident(typedef.ident)); try!(self.print_ty_param(&typedef.ty_param));
word(&mut self.s, ";") word(&mut self.s, ";")
} }
@ -2434,23 +2436,7 @@ impl<'a> State<'a> {
} else { } else {
let idx = idx - generics.lifetimes.len(); let idx = idx - generics.lifetimes.len();
let param = generics.ty_params.get(idx); let param = generics.ty_params.get(idx);
match param.unbound { s.print_ty_param(param)
Some(TraitTyParamBound(ref tref)) => {
try!(s.print_trait_ref(tref));
try!(s.word_space("?"));
}
_ => {}
}
try!(s.print_ident(param.ident));
try!(s.print_bounds(":", &param.bounds));
match param.default {
Some(ref default) => {
try!(space(&mut s.s));
try!(s.word_space("="));
s.print_type(&**default)
}
_ => Ok(())
}
} }
})); }));
@ -2458,6 +2444,26 @@ impl<'a> State<'a> {
Ok(()) Ok(())
} }
pub fn print_ty_param(&mut self, param: &ast::TyParam) -> IoResult<()> {
match param.unbound {
Some(TraitTyParamBound(ref tref)) => {
try!(self.print_trait_ref(tref));
try!(self.word_space("?"));
}
_ => {}
}
try!(self.print_ident(param.ident));
try!(self.print_bounds(":", &param.bounds));
match param.default {
Some(ref default) => {
try!(space(&mut self.s));
try!(self.word_space("="));
self.print_type(&**default)
}
_ => Ok(())
}
}
pub fn print_where_clause(&mut self, generics: &ast::Generics) pub fn print_where_clause(&mut self, generics: &ast::Generics)
-> IoResult<()> { -> IoResult<()> {
if generics.where_clause.predicates.len() == 0 { if generics.where_clause.predicates.len() == 0 {

View file

@ -596,7 +596,8 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_method: &'v Tr
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), ProvidedMethod(ref method) => walk_method_helper(visitor, &**method),
TypeTraitItem(ref associated_type) => { TypeTraitItem(ref associated_type) => {
visitor.visit_ident(associated_type.span, associated_type.ident) visitor.visit_ident(associated_type.ty_param.span,
associated_type.ty_param.ident)
} }
} }
} }