Skip to content

Commit adc18bb

Browse files
committed
rustc: Introduce and parse additional meta_item forms
Examples: #[test], #[link(name = "vers")] Issue #487
1 parent 6451380 commit adc18bb

File tree

8 files changed

+153
-37
lines changed

8 files changed

+153
-37
lines changed

src/comp/back/link.rs

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,15 @@ fn get_crate_meta_export(&session::session sess, &ast::crate c, str k,
291291
str default, bool warn_default) -> str {
292292
let vec[@ast::meta_item] v = [];
293293
for each (@ast::meta_item mi in crate_export_metas(c)) {
294-
if (mi.node.key == k) { v += [mi]; }
294+
// FIXME (#487): Support all variants of meta_item
295+
alt (mi.node) {
296+
case (ast::meta_key_value(?key, ?value)) {
297+
if (key == k) { v += [mi]; }
298+
}
299+
case (_) {
300+
sess.unimpl("meta_item variant");
301+
}
302+
}
295303
}
296304
alt (vec::len(v)) {
297305
case (0u) {
@@ -301,7 +309,16 @@ fn get_crate_meta_export(&session::session sess, &ast::crate c, str k,
301309
}
302310
ret default;
303311
}
304-
case (1u) { ret v.(0).node.value; }
312+
case (1u) {
313+
alt (v.(0).node) {
314+
case (ast::meta_key_value(_, ?value)) {
315+
ret value;
316+
}
317+
case (_) {
318+
sess.unimpl("meta_item variant");
319+
}
320+
}
321+
}
305322
case (_) {
306323
sess.span_fatal(v.(1).span, #fmt("duplicate meta '%s'", k));
307324
}
@@ -312,21 +329,45 @@ fn get_crate_meta_export(&session::session sess, &ast::crate c, str k,
312329
// This calculates CMH as defined above
313330
fn crate_meta_extras_hash(sha1 sha, &ast::crate crate) -> str {
314331
fn lteq(&@ast::meta_item ma, &@ast::meta_item mb) -> bool {
315-
ret ma.node.key <= mb.node.key;
332+
fn key(&@ast::meta_item m) -> ast::ident {
333+
alt (m.node) {
334+
case (ast::meta_word(?name)) {
335+
name
336+
}
337+
case (ast::meta_key_value(?key, _)) {
338+
key
339+
}
340+
}
341+
}
342+
ret key(ma) <= key(mb);
316343
}
317344
fn len_and_str(&str s) -> str { ret #fmt("%u_%s", str::byte_len(s), s); }
318345
let vec[mutable @ast::meta_item] v = [mutable ];
319346
for each (@ast::meta_item mi in crate_export_metas(crate)) {
320-
if (mi.node.key != "name" && mi.node.key != "vers") {
321-
v += [mutable mi];
347+
alt (mi.node) {
348+
case (ast::meta_key_value(?key, _)) {
349+
if (key != "name" && key != "vers") {
350+
v += [mutable mi];
351+
}
352+
}
353+
case (_) {
354+
v += [mutable mi];
355+
}
322356
}
323357
}
324358
sort::quick_sort(lteq, v);
325359
sha.reset();
326360
for (@ast::meta_item m_ in v) {
327361
auto m = m_;
328-
sha.input_str(len_and_str(m.node.key));
329-
sha.input_str(len_and_str(m.node.value));
362+
alt (m.node) {
363+
case (ast::meta_key_value(?key, ?value)) {
364+
sha.input_str(len_and_str(key));
365+
sha.input_str(len_and_str(value));
366+
}
367+
case (ast::meta_word(?name)) {
368+
sha.input_str(len_and_str(name));
369+
}
370+
}
330371
}
331372
ret truncated_sha1_result(sha);
332373
}

src/comp/front/ast.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,11 @@ type crate_directive = spanned[crate_directive_];
9797

9898
type meta_item = spanned[meta_item_];
9999

100-
type meta_item_ = rec(ident key, str value);
100+
tag meta_item_ {
101+
meta_word(ident);
102+
meta_list(ident, vec[@meta_item]);
103+
meta_key_value(ident, str);
104+
}
101105

102106
type block = spanned[block_];
103107

src/comp/front/creader.rs

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -548,19 +548,30 @@ fn metadata_matches(hashmap[str, str] mm, &vec[@ast::meta_item] metas) ->
548548
log #fmt("matching %u metadata requirements against %u metadata items",
549549
vec::len(metas), mm.size());
550550
for (@ast::meta_item mi in metas) {
551-
alt (mm.find(mi.node.key)) {
552-
case (some(?v)) {
553-
if (v == mi.node.value) {
554-
log #fmt("matched '%s': '%s'", mi.node.key,
555-
mi.node.value);
556-
} else {
557-
log #fmt("missing '%s': '%s' (got '%s')", mi.node.key,
558-
mi.node.value, v);
559-
ret false;
551+
alt (mi.node) {
552+
case (ast::meta_key_value(?key, ?value)) {
553+
alt (mm.find(key)) {
554+
case (some(?v)) {
555+
if (v == value) {
556+
log #fmt("matched '%s': '%s'", key,
557+
value);
558+
} else {
559+
log #fmt("missing '%s': '%s' (got '%s')",
560+
key,
561+
value, v);
562+
ret false;
563+
}
564+
}
565+
case (none) {
566+
log #fmt("missing '%s': '%s'",
567+
key, value);
568+
ret false;
569+
}
560570
}
561571
}
562-
case (none) {
563-
log #fmt("missing '%s': '%s'", mi.node.key, mi.node.value);
572+
case (_) {
573+
// FIXME (#487): Support all forms of meta_item
574+
log_err "unimplemented meta_item variant in metadata_matches";
564575
ret false;
565576
}
566577
}
@@ -574,7 +585,18 @@ fn find_library_crate(&session::session sess, &ast::ident ident,
574585
option::t[tup(str, vec[u8])] {
575586
let str crate_name = ident;
576587
for (@ast::meta_item mi in metas) {
577-
if (mi.node.key == "name") { crate_name = mi.node.value; break; }
588+
alt (mi.node) {
589+
case (ast::meta_key_value(?key, ?value)) {
590+
if (key == "name") {
591+
crate_name = value;
592+
break;
593+
}
594+
}
595+
case (_) {
596+
// FIXME (#487)
597+
sess.unimpl("meta_item variant")
598+
}
599+
}
578600
}
579601
auto nn = parser::default_native_lib_naming(sess);
580602
let str prefix = nn.prefix + crate_name;

src/comp/front/parser.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2113,26 +2113,41 @@ fn parse_inner_attrs(&parser p) -> vec[ast::attribute] {
21132113
fn parse_meta_item(&parser p) -> @ast::meta_item {
21142114
auto lo = p.get_lo_pos();
21152115
auto ident = parse_ident(p);
2116-
expect(p, token::EQ);
21172116
alt (p.peek()) {
2118-
case (token::LIT_STR(?s)) {
2119-
auto hi = p.get_hi_pos();
2117+
case (token::EQ) {
21202118
p.bump();
2121-
ret @spanned(lo, hi, rec(key=ident, value=p.get_str(s)));
2119+
alt (p.peek()) {
2120+
case (token::LIT_STR(?s)) {
2121+
p.bump();
2122+
auto value = p.get_str(s);
2123+
auto hi = p.get_hi_pos();
2124+
ret @spanned(lo, hi, ast::meta_key_value(ident, value));
2125+
}
2126+
case (_) {
2127+
p.fatal("Metadata items must be string literals");
2128+
}
2129+
}
2130+
}
2131+
case (token::LPAREN) {
2132+
auto inner_items = parse_meta_seq(p);
2133+
auto hi = p.get_hi_pos();
2134+
ret @spanned(lo, hi, ast::meta_list(ident, inner_items));
2135+
}
2136+
case (_) {
2137+
auto hi = p.get_hi_pos();
2138+
ret @spanned(lo, hi, ast::meta_word(ident));
21222139
}
2123-
case (_) { p.fatal("Metadata items must be string literals"); }
21242140
}
2125-
fail;
21262141
}
21272142

2128-
fn parse_meta(&parser p) -> vec[@ast::meta_item] {
2143+
fn parse_meta_seq(&parser p) -> vec[@ast::meta_item] {
21292144
ret parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
21302145
parse_meta_item, p).node;
21312146
}
21322147

21332148
fn parse_optional_meta(&parser p) -> vec[@ast::meta_item] {
21342149
alt (p.peek()) {
2135-
case (token::LPAREN) { ret parse_meta(p); }
2150+
case (token::LPAREN) { ret parse_meta_seq(p); }
21362151
case (_) { let vec[@ast::meta_item] v = []; ret v; }
21372152
}
21382153
}

src/comp/middle/metadata.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -669,13 +669,21 @@ fn write_int(&io::writer writer, &int n) {
669669

670670
fn encode_meta_items(&ebml::writer ebml_w, &crate crate) {
671671
fn encode_meta_item(&ebml::writer ebml_w, &meta_item mi) {
672+
// FIXME (#487): Support all forms of meta item
672673
ebml::start_tag(ebml_w, tag_meta_item);
673-
ebml::start_tag(ebml_w, tag_meta_item_key);
674-
ebml_w.writer.write(str::bytes(mi.node.key));
675-
ebml::end_tag(ebml_w);
676-
ebml::start_tag(ebml_w, tag_meta_item_value);
677-
ebml_w.writer.write(str::bytes(mi.node.value));
678-
ebml::end_tag(ebml_w);
674+
alt (mi.node) {
675+
case (meta_key_value(?key, ?value)) {
676+
ebml::start_tag(ebml_w, tag_meta_item_key);
677+
ebml_w.writer.write(str::bytes(key));
678+
ebml::end_tag(ebml_w);
679+
ebml::start_tag(ebml_w, tag_meta_item_value);
680+
ebml_w.writer.write(str::bytes(value));
681+
ebml::end_tag(ebml_w);
682+
}
683+
case (_) {
684+
log_err "unimplemented meta_item type";
685+
}
686+
}
679687
ebml::end_tag(ebml_w);
680688
}
681689
ebml::start_tag(ebml_w, tag_meta_export);

src/comp/pretty/pprust.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,9 +1018,18 @@ fn print_type_params(&ps s, &vec[ast::ty_param] params) {
10181018

10191019
fn print_meta_item(&ps s, &@ast::meta_item item) {
10201020
ibox(s, indent_unit);
1021-
word_space(s, item.node.key);
1022-
word_space(s, "=");
1023-
print_string(s, item.node.value);
1021+
// FIXME (#487): Print other meta item variants
1022+
alt (item.node) {
1023+
case (ast::meta_key_value(?key, ?value)) {
1024+
word_space(s, key);
1025+
word_space(s, "=");
1026+
print_string(s, value);
1027+
}
1028+
case (_) {
1029+
log_err "unimplemented meta_item variant";
1030+
fail;
1031+
}
1032+
}
10241033
end(s);
10251034
}
10261035

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// xfail-stage0
2+
// error-pattern:expecting \]
3+
4+
// asterisk is bogus
5+
#[attr*]
6+
mod m { }

src/test/run-pass/item-attributes.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,17 @@ mod test_distinguish_syntax_ext {
173173
}
174174
}
175175

176+
mod test_other_forms {
177+
#[attr]
178+
#[attr(word)]
179+
#[attr(attr(word))]
180+
#[attr(key1 = "val",
181+
key2 = "val",
182+
attr)]
183+
fn f() {
184+
}
185+
}
186+
176187
fn main() {
177188
}
178189

0 commit comments

Comments
 (0)