Skip to content

Allow proc macro to initialize a private field with a def_site value #47311

Closed

Description

@dtolnay

In a struct initializer expression S { k: v } generated by a procedural macro where the field k is private, it seems both k and v need to be spanned with call_site in order for the generated code to compile. I believe only k should be required to be call_site, and v should be allowed to be def_site or anything else.

This currently blocks a correct implementation of derive(Deserialize).

#![feature(proc_macro)]

extern crate mac;

struct S {
    unit: (),
}

fn main() {
    // Expands to `S { unit: () }`.
    mac::init_field_unit!(S unit);
}
#![feature(proc_macro)]

extern crate proc_macro;
use proc_macro::{TokenStream, TokenTree, TokenNode, Delimiter, Spacing, Span};

#[proc_macro]
pub fn init_field_unit(input: TokenStream) -> TokenStream {
    let mut iter = input.into_iter();
    let struct_name = iter.next().unwrap();
    let field_name = iter.next().unwrap();
    assert!(iter.next().is_none());

    // Expands to `$struct_name { $field_name: () }`.
    vec![
        struct_name,
        TokenTree {
            span: Span::call_site(),
            kind: TokenNode::Group(Delimiter::Brace, vec![
                field_name,
                TokenTree {
                    span: Span::call_site(),
                    kind: TokenNode::Op(':', Spacing::Alone),
                },
                TokenTree {
                    // Works if this is call_site, but in derive(Deserialize) I
                    // need to be able to use def_site variables here.
                    span: Span::def_site(),
                    kind: TokenNode::Group(Delimiter::Parenthesis, TokenStream::empty()),
                },
            ].into_iter().collect()),
        },
    ].into_iter().collect()
}
error[E0451]: field `unit` of struct `S` is private
  --> src/main.rs:49:5
   |
49 |     mac::init_field_unit!(S unit);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unit` is private

@jseyfried

Activity

  1. dtolnay commented on Jan 10, 2018

    @dtolnay
    MemberAuthor

    Found a workaround: wrap the def_site value in a set of call_site parentheses. It should work without this workaround.

    TokenTree {
        span: Span::call_site(),
        kind: TokenNode::Group(Delimiter::Parenthesis, vec![
            TokenTree {
                span: Span::def_site(),
                kind: TokenNode::Group(Delimiter::Parenthesis, TokenStream::empty()),
            },
        ].into_iter().collect()),
    },
  2. self-assigned this
    on Jan 10, 2018
  3. added
    C-enhancementCategory: An issue proposing an enhancement or a PR with one.
    A-decl-macros-2-0Area: Declarative macros 2.0 (#39412)
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Feb 6, 2018
  4. jseyfried commented on Feb 9, 2018

    @jseyfried
    Contributor

    @dtolnay Sorry for the delay!
    Fixed in #48082.

  5. added 2 commits that reference this issue on Feb 19, 2018
    face16b
  6. 98 remaining items

  7. added 9 commits that reference this issue on Mar 3, 2018
    3dbfa8b
    bffea5d
    85a6b92
    65253fd
    8bf026d
    8c7c8fb
    6fa14f0
    3fa4bff
    40d2a98
  8. added 6 commits that reference this issue on Oct 10, 2018
    a267b3a
    8ebc6d6
    50e410c
    e1e628e
    ff3e4d9
    be64bf3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-decl-macros-2-0Area: Declarative macros 2.0 (#39412)C-enhancementCategory: An issue proposing an enhancement or a PR with one.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions