Skip to content

Commit

Permalink
Functional changes for associated constants. Cross-crate usage of ass…
Browse files Browse the repository at this point in the history
…ociated constants is not yet working.
  • Loading branch information
quantheory committed Apr 24, 2015
1 parent b549977 commit 7129e88
Show file tree
Hide file tree
Showing 43 changed files with 1,387 additions and 294 deletions.
23 changes: 21 additions & 2 deletions src/grammar/parser-lalr.y
Expand Up @@ -505,10 +505,20 @@ trait_items
;

trait_item
: trait_type
: trait_const
| trait_type
| trait_method
;

trait_const
: maybe_outer_attrs CONST ident maybe_const_default ';' { $$ = mk_node("ConstTraitItem", 3, $1, $3, $4); }
;

maybe_const_default
: '=' expr { $$ = mk_node("ConstDefault", 1, $2); }
| %empty { $$ = mk_none(); }
;

trait_type
: maybe_outer_attrs TYPE ty_param ';' { $$ = mk_node("TypeTraitItem", 2, $1, $3); }
;
Expand Down Expand Up @@ -611,7 +621,16 @@ impl_items
impl_item
: impl_method
| item_macro
| trait_type
| impl_const
| impl_type
;

impl_const
: attrs_and_vis item_const { $$ = mk_node("ImplConst", 1, $1, $2); }
;

impl_type
: attrs_and_vis TYPE ident generic_params '=' ty_sum ';' { $$ = mk_node("ImplType", 4, $1, $3, $4, $6); }
;

item_fn
Expand Down
7 changes: 7 additions & 0 deletions src/librustc/metadata/csearch.rs
Expand Up @@ -175,6 +175,13 @@ pub fn get_provided_trait_methods<'tcx>(tcx: &ty::ctxt<'tcx>,
decoder::get_provided_trait_methods(cstore.intr.clone(), &*cdata, def.node, tcx)
}

pub fn get_associated_consts<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId)
-> Vec<Rc<ty::AssociatedConst<'tcx>>> {
let cstore = &tcx.sess.cstore;
let cdata = cstore.get_crate_data(def.krate);
decoder::get_associated_consts(cstore.intr.clone(), &*cdata, def.node, tcx)
}

pub fn get_type_name_if_impl(cstore: &cstore::CStore, def: ast::DefId)
-> Option<ast::Name> {
let cdata = cstore.get_crate_data(def.krate);
Expand Down
62 changes: 61 additions & 1 deletion src/librustc/metadata/decoder.rs
Expand Up @@ -305,7 +305,25 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
-> DefLike {
let fam = item_family(item);
match fam {
Constant => DlDef(def::DefConst(did)),
Constant => {
// Check whether we have an associated const item.
if item_sort(item) == Some('C') {
// Check whether the associated const is from a trait or impl.
// See the comment for methods below.
let provenance = if reader::maybe_get_doc(
item, tag_item_trait_parent_sort).is_some() {
def::FromTrait(item_reqd_and_translated_parent_item(cnum,
item))
} else {
def::FromImpl(item_reqd_and_translated_parent_item(cnum,
item))
};
DlDef(def::DefAssociatedConst(did, provenance))
} else {
// Regular const item.
DlDef(def::DefConst(did))
}
}
ImmStatic => DlDef(def::DefStatic(did, false)),
MutStatic => DlDef(def::DefStatic(did, true)),
Struct => DlDef(def::DefStruct(did)),
Expand Down Expand Up @@ -826,6 +844,7 @@ pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
tag_item_impl_item, |doc| {
let def_id = item_def_id(doc, cdata);
match item_sort(doc) {
Some('C') => impl_items.push(ty::ConstTraitItemId(def_id)),
Some('r') | Some('p') => {
impl_items.push(ty::MethodTraitItemId(def_id))
}
Expand Down Expand Up @@ -877,6 +896,18 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
let vis = item_visibility(method_doc);

match item_sort(method_doc) {
Some('C') => {
let ty = doc_type(method_doc, tcx, cdata);
let default = get_provided_source(method_doc, cdata);
ty::ConstTraitItem(Rc::new(ty::AssociatedConst {
name: name,
ty: ty,
vis: vis,
def_id: def_id,
container: container,
default: default,
}))
}
Some('r') | Some('p') => {
let generics = doc_generics(method_doc, tcx, cdata, tag_method_ty_generics);
let predicates = doc_predicates(method_doc, tcx, cdata, tag_method_ty_generics);
Expand Down Expand Up @@ -914,6 +945,7 @@ pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
reader::tagged_docs(item, tag_item_trait_item, |mth| {
let def_id = item_def_id(mth, cdata);
match item_sort(mth) {
Some('C') => result.push(ty::ConstTraitItemId(def_id)),
Some('r') | Some('p') => {
result.push(ty::MethodTraitItemId(def_id));
}
Expand Down Expand Up @@ -961,6 +993,34 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>,
return result;
}

pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
cdata: Cmd,
id: ast::NodeId,
tcx: &ty::ctxt<'tcx>)
-> Vec<Rc<ty::AssociatedConst<'tcx>>> {
let data = cdata.data();
let item = lookup_item(id, data);
let mut result = Vec::new();

reader::tagged_docs(item, tag_item_trait_item, |ac_id| {
let did = item_def_id(ac_id, cdata);
let ac_doc = lookup_item(did.node, data);

if item_sort(ac_doc) == Some('C') {
let trait_item = get_impl_or_trait_item(intr.clone(),
cdata,
did.node,
tcx);
if let ty::ConstTraitItem(ref ac) = trait_item {
result.push((*ac).clone())
}
}
true
});

return result;
}

pub fn get_type_name_if_impl(cdata: Cmd,
node_id: ast::NodeId) -> Option<ast::Name> {
let item = lookup_item(node_id, cdata.data());
Expand Down
83 changes: 75 additions & 8 deletions src/librustc/metadata/encoder.rs
Expand Up @@ -799,6 +799,43 @@ fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_provided_source(rbml_w, method_ty.provided_source);
}

fn encode_info_for_associated_const(ecx: &EncodeContext,
rbml_w: &mut Encoder,
associated_const: &ty::AssociatedConst,
impl_path: PathElems,
parent_id: NodeId,
impl_item_opt: Option<&ast::ImplItem>) {
debug!("encode_info_for_associated_const({:?},{:?})",
associated_const.def_id,
token::get_name(associated_const.name));

rbml_w.start_tag(tag_items_data_item);

encode_def_id(rbml_w, associated_const.def_id);
encode_name(rbml_w, associated_const.name);
encode_visibility(rbml_w, associated_const.vis);
encode_family(rbml_w, 'C');
encode_provided_source(rbml_w, associated_const.default);

encode_parent_item(rbml_w, local_def(parent_id));
encode_item_sort(rbml_w, 'C');

encode_bounds_and_type_for_item(rbml_w, ecx, associated_const.def_id.local_id());

let stab = stability::lookup(ecx.tcx, associated_const.def_id);
encode_stability(rbml_w, stab);

let elem = ast_map::PathName(associated_const.name);
encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));

if let Some(ii) = impl_item_opt {
encode_attributes(rbml_w, &ii.attrs);
encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id), ii));
}

rbml_w.end_tag();
}

fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
rbml_w: &mut Encoder,
m: &ty::Method<'tcx>,
Expand Down Expand Up @@ -1192,7 +1229,10 @@ 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::ConstTraitItemId(item_def_id) => {
encode_def_id(rbml_w, item_def_id);
encode_item_sort(rbml_w, 'C');
}
ty::MethodTraitItemId(item_def_id) => {
encode_def_id(rbml_w, item_def_id);
encode_item_sort(rbml_w, 'r');
Expand Down Expand Up @@ -1230,7 +1270,14 @@ fn encode_info_for_item(ecx: &EncodeContext,
});

match ty::impl_or_trait_item(tcx, trait_item_def_id.def_id()) {
ty::ConstTraitItem(_) => {}
ty::ConstTraitItem(ref associated_const) => {
encode_info_for_associated_const(ecx,
rbml_w,
&*associated_const,
path.clone(),
item.id,
ast_item)
}
ty::MethodTraitItem(ref method_type) => {
encode_info_for_method(ecx,
rbml_w,
Expand Down Expand Up @@ -1275,7 +1322,10 @@ 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::ConstTraitItemId(const_def_id) => {
encode_def_id(rbml_w, const_def_id);
encode_item_sort(rbml_w, 'C');
}
ty::MethodTraitItemId(method_def_id) => {
encode_def_id(rbml_w, method_def_id);
encode_item_sort(rbml_w, 'r');
Expand Down Expand Up @@ -1321,7 +1371,23 @@ 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(_) => {
ty::ConstTraitItem(associated_const) => {
encode_name(rbml_w, associated_const.name);
encode_def_id(rbml_w, associated_const.def_id);
encode_visibility(rbml_w, associated_const.vis);

encode_provided_source(rbml_w, associated_const.default);

let elem = ast_map::PathName(associated_const.name);
encode_path(rbml_w,
path.clone().chain(Some(elem).into_iter()));

encode_item_sort(rbml_w, 'C');
encode_family(rbml_w, 'C');

encode_bounds_and_type_for_item(rbml_w, ecx,
associated_const.def_id.local_id());

is_nonstatic_method = false;
}
ty::MethodTraitItem(method_ty) => {
Expand Down Expand Up @@ -1368,7 +1434,10 @@ 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::ConstTraitItem(_, _) => {
encode_inlined_item(ecx, rbml_w,
IITraitItemRef(def_id, trait_item));
}
ast::MethodTraitItem(ref sig, ref body) => {
// If this is a static method, we've already
// encoded this.
Expand All @@ -1388,9 +1457,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_method_argument_names(rbml_w, &sig.decl);
}

ast::TypeTraitItem(..) => {
encode_item_sort(rbml_w, 't');
}
ast::TypeTraitItem(..) => {}
}

rbml_w.end_tag();
Expand Down
33 changes: 29 additions & 4 deletions src/librustc/middle/check_const.rs
Expand Up @@ -223,6 +223,28 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
}
}

fn visit_trait_item(&mut self, t: &'v ast::TraitItem) {
match t.node {
ast::ConstTraitItem(_, ref default) => {
if let Some(ref expr) = *default {
self.global_expr(Mode::Const, &*expr);
} else {
visit::walk_trait_item(self, t);
}
}
_ => self.with_mode(Mode::Var, |v| visit::walk_trait_item(v, t)),
}
}

fn visit_impl_item(&mut self, i: &'v ast::ImplItem) {
match i.node {
ast::ConstImplItem(_, ref expr) => {
self.global_expr(Mode::Const, &*expr);
}
_ => self.with_mode(Mode::Var, |v| visit::walk_impl_item(v, i)),
}
}

fn visit_fn(&mut self,
fk: visit::FnKind<'v>,
fd: &'v ast::FnDecl,
Expand Down Expand Up @@ -468,13 +490,16 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
Mode::Var => v.add_qualif(NOT_CONST)
}
}
Some(def::DefConst(did)) => {
if let Some(expr) = const_eval::lookup_const_by_id(v.tcx, did) {
Some(def::DefConst(did)) |
Some(def::DefAssociatedConst(did, _)) => {
if let Some(expr) = const_eval::lookup_const_by_id(v.tcx, did,
Some(e.id)) {
let inner = v.global_expr(Mode::Const, expr);
v.add_qualif(inner);
} else {
v.tcx.sess.span_bug(e.span, "DefConst doesn't point \
to an ItemConst");
v.tcx.sess.span_bug(e.span,
"DefConst or DefAssociatedConst \
doesn't point to a constant");
}
}
def => {
Expand Down
15 changes: 8 additions & 7 deletions src/librustc/middle/check_match.rs
Expand Up @@ -442,7 +442,8 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
ast::PatIdent(..) | ast::PatEnum(..) => {
let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def());
match def {
Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did) {
Some(DefAssociatedConst(did, _)) |
Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did, Some(pat.id)) {
Some(const_expr) => {
const_expr_to_pat(self.tcx, const_expr, pat.span).map(|new_pat| {

Expand Down Expand Up @@ -746,7 +747,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
match pat.node {
ast::PatIdent(..) =>
match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(DefConst(..)) =>
Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
cx.tcx.sess.span_bug(pat.span, "const pattern should've \
been rewritten"),
Some(DefStruct(_)) => vec!(Single),
Expand All @@ -755,15 +756,15 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
},
ast::PatEnum(..) =>
match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(DefConst(..)) =>
Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
cx.tcx.sess.span_bug(pat.span, "const pattern should've \
been rewritten"),
Some(DefVariant(_, id, _)) => vec!(Variant(id)),
_ => vec!(Single)
},
ast::PatStruct(..) =>
match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(DefConst(..)) =>
Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
cx.tcx.sess.span_bug(pat.span, "const pattern should've \
been rewritten"),
Some(DefVariant(_, id, _)) => vec!(Variant(id)),
Expand Down Expand Up @@ -861,7 +862,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
ast::PatIdent(_, _, _) => {
let opt_def = cx.tcx.def_map.borrow().get(&pat_id).map(|d| d.full_def());
match opt_def {
Some(DefConst(..)) =>
Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
cx.tcx.sess.span_bug(pat_span, "const pattern should've \
been rewritten"),
Some(DefVariant(_, id, _)) => if *constructor == Variant(id) {
Expand All @@ -876,7 +877,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
ast::PatEnum(_, ref args) => {
let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
match def {
DefConst(..) =>
DefConst(..) | DefAssociatedConst(..) =>
cx.tcx.sess.span_bug(pat_span, "const pattern should've \
been rewritten"),
DefVariant(_, id, _) if *constructor != Variant(id) => None,
Expand All @@ -894,7 +895,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
// Is this a struct or an enum variant?
let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
let class_id = match def {
DefConst(..) =>
DefConst(..) | DefAssociatedConst(..) =>
cx.tcx.sess.span_bug(pat_span, "const pattern should've \
been rewritten"),
DefVariant(_, variant_id, _) => if *constructor == Variant(variant_id) {
Expand Down

0 comments on commit 7129e88

Please sign in to comment.