about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/hir/map/def_collector.rs15
-rw-r--r--src/librustc/hir/map/definitions.rs2
-rw-r--r--src/test/ui/attributes/unnamed-field-attributes.rs9
3 files changed, 24 insertions, 2 deletions
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index bffb4df836e..b42fbd5c0a1 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -170,9 +170,13 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
     }
 
     fn visit_variant_data(&mut self, data: &'a VariantData) {
+        // The assumption here is that non-`cfg` macro expansion cannot change field indices.
+        // It currently holds because only inert attributes are accepted on fields,
+        // and every such attribute expands into a single field after it's resolved.
         for (index, field) in data.fields().iter().enumerate() {
             if field.is_placeholder {
                 self.visit_macro_invoc(field.id);
+                self.definitions.placeholder_field_indices.insert(field.id, index);
                 continue;
             }
             let name = field.ident.map(|ident| ident.name)
@@ -338,12 +342,19 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         }
     }
 
+    // This method is called only when we are visiting an individual field
+    // after expanding an attribute on it.
     fn visit_struct_field(&mut self, sf: &'a StructField) {
         if sf.is_placeholder {
             self.visit_macro_invoc(sf.id)
         } else {
-            let name = sf.ident.map(|ident| ident.name)
-                .unwrap_or_else(|| panic!("don't know the field number in this context"));
+            let name = sf.ident.map_or_else(
+                || {
+                    let expn_id = NodeId::placeholder_from_expn_id(self.expansion);
+                    sym::integer(self.definitions.placeholder_field_indices[&expn_id])
+                },
+                |ident| ident.name,
+            );
             let def = self.create_def(sf.id,
                                         DefPathData::ValueNs(name.as_interned_str()),
                                         sf.span);
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 651fe8449ac..187bc593324 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -104,6 +104,8 @@ pub struct Definitions {
     /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId`
     /// we know what parent node that fragment should be attached to thanks to this table.
     invocation_parents: FxHashMap<ExpnId, DefIndex>,
+    /// Indices of unnamed struct or variant fields with unresolved attributes.
+    pub(super) placeholder_field_indices: NodeMap<usize>,
 }
 
 /// A unique identifier that we can use to lookup a definition
diff --git a/src/test/ui/attributes/unnamed-field-attributes.rs b/src/test/ui/attributes/unnamed-field-attributes.rs
new file mode 100644
index 00000000000..93f364047e9
--- /dev/null
+++ b/src/test/ui/attributes/unnamed-field-attributes.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+struct S(
+    #[rustfmt::skip] u8,
+    u16,
+    #[rustfmt::skip] u32,
+);
+
+fn main() {}