diff options
| author | Sean Patrick Santos <SeanPatrickSantos@gmail.com> | 2015-03-14 12:05:00 -0600 |
|---|---|---|
| committer | Sean Patrick Santos <SeanPatrickSantos@gmail.com> | 2015-04-23 21:02:25 -0600 |
| commit | b5499775d6bee080b3f46539d59d238de2c1726f (patch) | |
| tree | b8d5b0e9aae8d8ffcf884c9f98299ef1add06ed0 | |
| parent | 21f278a6877b3a66f665d86402c6ae057827a610 (diff) | |
| download | rust-b5499775d6bee080b3f46539d59d238de2c1726f.tar.gz rust-b5499775d6bee080b3f46539d59d238de2c1726f.zip | |
Structural changes for associated constants
Introduces new variants and types in syntax::ast, middle::ty, and middle::def.
40 files changed, 416 insertions, 243 deletions
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index cbd54256770..8e3f77f949b 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -951,11 +951,8 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>, cdata, did.node, tcx); - match trait_item { - ty::MethodTraitItem(ref method) => { - result.push((*method).clone()) - } - ty::TypeTraitItem(_) => {} + if let ty::MethodTraitItem(ref method) = trait_item { + result.push((*method).clone()) } } true diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 29270bd6c62..5f31e24a063 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -378,14 +378,11 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext, let impl_item = ty::impl_or_trait_item( ecx.tcx, method_did.def_id()); - match impl_item { - ty::MethodTraitItem(ref m) => { - encode_reexported_static_method(rbml_w, - exp, - m.def_id, - m.name); - } - ty::TypeTraitItem(_) => {} + if let ty::MethodTraitItem(ref m) = impl_item { + encode_reexported_static_method(rbml_w, + exp, + m.def_id, + m.name); } } } @@ -1195,6 +1192,7 @@ fn encode_info_for_item(ecx: &EncodeContext, for &item_def_id in items { rbml_w.start_tag(tag_item_impl_item); match item_def_id { + ty::ConstTraitItemId(_) => {} ty::MethodTraitItemId(item_def_id) => { encode_def_id(rbml_w, item_def_id); encode_item_sort(rbml_w, 'r'); @@ -1232,6 +1230,7 @@ fn encode_info_for_item(ecx: &EncodeContext, }); match ty::impl_or_trait_item(tcx, trait_item_def_id.def_id()) { + ty::ConstTraitItem(_) => {} ty::MethodTraitItem(ref method_type) => { encode_info_for_method(ecx, rbml_w, @@ -1276,6 +1275,7 @@ fn encode_info_for_item(ecx: &EncodeContext, for &method_def_id in &*ty::trait_item_def_ids(tcx, def_id) { rbml_w.start_tag(tag_item_trait_item); match method_def_id { + ty::ConstTraitItemId(_) => {} ty::MethodTraitItemId(method_def_id) => { encode_def_id(rbml_w, method_def_id); encode_item_sort(rbml_w, 'r'); @@ -1321,6 +1321,9 @@ fn encode_info_for_item(ecx: &EncodeContext, ty::impl_or_trait_item(tcx, item_def_id.def_id()); let is_nonstatic_method; match trait_item_type { + ty::ConstTraitItem(_) => { + is_nonstatic_method = false; + } ty::MethodTraitItem(method_ty) => { let method_def_id = item_def_id.def_id(); @@ -1365,6 +1368,7 @@ fn encode_info_for_item(ecx: &EncodeContext, let trait_item = &*ms[i]; encode_attributes(rbml_w, &trait_item.attrs); match trait_item.node { + ast::ConstTraitItem(_, _) => {} ast::MethodTraitItem(ref sig, ref body) => { // If this is a static method, we've already // encoded this. diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index ee8373279d9..61b610ab655 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -465,6 +465,9 @@ impl tr for def::Def { def::DefForeignMod(did) => { def::DefForeignMod(did.tr(dcx)) } def::DefStatic(did, m) => { def::DefStatic(did.tr(dcx), m) } def::DefConst(did) => { def::DefConst(did.tr(dcx)) } + def::DefAssociatedConst(did, p) => { + def::DefAssociatedConst(did.tr(dcx), p.map(|did2| did2.tr(dcx))) + } def::DefLocal(nid) => { def::DefLocal(dcx.tr_id(nid)) } def::DefVariant(e_did, v_did, is_s) => { def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s) diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 2befbf99245..fc40febdbf8 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -72,7 +72,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn lookup_and_handle_definition(&mut self, id: &ast::NodeId) { self.tcx.def_map.borrow().get(id).map(|def| { match def.full_def() { - def::DefConst(_) => { + def::DefConst(_) | def::DefAssociatedConst(..) => { self.check_def_id(def.def_id()) } _ if self.ignore_non_const_paths => (), @@ -114,14 +114,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { let trait_item = ty::trait_item(self.tcx, trait_ref.def_id, index); - match trait_item { - ty::MethodTraitItem(method) => { - self.check_def_id(method.def_id); - } - ty::TypeTraitItem(typedef) => { - self.check_def_id(typedef.def_id); - } - } + self.check_def_id(trait_item.def_id()); } } } @@ -365,6 +358,7 @@ impl<'v> Visitor<'v> for LifeSeeder { ast::ItemImpl(_, _, _, ref opt_trait, _, ref impl_items) => { for impl_item in impl_items { match impl_item.node { + ast::ConstImplItem(..) => {} ast::MethodImplItem(..) => { if opt_trait.is_some() || has_allow_dead_code_or_lang_attr(&impl_item.attrs) { @@ -584,6 +578,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> { // Overwrite so that we don't warn the trait method itself. fn visit_trait_item(&mut self, trait_method: &ast::TraitItem) { match trait_method.node { + ast::ConstTraitItem(_, _) => {} ast::MethodTraitItem(_, Some(ref body)) => { visit::walk_block(self, body) } diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index f0b35908854..bce246fa4af 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -28,6 +28,7 @@ pub enum Def { DefForeignMod(ast::DefId), DefStatic(ast::DefId, bool /* is_mutbl */), DefConst(ast::DefId), + DefAssociatedConst(ast::DefId /* const */, MethodProvenance), DefLocal(ast::NodeId), DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */), DefTy(ast::DefId, bool /* is_enum */), @@ -140,7 +141,8 @@ impl Def { DefFn(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) | DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) | DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) | - DefMethod(id, _) | DefConst(id) | DefSelfTy(Some(id), None)=> { + DefMethod(id, _) | DefConst(id) | DefAssociatedConst(id, _) | + DefSelfTy(Some(id), None)=> { id } DefLocal(id) | diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 5235bbdf9cf..87379bd48f0 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -234,7 +234,7 @@ impl OverloadedCallType { ty::MethodTraitItem(ref method_descriptor) => { (*method_descriptor).clone() } - ty::TypeTraitItem(_) => { + _ => { tcx.sess.bug("overloaded call method wasn't in method map") } }; @@ -1183,6 +1183,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { } Some(def::DefConst(..)) | + Some(def::DefAssociatedConst(..)) | Some(def::DefLocal(..)) => { // This is a leaf (i.e. identifier binding // or constant value to match); thus no diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 3dbbcce27b6..22e3376e09e 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -843,8 +843,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { Some(&sig.explicit_self.node), item.span)) } - ast::TypeImplItem(_) => None, - ast::MacImplItem(_) => self.tcx.sess.bug("unexpanded macro") + ast::MacImplItem(_) => self.tcx.sess.bug("unexpanded macro"), + _ => None, } }, ast_map::NodeTraitItem(item) => { @@ -1723,8 +1723,8 @@ fn lifetimes_in_scope(tcx: &ty::ctxt, taken.push_all(&sig.generics.lifetimes); Some(ii.id) } - ast::TypeImplItem(_) => None, - ast::MacImplItem(_) => tcx.sess.bug("unexpanded macro") + ast::MacImplItem(_) => tcx.sess.bug("unexpanded macro"), + _ => None, } } _ => None diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 003306fe558..6db55baf483 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -589,7 +589,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { match def { def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) | - def::DefFn(..) | def::DefMethod(..) => { + def::DefAssociatedConst(..) | def::DefFn(..) | def::DefMethod(..) => { Ok(self.cat_rvalue_node(id, span, expr_ty)) } def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) | @@ -1286,7 +1286,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { try!(self.cat_pattern_(cmt_field, &**subpat, op)); } } - Some(def::DefConst(..)) => { + Some(def::DefConst(..)) | Some(def::DefAssociatedConst(..)) => { for subpat in subpats { try!(self.cat_pattern_(cmt.clone(), &**subpat, op)); } diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index 12b56562c84..7a0f58947fe 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -62,7 +62,7 @@ pub fn pat_is_const(dm: &DefMap, pat: &ast::Pat) -> bool { match pat.node { ast::PatIdent(_, _, None) | ast::PatEnum(..) => { match dm.borrow().get(&pat.id).map(|d| d.full_def()) { - Some(DefConst(..)) => true, + Some(DefConst(..)) | Some(DefAssociatedConst(..)) => true, _ => false } } diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 1bd45b5fc86..b532dc88df4 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -113,7 +113,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> { // If this path leads to a constant, then we need to // recurse into the constant to continue finding // items that are reachable. - def::DefConst(..) => { + def::DefConst(..) | def::DefAssociatedConst(..) => { self.worklist.push(def_id.node); } @@ -183,12 +183,14 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { } Some(ast_map::NodeTraitItem(trait_method)) => { match trait_method.node { + ast::ConstTraitItem(_, ref default) => default.is_some(), ast::MethodTraitItem(_, ref body) => body.is_some(), ast::TypeTraitItem(..) => false, } } Some(ast_map::NodeImplItem(impl_item)) => { match impl_item.node { + ast::ConstImplItem(..) => true, ast::MethodImplItem(ref sig, _) => { if generics_require_inlining(&sig.generics) || attr::requests_inline(&impl_item.attrs) { @@ -303,9 +305,13 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { } ast_map::NodeTraitItem(trait_method) => { match trait_method.node { + ast::ConstTraitItem(_, None) | ast::MethodTraitItem(_, None) => { // Keep going, nothing to get exported } + ast::ConstTraitItem(_, Some(ref expr)) => { + self.visit_expr(&*expr); + } ast::MethodTraitItem(_, Some(ref body)) => { visit::walk_block(self, body); } @@ -314,6 +320,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { } ast_map::NodeImplItem(impl_item) => { match impl_item.node { + ast::ConstImplItem(_, ref expr) => { + self.visit_expr(&*expr); + } ast::MethodImplItem(ref sig, ref body) => { let did = self.tcx.map.get_parent_did(search_item); if method_might_be_inlined(self.tcx, sig, impl_item, did) { diff --git a/src/librustc/middle/traits/object_safety.rs b/src/librustc/middle/traits/object_safety.rs index a2ff86cd065..3d6ed3c3440 100644 --- a/src/librustc/middle/traits/object_safety.rs +++ b/src/librustc/middle/traits/object_safety.rs @@ -100,9 +100,7 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>, .map(|code| ObjectSafetyViolation::Method(m.clone(), code)) .into_iter() } - ty::TypeTraitItem(_) => { - None.into_iter() - } + _ => None.into_iter(), } }) .collect(); diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index 7488b8f046e..9cdae21868e 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -863,7 +863,7 @@ fn confirm_impl_candidate<'cx,'tcx>( for impl_item in impl_items { let assoc_type = match *impl_or_trait_items_map.get(&impl_item.def_id()).unwrap() { ty::TypeTraitItem(ref assoc_type) => assoc_type.clone(), - ty::MethodTraitItem(..) => { continue; } + ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => { continue; } }; if assoc_type.name != obligation.predicate.item_name { diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index ddf941198eb..6ecff3b7faa 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -434,7 +434,7 @@ pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>, for trait_item in &**trait_items { match *trait_item { ty::MethodTraitItem(_) => method_count += 1, - ty::TypeTraitItem(_) => {} + _ => {} } } } @@ -445,14 +445,14 @@ pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>, for trait_item in trait_items.iter().take(method_offset_in_trait) { match *trait_item { ty::MethodTraitItem(_) => method_count += 1, - ty::TypeTraitItem(_) => {} + _ => {} } } // the item at the offset we were given really ought to be a method assert!(match trait_items[method_offset_in_trait] { ty::MethodTraitItem(_) => true, - ty::TypeTraitItem(_) => false + _ => false }); method_count diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 2c94399f921..3f5f40ec0b5 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -131,6 +131,7 @@ impl ImplOrTraitItemContainer { #[derive(Clone, Debug)] pub enum ImplOrTraitItem<'tcx> { + ConstTraitItem(Rc<AssociatedConst<'tcx>>), MethodTraitItem(Rc<Method<'tcx>>), TypeTraitItem(Rc<AssociatedType>), } @@ -138,6 +139,9 @@ pub enum ImplOrTraitItem<'tcx> { impl<'tcx> ImplOrTraitItem<'tcx> { fn id(&self) -> ImplOrTraitItemId { match *self { + ConstTraitItem(ref associated_const) => { + ConstTraitItemId(associated_const.def_id) + } MethodTraitItem(ref method) => MethodTraitItemId(method.def_id), TypeTraitItem(ref associated_type) => { TypeTraitItemId(associated_type.def_id) @@ -147,6 +151,7 @@ impl<'tcx> ImplOrTraitItem<'tcx> { pub fn def_id(&self) -> ast::DefId { match *self { + ConstTraitItem(ref associated_const) => associated_const.def_id, MethodTraitItem(ref method) => method.def_id, TypeTraitItem(ref associated_type) => associated_type.def_id, } @@ -154,13 +159,23 @@ impl<'tcx> ImplOrTraitItem<'tcx> { pub fn name(&self) -> ast::Name { match *self { + ConstTraitItem(ref associated_const) => associated_const.name, MethodTraitItem(ref method) => method.name, TypeTraitItem(ref associated_type) => associated_type.name, } } + pub fn vis(&self) -> ast::Visibility { + match *self { + ConstTraitItem(ref associated_const) => associated_const.vis, + MethodTraitItem(ref method) => method.vis, + TypeTraitItem(ref associated_type) => associated_type.vis, + } + } + pub fn container(&self) -> ImplOrTraitItemContainer { match *self { + ConstTraitItem(ref associated_const) => associated_const.container, MethodTraitItem(ref method) => method.container, TypeTraitItem(ref associated_type) => associated_type.container, } @@ -169,13 +184,14 @@ impl<'tcx> ImplOrTraitItem<'tcx> { pub fn as_opt_method(&self) -> Option<Rc<Method<'tcx>>> { match *self { MethodTraitItem(ref m) => Some((*m).clone()), - TypeTraitItem(_) => None + _ => None, } } } #[derive(Clone, Copy, Debug)] pub enum ImplOrTraitItemId { + ConstTraitItemId(ast::DefId), MethodTraitItemId(ast::DefId), TypeTraitItemId(ast::DefId), } @@ -183,6 +199,7 @@ pub enum ImplOrTraitItemId { impl ImplOrTraitItemId { pub fn def_id(&self) -> ast::DefId { match *self { + ConstTraitItemId(def_id) => def_id, MethodTraitItemId(def_id) => def_id, TypeTraitItemId(def_id) => def_id, } @@ -237,6 +254,16 @@ impl<'tcx> Method<'tcx> { } #[derive(Clone, Copy, Debug)] +pub struct AssociatedConst<'tcx> { + pub name: ast::Name, + pub ty: Ty<'tcx>, + pub vis: ast::Visibility, + pub def_id: ast::DefId, + pub container: ImplOrTraitItemContainer, + pub default: Option<ast::DefId>, +} + +#[derive(Clone, Copy, Debug)] pub struct AssociatedType { pub name: ast::Name, pub vis: ast::Visibility, @@ -2273,6 +2300,16 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { match cx.map.find(id) { Some(ast_map::NodeImplItem(ref impl_item)) => { match impl_item.node { + ast::ConstImplItem(_, _) => { + let def_id = ast_util::local_def(id); + let scheme = lookup_item_type(cx, def_id); + let predicates = lookup_predicates(cx, def_id); + construct_parameter_environment(cx, + impl_item.span, + &scheme.generics, + &predicates, + id) + } ast::MethodImplItem(_, ref body) => { let method_def_id = ast_util::local_def(id); match ty::impl_or_trait_item(cx, method_def_id) { @@ -2286,11 +2323,10 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { method_bounds, body.id) } - TypeTraitItem(_) => { + _ => { cx.sess .bug("ParameterEnvironment::for_item(): \ - can't create a parameter environment \ - for type trait items") + got non-method item from impl method?!") } } } @@ -2304,6 +2340,25 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { } Some(ast_map::NodeTraitItem(trait_item)) => { match trait_item.node { + ast::ConstTraitItem(_, ref default) => { + match *default { + Some(_) => { + let def_id = ast_util::local_def(id); + let scheme = lookup_item_type(cx, def_id); + let predicates = lookup_predicates(cx, def_id); + construct_parameter_environment(cx, + trait_item.span, + &scheme.generics, + &predicates, + id) + } + None => { + cx.sess.bug("ParameterEnvironment::from_item(): \ + can't create a parameter environment \ + for const trait items without defaults") + } + } + } ast::MethodTraitItem(_, None) => { cx.sess.span_bug(trait_item.span, "ParameterEnvironment::for_item(): @@ -2324,11 +2379,11 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { method_bounds, body.id) } - TypeTraitItem(_) => { + _ => { cx.sess .bug("ParameterEnvironment::for_item(): \ - can't create a parameter environment \ - for type trait items") + got non-method item from provided \ + method?!") } } } @@ -4700,7 +4755,8 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { def::DefUpvar(..) | def::DefLocal(..) => LvalueExpr, - def::DefConst(..) => RvalueDatumExpr, + def::DefConst(..) | + def::DefAssociatedConst(..) => RvalueDatumExpr, def => { tcx.sess.span_bug( @@ -5051,10 +5107,10 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) if let ast::MethodTraitItem(_, Some(_)) = ti.node { match impl_or_trait_item(cx, ast_util::local_def(ti.id)) { MethodTraitItem(m) => Some(m), - TypeTraitItem(_) => { + _ => { cx.sess.bug("provided_trait_methods(): \ - associated type found from \ - looking up ProvidedMethod?!") + non-method item found from \ + looking up provided method?!") } } } else { @@ -5155,7 +5211,7 @@ pub fn is_associated_type(cx: &ctxt, id: ast::DefId) -> bool { Some(ref item) => { match **item { TypeTraitItem(_) => true, - MethodTraitItem(_) => false, + _ => false, } } None => false, @@ -6169,7 +6225,7 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt, .insert(method_def_id, source); } } - TypeTraitItem(_) => {} + _ => {} } } @@ -6221,7 +6277,7 @@ pub fn populate_implementations_for_trait_if_necessary( .insert(method_def_id, source); } } - TypeTraitItem(_) => {} + _ => {} } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 12a6d584857..3d56371dd52 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -830,6 +830,7 @@ impl<'tcx> Repr<'tcx> for ty::TraitDef<'tcx> { impl<'tcx> Repr<'tcx> for ast::TraitItem { fn repr(&self, _tcx: &ctxt) -> String { let kind = match self.node { + ast::ConstTraitItem(..) => "ConstTraitItem", ast::MethodTraitItem(..) => "MethodTraitItem", ast::TypeTraitItem(..) => "TypeTraitItem", }; @@ -1054,9 +1055,39 @@ impl<'tcx> Repr<'tcx> for ty::Variance { } } +impl<'tcx> Repr<'tcx> for ty::ImplOrTraitItem<'tcx> { + fn repr(&self, tcx: &ctxt<'tcx>) -> String { + format!("ImplOrTraitItem({})", + match *self { + ty::ImplOrTraitItem::MethodTraitItem(ref i) => i.repr(tcx), + ty::ImplOrTraitItem::ConstTraitItem(ref i) => i.repr(tcx), + ty::ImplOrTraitItem::TypeTraitItem(ref i) => i.repr(tcx), + }) + } +} + +impl<'tcx> Repr<'tcx> for ty::AssociatedConst<'tcx> { + fn repr(&self, tcx: &ctxt<'tcx>) -> String { + format!("AssociatedConst(name: {}, ty: {}, vis: {}, def_id: {})", + self.name.repr(tcx), + self.ty.repr(tcx), + self.vis.repr(tcx), + self.def_id.repr(tcx)) + } +} + +impl<'tcx> Repr<'tcx> for ty::AssociatedType { + fn repr(&self, tcx: &ctxt<'tcx>) -> String { + format!("AssociatedType(name: {}, vis: {}, def_id: {})", + self.name.repr(tcx), + self.vis.repr(tcx), + self.def_id.repr(tcx)) + } +} + impl<'tcx> Repr<'tcx> for ty::Method<'tcx> { fn repr(&self, tcx: &ctxt<'tcx>) -> String { - format!("method(name: {}, generics: {}, predicates: {}, fty: {}, \ + format!("Method(name: {}, generics: {}, predicates: {}, fty: {}, \ explicit_self: {}, vis: {}, def_id: {})", self.name.repr(tcx), self.generics.repr(tcx), diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index c12ac501c45..f4761f95505 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1584,8 +1584,9 @@ impl LintPass for MissingDoc { if self.private_traits.contains(&trait_item.id) { return } let desc = match trait_item.node { + ast::ConstTraitItem(..) => "an associated constant", ast::MethodTraitItem(..) => "a trait method", - ast::TypeTraitItem(..) => "an associated type" + ast::TypeTraitItem(..) => "an associated type", }; self.check_missing_docs_attrs(cx, Some(trait_item.id), @@ -1600,9 +1601,10 @@ impl LintPass for MissingDoc { } let desc = match impl_item.node { + ast::ConstImplItem(..) => "an associated constant", ast::MethodImplItem(..) => "a method", ast::TypeImplItem(_) => "an associated type", - ast::MacImplItem(_) => "an impl item macro" + ast::MacImplItem(_) => "an impl item macro", }; self.check_missing_docs_attrs(cx, Some(impl_item.id), &impl_item.attrs, diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 70c824a67a0..832a33e3fe0 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -272,6 +272,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { if public_ty || public_trait { for impl_item in impl_items { match impl_item.node { + ast::ConstImplItem(_, _) => {} ast::MethodImplItem(ref sig, _) => { let meth_public = match sig.explicit_self.node { ast::SelfStatic => public_ty, @@ -399,6 +400,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { debug!("privacy - is {:?} a public method", did); return match self.tcx.impl_or_trait_items.borrow().get(&did) { + Some(&ty::ConstTraitItem(_)) => ExternallyDenied, Some(&ty::MethodTraitItem(ref meth)) => { debug!("privacy - well at least it's a method: {:?}", *meth); @@ -490,6 +492,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { // where the method was defined? Some(ast_map::NodeImplItem(ii)) => { match ii.node { + ast::ConstImplItem(..) | ast::MethodImplItem(..) => { let imp = self.tcx.map .get_parent_did(closest_private_id); @@ -693,7 +696,11 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { ty::MethodTraitItem(method_type) => { method_type.provided_source.unwrap_or(method_id) } - ty::TypeTraitItem(_) => method_id, + _ => { + self.tcx.sess + .span_bug(span, + "got non-method item in check_static_method") + } }; let string = token::get_name(name); @@ -1128,8 +1135,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { ast::MethodImplItem(..) => { check_inherited(tcx, impl_item.span, impl_item.vis); } - ast::TypeImplItem(_) | - ast::MacImplItem(_) => {} + _ => {} } } } @@ -1307,6 +1313,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { impl_items.iter() .any(|impl_item| { match impl_item.node { + ast::ConstImplItem(..) | ast::MethodImplItem(..) => { self.exported_items.contains(&impl_item.id) } @@ -1330,6 +1337,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { // don't erroneously report errors for private // types in private items. match impl_item.node { + ast::ConstImplItem(..) | ast::MethodImplItem(..) if self.item_is_public(&impl_item.id, impl_item.vis) => { @@ -1360,12 +1368,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { // Those in 3. are warned with this call. for impl_item in impl_items { - match impl_item.node { - ast::TypeImplItem(ref ty) => { - self.visit_ty(ty); - } - ast::MethodImplItem(..) | - ast::MacImplItem(_) => {}, + if let ast::TypeImplItem(ref ty) = impl_item.node { + self.visit_ty(ty); } } } @@ -1376,15 +1380,20 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { let mut found_pub_static = false; for impl_item in impl_items { match impl_item.node { + ast::ConstImplItem(..) => { + if self.item_is_public(&impl_item.id, impl_item.vis) { + found_pub_static = true; + visit::walk_impl_item(self, impl_item); + } + } ast::MethodImplItem(ref sig, _) => { if sig.explicit_self.node == ast::SelfStatic && - self.item_is_public(&impl_item.id, impl_item.vis) { + self.item_is_public(&impl_item.id, impl_item.vis) { found_pub_static = true; visit::walk_impl_item(self, impl_item); } } - ast::TypeImplItem(_) | - ast::MacImplItem(_) => {} + _ => {} } } if found_pub_static { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 777154f3c9c..0d25700d2b7 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -530,6 +530,12 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { trait_item.span); match trait_item.node { + ast::ConstTraitItem(..) => { + let def = DefAssociatedConst(local_def(trait_item.id), + FromTrait(local_def(item.id))); + // NB: not IMPORTABLE + name_bindings.define_value(def, trait_item.span, PUBLIC); + } ast::MethodTraitItem(..) => { let def = DefMethod(local_def(trait_item.id), FromTrait(local_def(item.id))); @@ -703,7 +709,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id) .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers); } - DefFn(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => { + DefFn(..) | DefStatic(..) | DefConst(..) | DefAssociatedConst(..) | + DefMethod(..) => { debug!("(building reduced graph for external \ crate) building value (fn/static) {}", final_ident); // impl methods have already been defined with the correct importability modifier diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d300045c0ec..f43d951aaaa 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -60,7 +60,8 @@ use rustc::middle::ty::{Freevar, FreevarMap, TraitMap, GlobMap}; use rustc::util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap}; use rustc::util::lev_distance::lev_distance; -use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum}; +use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block}; +use syntax::ast::{ConstImplItem, Crate, CrateNum}; use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField}; use syntax::ast::{ExprLoop, ExprWhile, ExprMethodCall}; use syntax::ast::{ExprPath, ExprStruct, FnDecl}; @@ -1831,6 +1832,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // FIXME #4951: Do we need a node ID here? let type_parameters = match trait_item.node { + ast::ConstTraitItem(..) => NoTypeParameters, ast::MethodTraitItem(ref sig, _) => { HasTypeParameters(&sig.generics, FnSpace, @@ -2094,6 +2096,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { this.with_current_self_type(self_type, |this| { for impl_item in impl_items { match impl_item.node { + ConstImplItem(_, _) => {} MethodImplItem(ref sig, _) => { // If this is a trait impl, ensure the method // exists in trait @@ -2466,7 +2469,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // This must be an enum variant, struct or const. if let Some(path_res) = self.resolve_path(pat_id, path, 0, ValueNS, false) { match path_res.base_def { - DefVariant(..) | DefStruct(..) | DefConst(..) => { + DefVariant(..) | DefStruct(..) | DefConst(..) | + DefAssociatedConst(..) => { self.record_def(pattern.id, path_res); } DefStatic(..) => { @@ -2542,7 +2546,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { def @ DefVariant(..) | def @ DefStruct(..) => { return FoundStructOrEnumVariant(def, LastMod(AllPublic)); } - def @ DefConst(..) => { + def @ DefConst(..) | def @ DefAssociatedConst(..) => { return FoundConst(def, LastMod(AllPublic)); } DefStatic(..) => { diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 57dba30723f..237270da562 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -242,6 +242,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { def::DefTrait(_) => Some(recorder::TypeRef), def::DefStatic(_, _) | def::DefConst(_) | + def::DefAssociatedConst(..) | def::DefLocal(_) | def::DefVariant(_, _, _) | def::DefUpvar(..) => Some(recorder::VarRef), @@ -359,14 +360,10 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { // record the decl for this def (if it has one) let decl_id = ty::trait_item_of_item(&self.analysis.ty_cx, ast_util::local_def(id)) - .and_then(|def_id| { - if match def_id { - ty::MethodTraitItemId(def_id) => { - def_id.node != 0 && def_id != ast_util::local_def(id) - } - ty::TypeTraitItemId(_) => false, - } { - Some(def_id.def_id()) + .and_then(|new_id| { + let def_id = new_id.def_id(); + if def_id.node != 0 && def_id != ast_util::local_def(id) { + Some(def_id) } else { None } @@ -800,6 +797,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { def::DefLocal(..) | def::DefStatic(..) | def::DefConst(..) | + def::DefAssociatedConst(..) | def::DefVariant(..) => self.fmt.ref_str(ref_kind.unwrap_or(recorder::VarRef), span, sub_span, @@ -883,6 +881,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { def::DefLocal(_) | def::DefStatic(_,_) | def::DefConst(..) | + def::DefAssociatedConst(..) | def::DefStruct(_) | def::DefVariant(..) | def::DefFn(..) => self.write_sub_paths_truncated(path, false), @@ -966,7 +965,10 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { ty::MethodTraitItem(method) => { method.provided_source.unwrap_or(def_id) } - ty::TypeTraitItem(_) => def_id, + _ => self.sess + .span_bug(ex.span, + "save::process_method_call: non-method \ + DefId in MethodStatic or MethodStaticClosure"), }; (Some(def_id), decl_id) } @@ -1008,7 +1010,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { let def = self.analysis.ty_cx.def_map.borrow().get(&p.id).unwrap().full_def(); let struct_def = match def { - def::DefConst(..) => None, + def::DefConst(..) | def::DefAssociatedConst(..) => None, def::DefVariant(_, variant_id, _) => Some(variant_id), _ => { match ty::ty_to_def_id(ty::node_id_to_type(&self.analysis.ty_cx, p.id)) { @@ -1236,6 +1238,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) { match trait_item.node { + ast::ConstTraitItem(..) => {} ast::MethodTraitItem(ref sig, ref body) => { self.process_method(sig, body.as_ref().map(|x| &**x), trait_item.id, trait_item.ident.name, trait_item.span); @@ -1246,6 +1249,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) { match impl_item.node { + ast::ConstImplItem(..) => {} ast::MethodImplItem(ref sig, ref body) => { self.process_method(sig, Some(body), impl_item.id, impl_item.ident.name, impl_item.span); @@ -1432,8 +1436,9 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { paths_to_process.push((id, p.clone(), Some(ref_kind))) } // FIXME(nrc) what are these doing here? - def::DefStatic(_, _) => {} - def::DefConst(..) => {} + def::DefStatic(_, _) | + def::DefConst(..) | + def::DefAssociatedConst(..) => {} _ => error!("unexpected definition kind when processing collected paths: {:?}", def) } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 59f3ff72602..1ceba3c8230 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -1078,25 +1078,17 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>) Some(ast_map::NodeTraitItem(trait_item)) => { match trait_item.node { ast::MethodTraitItem(_, Some(ref body)) => body, - ast::MethodTraitItem(_, None) => { - tcx.sess.bug("unexpected variant: required trait method \ - in has_nested_returns") - } - ast::TypeTraitItem(..) => { - tcx.sess.bug("unexpected variant: associated type trait item in \ - has_nested_returns") + _ => { + tcx.sess.bug("unexpected variant: trait item other than a \ + provided method in has_nested_returns") } } } Some(ast_map::NodeImplItem(impl_item)) => { match impl_item.node { ast::MethodImplItem(_, ref body) => body, - ast::TypeImplItem(_) => { - tcx.sess.bug("unexpected variant: associated type impl item in \ - has_nested_returns") - } - ast::MacImplItem(_) => { - tcx.sess.bug("unexpected variant: unexpanded macro impl item in \ + _ => { + tcx.sess.bug("unexpected variant: non-method impl item in \ has_nested_returns") } } @@ -2363,13 +2355,14 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { ast_map::NodeTraitItem(trait_item) => { debug!("get_item_val(): processing a NodeTraitItem"); match trait_item.node { - ast::MethodTraitItem(_, None) | ast::TypeTraitItem(..) => { - ccx.sess().span_bug(trait_item.span, - "unexpected variant: required trait method in get_item_val()"); - } ast::MethodTraitItem(_, Some(_)) => { register_method(ccx, id, &trait_item.attrs, trait_item.span) } + _ => { + ccx.sess().span_bug(trait_item.span, + "unexpected variant: trait item other than a provided \ + method in get_item_val()"); + } } } @@ -2378,13 +2371,10 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { ast::MethodImplItem(..) => { register_method(ccx, id, &impl_item.attrs, impl_item.span) } - ast::TypeImplItem(_) => { - ccx.sess().span_bug(impl_item.span, - "unexpected variant: associated type in get_item_val()") - } - ast::MacImplItem(_) => { + _ => { ccx.sess().span_bug(impl_item.span, - "unexpected variant: unexpanded macro in get_item_val()") + "unexpected variant: non-method impl item in \ + get_item_val()"); } } } diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 0e8c33cd93a..0e468072307 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -202,6 +202,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) } def::DefStatic(..) | def::DefConst(..) | + def::DefAssociatedConst(..) | def::DefLocal(..) | def::DefUpvar(..) => { datum_callee(bcx, ref_expr) @@ -465,9 +466,9 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( (true, source_id, new_substs) } - ty::TypeTraitItem(_) => { + _ => { tcx.sess.bug("trans_fn_ref_with_vtables() tried \ - to translate an associated type?!") + to translate a non-method?!") } } } diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 7c769eca74a..69cd57d1bab 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -1314,15 +1314,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, impl_item.span, true) } - ast::TypeImplItem(_) => { - cx.sess().span_bug(impl_item.span, - "create_function_debug_context() \ - called on associated type?!") - } - ast::MacImplItem(_) => { + _ => { cx.sess().span_bug(impl_item.span, "create_function_debug_context() \ - called on unexpanded macro?!") + called on non-method impl item?!") } } } diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index e346fb0d931..fda931fde6e 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -74,8 +74,7 @@ pub fn trans_impl(ccx: &CrateContext, ast::MethodImplItem(..) => { visit::walk_impl_item(&mut v, impl_item); } - ast::TypeImplItem(_) | - ast::MacImplItem(_) => {} + _ => {} } } return; @@ -98,8 +97,7 @@ pub fn trans_impl(ccx: &CrateContext, } visit::walk_impl_item(&mut v, impl_item); } - ast::TypeImplItem(_) | - ast::MacImplItem(_) => {} + _ => {} } } } @@ -336,9 +334,9 @@ 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.name, - ty::TypeTraitItem(_) => { - bcx.tcx().sess.bug("can't monomorphize an associated \ - type") + _ => { + bcx.tcx().sess.bug("can't monomorphize a non-method trait \ + item") } }; let mth_id = method_with_name(bcx.ccx(), impl_did, mname); @@ -579,8 +577,8 @@ pub fn trans_object_shim<'a, 'tcx>( // Lookup the type of this method as declared in the trait and apply substitutions. let method_ty = match ty::trait_item(tcx, trait_id, method_offset_in_trait) { ty::MethodTraitItem(method) => method, - ty::TypeTraitItem(_) => { - tcx.sess.bug("can't create a method shim for an associated type") + _ => { + tcx.sess.bug("can't create a method shim for a non-method item") } }; let fty = monomorphize::apply_param_substs(tcx, &object_substs, &method_ty.fty); @@ -789,11 +787,11 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, trait_item_def_ids .iter() - // Filter out the associated types. + // Filter out non-method items. .filter_map(|item_def_id| { match *item_def_id { ty::MethodTraitItemId(def_id) => Some(def_id), - ty::TypeTraitItemId(_) => None, + _ => None, } }) @@ -806,7 +804,7 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let trait_method_type = match ty::impl_or_trait_item(tcx, trait_method_def_id) { ty::MethodTraitItem(m) => m, - ty::TypeTraitItem(_) => ccx.sess().bug("should be a method, not assoc type") + _ => ccx.sess().bug("should be a method, not other assoc item"), }; let name = trait_method_type.name; @@ -824,7 +822,7 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let impl_method_def_id = method_with_name(ccx, impl_id, name); let impl_method_type = match ty::impl_or_trait_item(tcx, impl_method_def_id) { ty::MethodTraitItem(m) => m, - ty::TypeTraitItem(_) => ccx.sess().bug("should be a method, not assoc type") + _ => ccx.sess().bug("should be a method, not other assoc item"), }; debug!("emit_vtable_methods: impl_method_type={}", diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index 1c8d020494f..03fdd0c45c1 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -236,11 +236,9 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } d } - ast::TypeImplItem(_) => { - ccx.sess().bug("can't monomorphize an associated type") - } - ast::MacImplItem(_) => { - ccx.sess().bug("can't monomorphize an unexpanded macro") + _ => { + ccx.sess().bug(&format!("can't monomorphize a {:?}", + map_node)) } } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 348846b8ad4..47388e0e558 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -808,6 +808,7 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { for impl_item in impl_items { match impl_item.node { + ast::ConstImplItem(_, _) => {} ast::MethodImplItem(ref sig, ref body) => { check_method_body(ccx, &impl_pty.generics, sig, body, impl_item.id, impl_item.span); @@ -823,6 +824,7 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id)); for trait_item in trait_items { match trait_item.node { + ast::ConstTraitItem(_, _) => {} ast::MethodTraitItem(_, None) => { // Nothing to do, since required methods don't have // bodies to check. @@ -920,6 +922,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // and compatible with trait signature for impl_item in impl_items { match impl_item.node { + ast::ConstImplItem(_, _) => {} ast::MethodImplItem(_, ref body) => { let impl_method_def_id = local_def(impl_item.id); let impl_item_ty = ty::impl_or_trait_item(ccx.tcx, @@ -979,13 +982,15 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, 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( - impl_item.span, - &format!("item `{}` is of a different kind from its trait `{}`", - token::get_name(typedef_ty.name()), - impl_trait_ref.repr(tcx))); + // Formerly `span_bug`, but it turns out that + // this is not checked in resolve, so this is + // the first place where we'll notice the + // mismatch. + span_err!(tcx.sess, impl_item.span, E0323, + "item `{}` is an associated type, \ + which doesn't match its trait `{}`", + token::get_name(typedef_ty.name()), + impl_trait_ref.repr(tcx)) } } } @@ -1012,6 +1017,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let mut missing_methods = Vec::new(); for trait_item in &*trait_items { match *trait_item { + ty::ConstTraitItem(_) => {} ty::MethodTraitItem(ref trait_method) => { let is_implemented = impl_items.iter().any(|ii| { @@ -1019,8 +1025,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ast::MethodImplItem(..) => { ii.ident.name == trait_method.name } - ast::TypeImplItem(_) | - ast::MacImplItem(_) => false, + _ => false, } }); let is_provided = @@ -1035,8 +1040,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ast::TypeImplItem(_) => { ii.ident.name == associated_type.name } - ast::MethodImplItem(..) | - ast::MacImplItem(_) => false, + _ => false, } }); if !is_implemented { @@ -4208,7 +4212,7 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } def::DefFn(id, _) | def::DefMethod(id, _) | def::DefStatic(id, _) | def::DefVariant(_, id, _) | - def::DefStruct(id) | def::DefConst(id) => { + def::DefStruct(id) | def::DefConst(id) | def::DefAssociatedConst(id, _) => { (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id)) } def::DefTrait(_) | @@ -4351,6 +4355,10 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } + def::DefAssociatedConst(..) => { + segment_spaces = repeat(None).take(segments.len()).collect(); + } + // Other cases. Various nonsense that really shouldn't show up // here. If they do, an error will have been reported // elsewhere. (I hope) diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index b0c994f7f64..fbfe73674e1 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -20,8 +20,9 @@ use metadata::csearch::{each_impl, get_impl_trait}; use metadata::csearch; use middle::subst::{self, Subst}; use middle::ty::RegionEscape; -use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId}; -use middle::ty::{ParameterEnvironment, TypeTraitItemId, lookup_item_type}; +use middle::ty::{ImplContainer, ImplOrTraitItemId, ConstTraitItemId}; +use middle::ty::{MethodTraitItemId, TypeTraitItemId}; +use middle::ty::{ParameterEnvironment, lookup_item_type}; use middle::ty::{Ty, ty_bool, ty_char, ty_enum, ty_err}; use middle::ty::{ty_param, TypeScheme, ty_ptr}; use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup}; @@ -278,6 +279,9 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { let mut items: Vec<ImplOrTraitItemId> = impl_items.iter().map(|impl_item| { match impl_item.node { + ast::ConstImplItem(..) => { + ConstTraitItemId(local_def(impl_item.id)) + } ast::MethodImplItem(..) => { MethodTraitItemId(local_def(impl_item.id)) } @@ -348,7 +352,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { .insert(item_def_id.def_id(), source); } } - ty::TypeTraitItem(_) => {} + _ => {} } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 5ed93703d97..d04e447a460 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -196,7 +196,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { let def_id = local_def(method_id); match *self.tcx.impl_or_trait_items.borrow().get(&def_id).unwrap() { ty::MethodTraitItem(ref mty) => mty.clone(), - ty::TypeTraitItem(..) => { + _ => { self.tcx.sess.bug(&format!("method with id {} has the wrong type", method_id)); } } @@ -830,43 +830,37 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) { // Convert all the associated types. for impl_item in impl_items { - match impl_item.node { - ast::TypeImplItem(ref ty) => { - if opt_trait_ref.is_none() { - span_err!(tcx.sess, impl_item.span, E0202, - "associated items are not allowed in inherent impls"); - } - - as_refsociated_type(ccx, ImplContainer(local_def(it.id)), - impl_item.ident, impl_item.id, impl_item.vis); - - let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty); - tcx.tcache.borrow_mut().insert(local_def(impl_item.id), - TypeScheme { - generics: ty::Generics::empty(), - ty: typ, - }); - tcx.predicates.borrow_mut().insert(local_def(impl_item.id), - ty::GenericPredicates::empty()); - write_ty_to_tcx(tcx, impl_item.id, typ); + if let ast::TypeImplItem(ref ty) = impl_item.node { + if opt_trait_ref.is_none() { + span_err!(tcx.sess, impl_item.span, E0202, + "associated items are not allowed in inherent impls"); } - ast::MethodImplItem(..) | - ast::MacImplItem(_) => {} + + as_refsociated_type(ccx, ImplContainer(local_def(it.id)), + impl_item.ident, impl_item.id, impl_item.vis); + + let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty); + tcx.tcache.borrow_mut().insert(local_def(impl_item.id), + TypeScheme { + generics: ty::Generics::empty(), + ty: typ, + }); + tcx.predicates.borrow_mut().insert(local_def(impl_item.id), + ty::GenericPredicates::empty()); + write_ty_to_tcx(tcx, impl_item.id, typ); } } let methods = impl_items.iter().filter_map(|ii| { - match ii.node { - ast::MethodImplItem(ref sig, _) => { - // if the method specifies a visibility, use that, otherwise - // inherit the visibility from the impl (so `foo` in `pub impl - // { fn foo(); }` is public, but private in `priv impl { fn - // foo(); }`). - let method_vis = ii.vis.inherit_from(parent_visibility); - Some((sig, ii.id, ii.ident, method_vis, ii.span)) - } - ast::TypeImplItem(_) | - ast::MacImplItem(_) => None + if let ast::MethodImplItem(ref sig, _) = ii.node { + // if the method specifies a visibility, use that, otherwise + // inherit the visibility from the impl (so `foo` in `pub impl + // { fn foo(); }` is public, but private in `priv impl { fn + // foo(); }`). + let method_vis = ii.vis.inherit_from(parent_visibility); + Some((sig, ii.id, ii.ident, method_vis, ii.span)) + } else { + None } }); convert_methods(ccx, @@ -877,18 +871,14 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) { &ty_predicates); for impl_item in impl_items { - match impl_item.node { - ast::MethodImplItem(ref sig, ref body) => { - let body_id = body.id; - check_method_self_type(ccx, - &BindingRscope::new(), - ccx.method_ty(impl_item.id), - selfty, - &sig.explicit_self, - body_id); - } - ast::TypeImplItem(_) | - ast::MacImplItem(_) => {} + if let ast::MethodImplItem(ref sig, ref body) = impl_item.node { + let body_id = body.id; + check_method_self_type(ccx, + &BindingRscope::new(), + ccx.method_ty(impl_item.id), + selfty, + &sig.explicit_self, + body_id); } } @@ -919,18 +909,18 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) { // Convert all the associated types. for trait_item in trait_items { match trait_item.node { - ast::MethodTraitItem(..) => {} ast::TypeTraitItem(..) => { as_refsociated_type(ccx, TraitContainer(local_def(it.id)), trait_item.ident, trait_item.id, ast::Public); } + _ => {} } }; let methods = trait_items.iter().filter_map(|ti| { let sig = match ti.node { ast::MethodTraitItem(ref sig, _) => sig, - ast::TypeTraitItem(..) => return None, + _ => return None, }; Some((sig, ti.id, ti.ident, ast::Inherited, ti.span)) }); @@ -947,6 +937,9 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) { let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| { let def_id = local_def(trait_item.id); match trait_item.node { + ast::ConstTraitItem(..) => { + ty::ConstTraitItemId(def_id) + } ast::MethodTraitItem(..) => { ty::MethodTraitItemId(def_id) } @@ -962,7 +955,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) { for trait_item in trait_items { let sig = match trait_item.node { ast::MethodTraitItem(ref sig, _) => sig, - ast::TypeTraitItem(..) => continue + _ => continue }; check_method_self_type(ccx, &BindingRscope::new(), @@ -1185,8 +1178,8 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| { match trait_item.node { - ast::MethodTraitItem(..) => None, ast::TypeTraitItem(..) => Some(trait_item.ident.name), + _ => None, } }).collect(); @@ -1260,7 +1253,7 @@ fn trait_defines_associated_type_named(ccx: &CrateCtxt, trait_items.iter().any(|trait_item| { match trait_item.node { ast::TypeTraitItem(..) => trait_item.ident.name == assoc_name, - ast::MethodTraitItem(..) => false, + _ => false, } }) } @@ -1320,7 +1313,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) trait_items.iter().flat_map(|trait_item| { let bounds = match trait_item.node { ast::TypeTraitItem(ref bounds, _) => bounds, - ast::MethodTraitItem(..) => { + _ => { return vec!().into_iter(); } }; @@ -2227,7 +2220,8 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, impl_items.iter() .filter_map(|item| match item.node { ast::TypeImplItem(..) => Some(ty::node_id_to_type(tcx, item.id)), - ast::MethodImplItem(..) | ast::MacImplItem(..) => None, + ast::ConstImplItem(..) | ast::MethodImplItem(..) | + ast::MacImplItem(..) => None, }) .flat_map(|ty| ctp::parameters_for_type(ty).into_iter()) .filter_map(|p| match p { diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index b17702cfb8c..b17a7f4f318 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -176,6 +176,7 @@ register_diagnostics! { E0320, // recursive overflow during dropck E0321, // extended coherence rules for defaulted traits violated E0322, // cannot implement Sized explicitly + E0323, // implemented trait where method should have been provided E0366, // dropck forbid specialization to concrete type or region E0367, // dropck forbid specialization to predicate not in struct/enum E0368, // binary operation `<op>=` cannot be applied to types diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 4fc86cf181b..0bc3da416cb 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -312,6 +312,7 @@ pub fn build_impl(cx: &DocContext, let did = did.def_id(); let impl_item = ty::impl_or_trait_item(tcx, did); match impl_item { + ty::ConstTraitItem(_) => { return None } ty::MethodTraitItem(method) => { if method.vis != ast::Public && associated_trait.is_none() { return None diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 23c9edde77c..73fbfe29224 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -361,6 +361,7 @@ pub enum ItemEnum { ForeignStaticItem(Static), MacroItem(Macro), PrimitiveItem(PrimitiveType), + AssociatedConstItem(Type, Option<String>), AssociatedTypeItem(Vec<TyParamBound>, Option<Type>), DefaultImplItem(DefaultImpl), } @@ -1235,6 +1236,11 @@ impl Clean<PolyTrait> for ast::PolyTraitRef { impl Clean<Item> for ast::TraitItem { fn clean(&self, cx: &DocContext) -> Item { let inner = match self.node { + ast::ConstTraitItem(ref ty, ref default) => { + AssociatedConstItem(ty.clean(cx), + default.as_ref().map(|expr| + expr.span.to_src(cx))) + } ast::MethodTraitItem(ref sig, Some(_)) => { MethodItem(sig.clean(cx)) } @@ -1260,6 +1266,12 @@ impl Clean<Item> for ast::TraitItem { impl Clean<Item> for ast::ImplItem { fn clean(&self, cx: &DocContext) -> Item { let inner = match self.node { + ast::ConstImplItem(ref ty, ref expr) => { + ConstantItem(Constant{ + type_: ty.clean(cx), + expr: expr.span.to_src(cx), + }) + } ast::MethodImplItem(ref sig, _) => { MethodItem(sig.clean(cx)) } @@ -1363,6 +1375,7 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> { impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> { fn clean(&self, cx: &DocContext) -> Item { match *self { + ty::ConstTraitItem(ref cti) => cti.clean(cx), ty::MethodTraitItem(ref mti) => mti.clean(cx), ty::TypeTraitItem(ref tti) => tti.clean(cx), } @@ -2672,6 +2685,20 @@ impl Clean<Stability> for attr::Stability { } } +impl<'tcx> Clean<Item> for ty::AssociatedConst<'tcx> { + fn clean(&self, cx: &DocContext) -> Item { + Item { + source: DUMMY_SP.clean(cx), + name: Some(self.name.clean(cx)), + attrs: Vec::new(), + inner: AssociatedConstItem(self.ty.clean(cx), None), + visibility: None, + def_id: self.def_id, + stability: None, + } + } +} + impl Clean<Item> for ty::AssociatedType { fn clean(&self, cx: &DocContext) -> Item { // When loading a cross-crate associated type, the bounds for this type diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index d2385702a73..afc93f41172 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -39,6 +39,7 @@ pub enum ItemType { Primitive = 15, AssociatedType = 16, Constant = 17, + AssociatedConst = 18, } impl ItemType { @@ -63,6 +64,7 @@ impl ItemType { clean::ForeignStaticItem(..) => ItemType::Static, // no ForeignStatic clean::MacroItem(..) => ItemType::Macro, clean::PrimitiveItem(..) => ItemType::Primitive, + clean::AssociatedConstItem(..) => ItemType::AssociatedConst, clean::AssociatedTypeItem(..) => ItemType::AssociatedType, clean::DefaultImplItem(..) => ItemType::Impl, } @@ -102,6 +104,7 @@ impl ItemType { ItemType::Primitive => "primitive", ItemType::AssociatedType => "associatedtype", ItemType::Constant => "constant", + ItemType::AssociatedConst => "associatedconstant", } } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 1993f03efd1..447cf7eab45 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1629,6 +1629,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, ItemType::Macro => ("macros", "Macros"), ItemType::Primitive => ("primitives", "Primitive Types"), ItemType::AssociatedType => ("associated-types", "Associated Types"), + ItemType::AssociatedConst => ("associated-consts", "Associated Constants"), }; try!(write!(w, "<h2 id='{id}' class='section-header'>\ @@ -1799,7 +1800,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, try!(write!(w, "{{\n")); for t in &types { try!(write!(w, " ")); - try!(render_method(w, t, MethodLink::Anchor)); + try!(render_assoc_item(w, t, AssocItemLink::Anchor)); try!(write!(w, ";\n")); } if !types.is_empty() && !required.is_empty() { @@ -1807,7 +1808,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, } for m in &required { try!(write!(w, " ")); - try!(render_method(w, m, MethodLink::Anchor)); + try!(render_assoc_item(w, m, AssocItemLink::Anchor)); try!(write!(w, ";\n")); } if !required.is_empty() && !provided.is_empty() { @@ -1815,7 +1816,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, } for m in &provided { try!(write!(w, " ")); - try!(render_method(w, m, MethodLink::Anchor)); + try!(render_assoc_item(w, m, AssocItemLink::Anchor)); try!(write!(w, " {{ ... }}\n")); } try!(write!(w, "}}")); @@ -1831,7 +1832,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, ty = shortty(m), name = *m.name.as_ref().unwrap(), stab = m.stability_class())); - try!(render_method(w, m, MethodLink::Anchor)); + try!(render_assoc_item(w, m, AssocItemLink::Anchor)); try!(write!(w, "</code></h3>")); try!(document(w, m)); Ok(()) @@ -1871,7 +1872,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, } // If there are methods directly on this trait object, render them here. - try!(render_methods(w, it.def_id, MethodRender::All)); + try!(render_assoc_items(w, it.def_id, AssocItemRender::All)); let cache = cache(); try!(write!(w, " @@ -1917,19 +1918,19 @@ fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item, Ok(()) } -fn render_method(w: &mut fmt::Formatter, meth: &clean::Item, - link: MethodLink) -> fmt::Result { +fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item, + link: AssocItemLink) -> fmt::Result { fn method(w: &mut fmt::Formatter, it: &clean::Item, unsafety: ast::Unsafety, abi: abi::Abi, g: &clean::Generics, selfty: &clean::SelfTy, - d: &clean::FnDecl, link: MethodLink) -> fmt::Result { + d: &clean::FnDecl, link: AssocItemLink) -> fmt::Result { use syntax::abi::Abi; let name = it.name.as_ref().unwrap(); let anchor = format!("#{}.{}", shortty(it), name); let href = match link { - MethodLink::Anchor => anchor, - MethodLink::GotoSource(did) => { + AssocItemLink::Anchor => anchor, + AssocItemLink::GotoSource(did) => { href(did).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor) } }; @@ -1958,10 +1959,11 @@ fn render_method(w: &mut fmt::Formatter, meth: &clean::Item, method(w, meth, m.unsafety, m.abi, &m.generics, &m.self_, &m.decl, link) } + clean::AssociatedConstItem(_, _) => Ok(()), clean::AssociatedTypeItem(ref bounds, ref default) => { assoc_type(w, meth, bounds, default) } - _ => panic!("render_method called on non-method") + _ => panic!("render_assoc_item called on non-associated-item") } } @@ -2001,7 +2003,7 @@ fn item_struct(w: &mut fmt::Formatter, it: &clean::Item, try!(write!(w, "</table>")); } } - render_methods(w, it.def_id, MethodRender::All) + render_assoc_items(w, it.def_id, AssocItemRender::All) } fn item_enum(w: &mut fmt::Formatter, it: &clean::Item, @@ -2100,7 +2102,7 @@ fn item_enum(w: &mut fmt::Formatter, it: &clean::Item, try!(write!(w, "</table>")); } - try!(render_methods(w, it.def_id, MethodRender::All)); + try!(render_assoc_items(w, it.def_id, AssocItemRender::All)); Ok(()) } @@ -2184,19 +2186,19 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item, } #[derive(Copy, Clone)] -enum MethodLink { +enum AssocItemLink { Anchor, GotoSource(ast::DefId), } -enum MethodRender<'a> { +enum AssocItemRender<'a> { All, DerefFor { trait_: &'a clean::Type, type_: &'a clean::Type }, } -fn render_methods(w: &mut fmt::Formatter, - it: ast::DefId, - what: MethodRender) -> fmt::Result { +fn render_assoc_items(w: &mut fmt::Formatter, + it: ast::DefId, + what: AssocItemRender) -> fmt::Result { let c = cache(); let v = match c.impls.get(&it) { Some(v) => v, @@ -2207,21 +2209,21 @@ fn render_methods(w: &mut fmt::Formatter, }); if !non_trait.is_empty() { let render_header = match what { - MethodRender::All => { + AssocItemRender::All => { try!(write!(w, "<h2 id='methods'>Methods</h2>")); true } - MethodRender::DerefFor { trait_, type_ } => { + AssocItemRender::DerefFor { trait_, type_ } => { try!(write!(w, "<h2 id='deref-methods'>Methods from \ {}<Target={}></h2>", trait_, type_)); false } }; for i in &non_trait { - try!(render_impl(w, i, MethodLink::Anchor, render_header)); + try!(render_impl(w, i, AssocItemLink::Anchor, render_header)); } } - if let MethodRender::DerefFor { .. } = what { + if let AssocItemRender::DerefFor { .. } = what { return Ok(()) } if !traits.is_empty() { @@ -2243,7 +2245,7 @@ fn render_methods(w: &mut fmt::Formatter, }); for i in &manual { let did = i.trait_did().unwrap(); - try!(render_impl(w, i, MethodLink::GotoSource(did), true)); + try!(render_impl(w, i, AssocItemLink::GotoSource(did), true)); } if !derived.is_empty() { try!(write!(w, "<h3 id='derived_implementations'>\ @@ -2251,7 +2253,7 @@ fn render_methods(w: &mut fmt::Formatter, </h3>")); for i in &derived { let did = i.trait_did().unwrap(); - try!(render_impl(w, i, MethodLink::GotoSource(did), true)); + try!(render_impl(w, i, AssocItemLink::GotoSource(did), true)); } } } @@ -2266,14 +2268,14 @@ fn render_deref_methods(w: &mut fmt::Formatter, impl_: &Impl) -> fmt::Result { _ => None, } }).next().unwrap(); - let what = MethodRender::DerefFor { trait_: deref_type, type_: target }; + let what = AssocItemRender::DerefFor { trait_: deref_type, type_: target }; match *target { - clean::ResolvedPath { did, .. } => render_methods(w, did, what), + clean::ResolvedPath { did, .. } => render_assoc_items(w, did, what), _ => { if let Some(prim) = target.primitive_type() { if let Some(c) = cache().primitive_locations.get(&prim) { let did = ast::DefId { krate: *c, node: prim.to_node_id() }; - try!(render_methods(w, did, what)); + try!(render_assoc_items(w, did, what)); } } Ok(()) @@ -2281,7 +2283,7 @@ fn render_deref_methods(w: &mut fmt::Formatter, impl_: &Impl) -> fmt::Result { } } -fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink, +fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink, render_header: bool) -> fmt::Result { if render_header { try!(write!(w, "<h3 class='impl'><code>impl{} ", @@ -2300,13 +2302,13 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink, } fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item, - link: MethodLink) -> fmt::Result { + link: AssocItemLink) -> fmt::Result { match item.inner { clean::MethodItem(..) | clean::TyMethodItem(..) => { try!(write!(w, "<h4 id='method.{}' class='{}'><code>", *item.name.as_ref().unwrap(), shortty(item))); - try!(render_method(w, item, link)); + try!(render_assoc_item(w, item, link)); try!(write!(w, "</code></h4>\n")); } clean::TypedefItem(ref tydef) => { @@ -2317,6 +2319,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink, try!(write!(w, "type {} = {}", name, tydef.type_)); try!(write!(w, "</code></h4>\n")); } + clean::AssociatedConstItem(_, _) => {} clean::AssociatedTypeItem(ref bounds, ref default) => { let name = item.name.as_ref().unwrap(); try!(write!(w, "<h4 id='assoc_type.{}' class='{}'><code>", @@ -2327,7 +2330,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink, } _ => panic!("can't make docs for trait item with name {:?}", item.name) } - if let MethodLink::Anchor = link { + if let AssocItemLink::Anchor = link { document(w, item) } else { Ok(()) @@ -2339,10 +2342,10 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink, try!(doctraititem(w, trait_item, link)); } - fn render_default_methods(w: &mut fmt::Formatter, - did: ast::DefId, - t: &clean::Trait, - i: &clean::Impl) -> fmt::Result { + fn render_default_items(w: &mut fmt::Formatter, + did: ast::DefId, + t: &clean::Trait, + i: &clean::Impl) -> fmt::Result { for trait_item in &t.items { let n = trait_item.name.clone(); match i.items.iter().find(|m| { m.name == n }) { @@ -2350,7 +2353,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink, None => {} } - try!(doctraititem(w, trait_item, MethodLink::GotoSource(did))); + try!(doctraititem(w, trait_item, AssocItemLink::GotoSource(did))); } Ok(()) } @@ -2361,7 +2364,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink, // for them work. if let Some(clean::ResolvedPath { did, .. }) = i.impl_.trait_ { if let Some(t) = cache().traits.get(&did) { - try!(render_default_methods(w, did, t, &i.impl_)); + try!(render_default_items(w, did, t, &i.impl_)); } } try!(write!(w, "</div>")); @@ -2458,7 +2461,7 @@ fn item_primitive(w: &mut fmt::Formatter, it: &clean::Item, _p: &clean::PrimitiveType) -> fmt::Result { try!(document(w, it)); - render_methods(w, it.def_id, MethodRender::All) + render_assoc_items(w, it.def_id, AssocItemRender::All) } fn get_basic_keywords() -> &'static str { diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index 53cfbb3efdd..74c16127f41 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -184,7 +184,8 @@ impl<'a> fold::DocFolder for Stripper<'a> { // Primitives are never stripped clean::PrimitiveItem(..) => {} - // Associated types are never stripped + // Associated consts and types are never stripped + clean::AssociatedConstItem(..) | clean::AssociatedTypeItem(..) => {} } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 399810cb7f5..3f2e7c765a5 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1236,6 +1236,7 @@ pub struct TraitItem { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum TraitItem_ { + ConstTraitItem(P<Ty>, Option<P<Expr>>), MethodTraitItem(MethodSig, Option<P<Block>>), TypeTraitItem(TyParamBounds, Option<P<Ty>>), } @@ -1252,6 +1253,7 @@ pub struct ImplItem { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum ImplItem_ { + ConstImplItem(P<Ty>, P<Expr>), MethodImplItem(MethodSig, P<Block>), TypeImplItem(P<Ty>), MacImplItem(Mac), diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs index 1505d1e91b8..36a7f3a9381 100644 --- a/src/libsyntax/ast_map/blocks.rs +++ b/src/libsyntax/ast_map/blocks.rs @@ -222,8 +222,7 @@ impl<'a> FnLikeNode<'a> { ast::MethodImplItem(ref sig, ref body) => { method(ii.id, ii.ident, sig, Some(ii.vis), body, ii.span) } - ast::TypeImplItem(_) | - ast::MacImplItem(_) => { + _ => { panic!("impl method FnLikeNode that is not fn-like") } } diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index 2a9a609ecd1..795391d4009 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -940,6 +940,12 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { } Some(NodeImplItem(ii)) => { match ii.node { + ConstImplItem(..) => { + format!("assoc const {} in {}{}", + token::get_ident(ii.ident), + map.path_to_string(id), + id_str) + } MethodImplItem(..) => { format!("method {} in {}{}", token::get_ident(ii.ident), @@ -959,9 +965,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { } Some(NodeTraitItem(ti)) => { let kind = match ti.node { + ConstTraitItem(..) => "assoc constant", MethodTraitItem(..) => "trait method", TypeTraitItem(..) => "assoc type", -// ConstTraitItem(..) => "assoc constant" }; format!("{} {} in {}{}", diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 8ba36cefc65..22bc3a198e2 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -973,6 +973,10 @@ pub fn noop_fold_trait_item<T: Folder>(i: P<TraitItem>, folder: &mut T) ident: folder.fold_ident(ident), attrs: fold_attrs(attrs, folder), node: match node { + ConstTraitItem(ty, default) => { + ConstTraitItem(folder.fold_ty(ty), + default.map(|x| folder.fold_expr(x))) + } MethodTraitItem(sig, body) => { MethodTraitItem(noop_fold_method_sig(sig, folder), body.map(|x| folder.fold_block(x))) @@ -994,6 +998,9 @@ pub fn noop_fold_impl_item<T: Folder>(i: P<ImplItem>, folder: &mut T) attrs: fold_attrs(attrs, folder), vis: vis, node: match node { + ConstImplItem(ty, expr) => { + ConstImplItem(folder.fold_ty(ty), folder.fold_expr(expr)) + } MethodImplItem(sig, body) => { MethodImplItem(noop_fold_method_sig(sig, folder), folder.fold_block(body)) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 5a57e09fcff..6fd2a8b1815 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1269,6 +1269,7 @@ impl<'a> State<'a> { try!(self.maybe_print_comment(ti.span.lo)); try!(self.print_outer_attributes(&ti.attrs)); match ti.node { + ast::ConstTraitItem(_, _) => Ok(()), ast::MethodTraitItem(ref sig, ref body) => { if body.is_some() { try!(self.head("")); @@ -1295,6 +1296,7 @@ impl<'a> State<'a> { try!(self.maybe_print_comment(ii.span.lo)); try!(self.print_outer_attributes(&ii.attrs)); match ii.node { + ast::ConstImplItem(_, _) => Ok(()), ast::MethodImplItem(ref sig, ref body) => { try!(self.head("")); try!(self.print_method_sig(ii.ident, sig, ii.vis)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 4c70fc9f81f..2ab35367625 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -619,6 +619,12 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai visitor.visit_attribute(attr); } match trait_item.node { + ConstTraitItem(ref ty, ref default) => { + visitor.visit_ty(ty); + if let Some(ref expr) = *default { + visitor.visit_expr(expr); + } + } MethodTraitItem(ref sig, None) => { visitor.visit_explicit_self(&sig.explicit_self); visitor.visit_generics(&sig.generics); @@ -641,6 +647,10 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt visitor.visit_attribute(attr); } match impl_item.node { + ConstImplItem(ref ty, ref expr) => { + visitor.visit_ty(ty); + visitor.visit_expr(expr); + } MethodImplItem(ref sig, ref body) => { visitor.visit_fn(FkMethod(impl_item.ident, sig, Some(impl_item.vis)), &sig.decl, body, impl_item.span, impl_item.id); |
