From 319d778ed306d0b3c35af79c47c702dbdebf6d09 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 28 Oct 2014 14:48:52 -0400 Subject: [PATCH] Restructure AST so that the associated type definition carries bounds like any other "type parameter". --- src/librustc/middle/astencode.rs | 4 +- src/librustc/middle/privacy.rs | 4 +- src/librustc/middle/resolve.rs | 62 +++++++++++++++------------ src/librustc/middle/stability.rs | 2 +- src/librustc/middle/typeck/collect.rs | 40 ++++++++--------- src/libsyntax/ast.rs | 4 +- src/libsyntax/ast_map/mod.rs | 14 +++--- src/libsyntax/ast_util.rs | 2 +- src/libsyntax/feature_gate.rs | 2 +- src/libsyntax/fold.rs | 11 ++--- src/libsyntax/parse/parser.rs | 11 ++--- src/libsyntax/print/pprust.rs | 44 +++++++++++-------- src/libsyntax/visit.rs | 3 +- 13 files changed, 105 insertions(+), 98 deletions(-) diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 3d2bd763a14..be4139e65ba 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -81,7 +81,7 @@ 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::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::TypeImplItem(ref ti)) => ti.id, }; @@ -156,7 +156,7 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata, match *ti { ast::ProvidedMethod(ref m) => m.pe_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) => { diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 2256bd71e65..4fbffa2a819 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -296,8 +296,8 @@ fn visit_item(&mut self, item: &ast::Item) { self.exported_items.insert(m.id); } ast::TypeTraitItem(ref t) => { - debug!("typedef {}", t.id); - self.exported_items.insert(t.id); + debug!("typedef {}", t.ty_param.id); + self.exported_items.insert(t.ty_param.id); } } } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index c297bdc6ca2..d1345efaf90 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1559,19 +1559,19 @@ fn build_reduced_graph_for_item(&mut self, } ast::TypeTraitItem(ref associated_type) => { let def = DefAssociatedTy(local_def( - associated_type.id)); + associated_type.ty_param.id)); let name_bindings = - self.add_child(associated_type.ident.name, + self.add_child(associated_type.ty_param.ident.name, module_parent.clone(), ForbidDuplicateTypesAndValues, - associated_type.span); + associated_type.ty_param.span); // NB: not IMPORTABLE name_bindings.define_type(def, - associated_type.span, + associated_type.ty_param.span, PUBLIC); - (associated_type.ident.name, TypeTraitItemKind) + (associated_type.ty_param.ident.name, TypeTraitItemKind) } }; @@ -4218,7 +4218,7 @@ fn resolve_item(&mut self, item: &Item) { 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. let mut self_type_rib = Rib::new(ItemRibKind); @@ -4246,13 +4246,13 @@ fn resolve_item(&mut self, item: &Item) { _ => {} } - for method in (*methods).iter() { - // Create a new rib for the method-specific type + for trait_item in (*trait_items).iter() { + // Create a new rib for the trait_item-specific type // parameters. // // FIXME #4951: Do we need a node ID here? - match *method { + match *trait_item { ast::RequiredMethod(ref ty_m) => { this.with_type_parameter_rib (HasTypeParameters(&ty_m.generics, @@ -4287,8 +4287,9 @@ fn resolve_item(&mut self, item: &Item) { ProvidedMethod(m.id)), &**m) } - ast::TypeTraitItem(_) => { - visit::walk_trait_item(this, method); + ast::TypeTraitItem(ref data) => { + this.resolve_type_parameter(&data.ty_param); + visit::walk_trait_item(this, trait_item); } } } @@ -4477,20 +4478,25 @@ fn resolve_function(&mut self, fn resolve_type_parameters(&mut self, type_parameters: &OwnedSlice) { for type_parameter in type_parameters.iter() { - for bound in type_parameter.bounds.iter() { - self.resolve_type_parameter_bound(type_parameter.id, bound, - TraitBoundingTypeParameter); - } - match &type_parameter.unbound { - &Some(ref unbound) => - self.resolve_type_parameter_bound( - type_parameter.id, unbound, TraitBoundingTypeParameter), - &None => {} - } - match type_parameter.default { - Some(ref ty) => self.resolve_type(&**ty), - None => {} - } + self.resolve_type_parameter(type_parameter); + } + } + + fn resolve_type_parameter(&mut self, + type_parameter: &TyParam) { + for bound in type_parameter.bounds.iter() { + self.resolve_type_parameter_bound(type_parameter.id, bound, + TraitBoundingTypeParameter); + } + match &type_parameter.unbound { + &Some(ref unbound) => + self.resolve_type_parameter_bound( + type_parameter.id, unbound, TraitBoundingTypeParameter), + &None => {} + } + match type_parameter.default { + Some(ref ty) => self.resolve_type(&**ty), + None => {} } } @@ -4577,14 +4583,14 @@ fn resolve_trait_reference(&mut self, self.resolve_error(trait_reference.path.span, format!("`{}` is not a trait", self.path_names_to_string( - &trait_reference.path))); + &trait_reference.path))); // If it's a typedef, give a note match def { DefTy(..) => { self.session.span_note( - trait_reference.path.span, - format!("`type` aliases cannot \ + trait_reference.path.span, + format!("`type` aliases cannot \ be used for traits") .as_slice()); } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 9cac97dc659..7f6a73c83fa 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -86,7 +86,7 @@ fn visit_trait_item(&mut self, t: &TraitItem) { } } - 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)); } diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 847d8e88bde..a4faff8e3bd 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -298,7 +298,7 @@ fn collect_trait_methods(ccx: &CrateCtxt, &*m.pe_fn_decl()) } ast::TypeTraitItem(ref at) => { - tcx.sess.span_bug(at.span, + tcx.sess.span_bug(at.ty_param.span, "there shouldn't \ be a type trait \ item here") @@ -315,9 +315,9 @@ fn collect_trait_methods(ccx: &CrateCtxt, ast::TypeTraitItem(ref ast_associated_type) => { let trait_did = local_def(trait_id); let associated_type = ty::AssociatedType { - name: ast_associated_type.ident.name, + name: ast_associated_type.ty_param.ident.name, 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), }; @@ -345,7 +345,7 @@ fn collect_trait_methods(ccx: &CrateCtxt, method.id)) } ast::TypeTraitItem(ref typedef) => { - ty::TypeTraitItemId(local_def(typedef.id)) + ty::TypeTraitItemId(local_def(typedef.ty_param.id)) } } }).collect()); @@ -463,12 +463,12 @@ fn convert_associated_type(ccx: &CrateCtxt, .get_slice(subst::TypeSpace) .iter() .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 { Some(type_parameter_def) => type_parameter_def, 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 \ a type parameter ID corresponding to \ this type") @@ -477,18 +477,18 @@ fn convert_associated_type(ccx: &CrateCtxt, let param_type = ty::mk_param(ccx.tcx, subst::TypeSpace, type_parameter_def.index, - local_def(associated_type.id)); - ccx.tcx.tcache.borrow_mut().insert(local_def(associated_type.id), + local_def(associated_type.ty_param.id)); + ccx.tcx.tcache.borrow_mut().insert(local_def(associated_type.ty_param.id), Polytype { generics: ty::Generics::empty(), 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 { - name: associated_type.ident.name, + name: associated_type.ty_param.ident.name, 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), }); ccx.tcx @@ -978,7 +978,7 @@ fn associated_type_binding(&self, match *item { ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {} 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(), subst::TypeSpace, index, @@ -1480,7 +1480,7 @@ fn mk_trait_substs(ccx: &CrateCtxt, types.push(ty::mk_param(ccx.tcx, subst::TypeSpace, index, - local_def(trait_item.id))) + local_def(trait_item.ty_param.id))) } 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") } 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) { 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 \ an item?!") } @@ -1680,8 +1680,8 @@ fn ty_generics_for_trait(ccx: &CrateCtxt, let def = ty::TypeParameterDef { space: subst::TypeSpace, index: generics.types.len(subst::TypeSpace), - name: associated_type.ident.name, - def_id: local_def(associated_type.id), + name: associated_type.ty_param.ident.name, + def_id: local_def(associated_type.ty_param.id), bounds: ty::ParamBounds { builtin_bounds: ty::empty_builtin_bounds(), trait_bounds: Vec::new(), @@ -1690,7 +1690,7 @@ fn ty_generics_for_trait(ccx: &CrateCtxt, associated_with: Some(local_def(trait_id)), 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()); 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::TypeTraitItem(ref associated_type) => { let info = ty::AssociatedTypeInfo { - def_id: local_def(associated_type.id), + def_id: local_def(associated_type.ty_param.id), index: index, - name: associated_type.ident.name, + name: associated_type.ty_param.ident.name, }; result.push(info); index += 1; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a2c859cf9fd..fdacc860bb7 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -861,10 +861,8 @@ pub enum ImplItem { #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct AssociatedType { - pub id: NodeId, - pub span: Span, - pub ident: Ident, pub attrs: Vec, + pub ty_param: TyParam, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index fa36577ebdb..f049b964ff3 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -405,7 +405,9 @@ pub fn get_path_elem(&self, id: NodeId) -> PathElem { 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), _ => panic!("no path elem for {}", node) @@ -510,7 +512,7 @@ pub fn opt_span(&self, id: NodeId) -> Option { match *trait_method { RequiredMethod(ref type_method) => type_method.span, ProvidedMethod(ref method) => method.span, - TypeTraitItem(ref typedef) => typedef.span, + TypeTraitItem(ref typedef) => typedef.ty_param.span, } } Some(NodeImplItem(ref impl_item)) => { @@ -650,7 +652,7 @@ fn name(&self) -> Name { match *self { RequiredMethod(ref tm) => tm.ident.name, ProvidedMethod(ref m) => m.name(), - TypeTraitItem(ref at) => at.ident.name, + TypeTraitItem(ref at) => at.ty_param.ident.name, } } } @@ -783,7 +785,7 @@ fn visit_item(&mut self, i: &'ast Item) { self.insert(m.id, NodeTraitItem(tm)); } 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 { ProvidedMethod(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)); @@ -1080,7 +1082,7 @@ fn node_id_to_string(map: &Map, id: NodeId) -> String { } TypeTraitItem(ref t) => { format!("type item {} in {} (id={})", - token::get_ident(t.ident), + token::get_ident(t.ty_param.ident), map.path_to_string(id), id) } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 8b0e1f32fd4..035b80f5564 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -525,7 +525,7 @@ fn visit_trait_item(&mut self, tm: &ast::TraitItem) { match *tm { ast::RequiredMethod(ref m) => self.operation.visit_id(m.id), ast::ProvidedMethod(ref m) => self.operation.visit_id(m.id), - ast::TypeTraitItem(ref typ) => self.operation.visit_id(typ.id), + ast::TypeTraitItem(ref typ) => self.operation.visit_id(typ.ty_param.id), } visit::walk_trait_item(self, tm); } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index c1877c827a4..3743e08e9a9 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -260,7 +260,7 @@ fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) { ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {} ast::TypeTraitItem(ref ti) => { self.gate_feature("associated_types", - ti.span, + ti.ty_param.span, "associated types are experimental") } } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 9a55f07e98d..6535c8e89fd 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -793,19 +793,16 @@ pub fn noop_fold_typedef(t: Typedef, folder: &mut T) pub fn noop_fold_associated_type(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); + where T: Folder +{ let new_attrs = at.attrs .iter() .map(|attr| folder.fold_attribute((*attr).clone())) .collect(); + let new_param = folder.fold_ty_param(at.ty_param); ast::AssociatedType { - ident: new_ident, attrs: new_attrs, - id: new_id, - span: new_span, + ty_param: new_param, } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index aa3b9668d46..ad445ef331f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1229,16 +1229,13 @@ pub fn parse_ty_fn_decl(&mut self, allow_variadic: bool) /// Parses `type Foo;` in a trait declaration only. The `type` keyword has /// already been parsed. fn parse_associated_type(&mut self, attrs: Vec) - -> AssociatedType { - let lo = self.span.lo; - let ident = self.parse_ident(); - let hi = self.span.hi; + -> AssociatedType + { + let ty_param = self.parse_ty_param(); self.expect(&token::Semi); AssociatedType { - id: ast::DUMMY_NODE_ID, - span: mk_sp(lo, hi), - ident: ident, attrs: attrs, + ty_param: ty_param, } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 386fd8ae5a6..b7f6e65fb93 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -818,9 +818,11 @@ pub fn print_foreign_item(&mut self, } 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.print_ident(typedef.ident)); + try!(self.print_ty_param(&typedef.ty_param)); word(&mut self.s, ";") } @@ -2434,23 +2436,7 @@ pub fn print_generics(&mut self, } else { let idx = idx - generics.lifetimes.len(); let param = generics.ty_params.get(idx); - match param.unbound { - Some(TraitTyParamBound(ref tref)) => { - try!(s.print_trait_ref(tref)); - try!(s.word_space("?")); - } - _ => {} - } - try!(s.print_ident(param.ident)); - try!(s.print_bounds(":", ¶m.bounds)); - match param.default { - Some(ref default) => { - try!(space(&mut s.s)); - try!(s.word_space("=")); - s.print_type(&**default) - } - _ => Ok(()) - } + s.print_ty_param(param) } })); @@ -2458,6 +2444,26 @@ pub fn print_generics(&mut self, 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(":", ¶m.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) -> IoResult<()> { if generics.where_clause.predicates.len() == 0 { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index bec72e88f99..86ee23d71a6 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -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), ProvidedMethod(ref method) => walk_method_helper(visitor, &**method), 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) } } } -- GitLab