Skip to content

Commit a17c556

Browse files
petrochenkovMark-Simulacrum
authored andcommitted
expand: Fully preserve visibilities on unnamed fields with attributes
1 parent e49abf2 commit a17c556

File tree

4 files changed

+35
-5
lines changed

4 files changed

+35
-5
lines changed

src/librustc_resolve/build_reduced_graph.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
755755
// NOTE: The field may be an expansion placeholder, but expansion sets correct
756756
// visibilities for unnamed field placeholders specifically, so the constructor
757757
// visibility should still be determined correctly.
758-
let field_vis = self.resolve_visibility_speculative(&field.vis, true);
758+
let field_vis = self.resolve_visibility(&field.vis);
759759
if ctor_vis.is_at_least(field_vis, &*self.r) {
760760
ctor_vis = field_vis;
761761
}

src/libsyntax_expand/expand.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ macro_rules! ast_fragments {
8585
// mention some macro variable from those arguments even if it's not used.
8686
#[cfg_attr(bootstrap, allow(unused_macros))]
8787
macro _repeating($flat_map_ast_elt) {}
88-
placeholder(AstFragmentKind::$Kind, *id).$make_ast()
88+
placeholder(AstFragmentKind::$Kind, *id, None).$make_ast()
8989
})),)?)*
9090
_ => panic!("unexpected AST fragment kind")
9191
}
@@ -274,6 +274,23 @@ pub enum InvocationKind {
274274
},
275275
}
276276

277+
impl InvocationKind {
278+
fn placeholder_visibility(&self) -> Option<ast::Visibility> {
279+
// HACK: For unnamed fields placeholders should have the same visibility as the actual
280+
// fields because for tuple structs/variants resolve determines visibilities of their
281+
// constructor using these field visibilities before attributes on them are are expanded.
282+
// The assumption is that the attribute expansion cannot change field visibilities,
283+
// and it holds because only inert attributes are supported in this position.
284+
match self {
285+
InvocationKind::Attr { item: Annotatable::StructField(field), .. } |
286+
InvocationKind::Derive { item: Annotatable::StructField(field), .. } |
287+
InvocationKind::DeriveContainer { item: Annotatable::StructField(field), .. }
288+
if field.ident.is_none() => Some(field.vis.clone()),
289+
_ => None,
290+
}
291+
}
292+
}
293+
277294
impl Invocation {
278295
pub fn span(&self) -> Span {
279296
match &self.kind {
@@ -941,6 +958,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
941958
_ => None,
942959
};
943960
let expn_id = ExpnId::fresh(expn_data);
961+
let vis = kind.placeholder_visibility();
944962
self.invocations.push(Invocation {
945963
kind,
946964
fragment_kind,
@@ -950,7 +968,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
950968
..self.cx.current_expansion.clone()
951969
},
952970
});
953-
placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id))
971+
placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis)
954972
}
955973

956974
fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {

src/libsyntax_expand/placeholders.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use smallvec::{smallvec, SmallVec};
1212

1313
use rustc_data_structures::fx::FxHashMap;
1414

15-
pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
15+
pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId, vis: Option<ast::Visibility>)
16+
-> AstFragment {
1617
fn mac_placeholder() -> ast::Mac {
1718
ast::Mac {
1819
path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
@@ -26,7 +27,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
2627
let ident = ast::Ident::invalid();
2728
let attrs = Vec::new();
2829
let generics = ast::Generics::default();
29-
let vis = dummy_spanned(ast::VisibilityKind::Inherited);
30+
let vis = vis.unwrap_or_else(|| dummy_spanned(ast::VisibilityKind::Inherited));
3031
let span = DUMMY_SP;
3132
let expr_placeholder = || P(ast::Expr {
3233
id, span,
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Unnamed fields don't lose their visibility due to non-builtin attributes on them.
2+
3+
// check-pass
4+
5+
mod m {
6+
pub struct S(#[rustfmt::skip] pub u8);
7+
}
8+
9+
fn main() {
10+
m::S(0);
11+
}

0 commit comments

Comments
 (0)