Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Require a #[defines] attribute for type-alias-impl-trait in order for a function to be able to register hidden types. #110010

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
45 changes: 31 additions & 14 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,13 +390,19 @@ impl GenericParam {
pub struct Generics {
pub params: ThinVec<GenericParam>,
pub where_clause: WhereClause,
pub defines_opaque_types: ThinVec<(NodeId, Path)>,
pub span: Span,
}

impl Default for Generics {
impl Generics {
/// Creates an instance of `Generics`.
fn default() -> Generics {
Generics { params: ThinVec::new(), where_clause: Default::default(), span: DUMMY_SP }
pub fn new(span: Span, defines_opaque_types: ThinVec<(NodeId, Path)>) -> Generics {
Generics {
params: ThinVec::new(),
defines_opaque_types,
where_clause: Default::default(),
span,
}
}
}

Expand Down Expand Up @@ -2895,13 +2901,15 @@ pub struct StaticItem {
pub ty: P<Ty>,
pub mutability: Mutability,
pub expr: Option<P<Expr>>,
pub defines_opaque_types: ThinVec<(NodeId, Path)>,
}

#[derive(Clone, Encodable, Decodable, Debug)]
pub struct ConstItem {
pub defaultness: Defaultness,
pub ty: P<Ty>,
pub expr: Option<P<Expr>>,
pub defines_opaque_types: ThinVec<(NodeId, Path)>,
}

#[derive(Clone, Encodable, Decodable, Debug)]
Expand Down Expand Up @@ -3098,9 +3106,15 @@ pub enum ForeignItemKind {
impl From<ForeignItemKind> for ItemKind {
fn from(foreign_item_kind: ForeignItemKind) -> ItemKind {
match foreign_item_kind {
ForeignItemKind::Static(a, b, c) => {
ItemKind::Static(StaticItem { ty: a, mutability: b, expr: c }.into())
}
ForeignItemKind::Static(a, b, c) => ItemKind::Static(
StaticItem {
ty: a,
mutability: b,
expr: c,
defines_opaque_types: Default::default(),
}
.into(),
),
ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
ForeignItemKind::MacCall(a) => ItemKind::MacCall(a),
Expand All @@ -3113,9 +3127,12 @@ impl TryFrom<ItemKind> for ForeignItemKind {

fn try_from(item_kind: ItemKind) -> Result<ForeignItemKind, ItemKind> {
Ok(match item_kind {
ItemKind::Static(box StaticItem { ty: a, mutability: b, expr: c }) => {
ForeignItemKind::Static(a, b, c)
}
ItemKind::Static(box StaticItem {
ty: a,
mutability: b,
expr: c,
defines_opaque_types,
}) if defines_opaque_types.is_empty() => ForeignItemKind::Static(a, b, c),
ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind),
ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind),
ItemKind::MacCall(a) => ForeignItemKind::MacCall(a),
Expand All @@ -3138,15 +3155,15 @@ mod size_asserts {
static_assert_size!(Block, 32);
static_assert_size!(Expr, 72);
static_assert_size!(ExprKind, 40);
static_assert_size!(Fn, 152);
static_assert_size!(Fn, 160);
static_assert_size!(ForeignItem, 96);
static_assert_size!(ForeignItemKind, 24);
static_assert_size!(GenericArg, 24);
static_assert_size!(GenericBound, 56);
static_assert_size!(Generics, 40);
static_assert_size!(Impl, 136);
static_assert_size!(Item, 136);
static_assert_size!(ItemKind, 64);
static_assert_size!(Generics, 48);
static_assert_size!(Impl, 144);
static_assert_size!(Item, 152);
static_assert_size!(ItemKind, 80);
static_assert_size!(LitKind, 24);
static_assert_size!(Local, 72);
static_assert_size!(MetaItemLit, 40);
Expand Down
49 changes: 47 additions & 2 deletions compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit};
use crate::ast::{MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem, NormalAttr};
use crate::ast::{Path, PathSegment, DUMMY_NODE_ID};
use crate::ptr::P;
use crate::token::{self, CommentKind, Delimiter, Token};
use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
use crate::token::{self, CommentKind, Delimiter, Token, TokenKind};
use crate::tokenstream::{AttrTokenStream, AttrTokenTree, DelimSpan, Spacing, TokenTree};
use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
use crate::util::comments;
use crate::util::literal::escape_string_symbol;
Expand Down Expand Up @@ -215,6 +215,51 @@ impl Attribute {
)]),
}
}

pub fn expand_cfg_attr(
self: &Attribute,
attr_id_generator: &AttrIdGenerator,
(item, item_span): (AttrItem, Span),
) -> Attribute {
let orig_tokens = self.tokens();

// We are taking an attribute of the form `#[cfg_attr(pred, attr)]`
// and producing an attribute of the form `#[attr]`. We
// have captured tokens for `attr` itself, but we need to
// synthesize tokens for the wrapper `#` and `[]`, which
// we do below.

// Use the `#` in `#[cfg_attr(pred, attr)]` as the `#` token
// for `attr` when we expand it to `#[attr]`
let mut orig_trees = orig_tokens.into_trees();
let TokenTree::Token(pound_token @ Token { kind: TokenKind::Pound, .. }, _) = orig_trees.next().unwrap() else {
panic!("Bad tokens for attribute {:?}", self);
};
let pound_span = pound_token.span;

let mut trees = vec![AttrTokenTree::Token(pound_token, Spacing::Alone)];
if self.style == AttrStyle::Inner {
// For inner attributes, we do the same thing for the `!` in `#![some_attr]`
let TokenTree::Token(bang_token @ Token { kind: TokenKind::Not, .. }, _) = orig_trees.next().unwrap() else {
panic!("Bad tokens for attribute {:?}", self);
};
trees.push(AttrTokenTree::Token(bang_token, Spacing::Alone));
}
// We don't really have a good span to use for the synthesized `[]`
// in `#[attr]`, so just use the span of the `#` token.
let bracket_group = AttrTokenTree::Delimited(
DelimSpan::from_single(pound_span),
Delimiter::Bracket,
item.tokens
.as_ref()
.unwrap_or_else(|| panic!("Missing tokens for {:?}", item))
.to_attr_token_stream(),
);
trees.push(bracket_group);
let tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::new(trees)));

mk_attr_from_item(attr_id_generator, item, tokens, self.style, item_span)
}
}

impl AttrItem {
Expand Down
19 changes: 16 additions & 3 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -926,10 +926,14 @@ fn noop_visit_lifetime<T: MutVisitor>(Lifetime { id, ident }: &mut Lifetime, vis
}

pub fn noop_visit_generics<T: MutVisitor>(generics: &mut Generics, vis: &mut T) {
let Generics { params, where_clause, span } = generics;
let Generics { params, where_clause, span, defines_opaque_types } = generics;
params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
vis.visit_where_clause(where_clause);
vis.visit_span(span);
for (id, path) in defines_opaque_types {
vis.visit_id(id);
vis.visit_path(path);
}
}

pub fn noop_visit_where_clause<T: MutVisitor>(wc: &mut WhereClause, vis: &mut T) {
Expand Down Expand Up @@ -1030,9 +1034,13 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
match kind {
ItemKind::ExternCrate(_orig_name) => {}
ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
ItemKind::Static(box StaticItem { ty, mutability: _, expr, defines_opaque_types }) => {
vis.visit_ty(ty);
visit_opt(expr, |expr| vis.visit_expr(expr));
for (id, path) in defines_opaque_types {
vis.visit_id(id);
vis.visit_path(path);
}
}
ItemKind::Const(item) => {
visit_const_item(item, vis);
Expand Down Expand Up @@ -1150,12 +1158,17 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
}

fn visit_const_item<T: MutVisitor>(
ConstItem { defaultness, ty, expr }: &mut ConstItem,
ConstItem { defaultness, ty, expr, defines_opaque_types }: &mut ConstItem,
visitor: &mut T,
) {
visit_defaultness(defaultness, visitor);
visitor.visit_ty(ty);
visit_opt(expr, |expr| visitor.visit_expr(expr));

for (id, path) in defines_opaque_types {
visitor.visit_id(id);
visitor.visit_path(path);
}
}

pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
Expand Down
11 changes: 9 additions & 2 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,14 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
match &item.kind {
ItemKind::ExternCrate(_) => {}
ItemKind::Use(use_tree) => visitor.visit_use_tree(use_tree, item.id, false),
ItemKind::Static(box StaticItem { ty, mutability: _, expr })
| ItemKind::Const(box ConstItem { ty, expr, .. }) => {
ItemKind::Static(box StaticItem { ty, mutability: _, expr, defines_opaque_types })
| ItemKind::Const(box ConstItem { ty, expr, defines_opaque_types, .. }) => {
visitor.visit_ty(ty);
walk_list!(visitor, visit_expr, expr);

for (id, path) in defines_opaque_types {
visitor.visit_path(path, *id);
}
}
ItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
let kind =
Expand Down Expand Up @@ -606,6 +610,9 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Generi
pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) {
walk_list!(visitor, visit_generic_param, &generics.params);
walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates);
for (id, path) in &generics.defines_opaque_types {
visitor.visit_path(path, *id);
}
}

pub fn walk_closure_binder<'a, V: Visitor<'a>>(visitor: &mut V, binder: &'a ClosureBinder) {
Expand Down
38 changes: 34 additions & 4 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,13 +229,20 @@ impl<'hir> LoweringContext<'_, 'hir> {

self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs)
}
ItemKind::Static(box ast::StaticItem { ty: t, mutability: m, expr: e }) => {
ItemKind::Static(box ast::StaticItem {
ty: t,
mutability: m,
expr: e,
defines_opaque_types,
}) => {
let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
hir::ItemKind::Static(ty, *m, body_id)
let defines_opaque_types = self.lower_defines(defines_opaque_types);
hir::ItemKind::Static(ty, *m, body_id, defines_opaque_types)
}
ItemKind::Const(box ast::ConstItem { ty, expr, .. }) => {
ItemKind::Const(box ast::ConstItem { ty, expr, defines_opaque_types, .. }) => {
let (ty, body_id) = self.lower_const_item(ty, span, expr.as_deref());
hir::ItemKind::Const(ty, body_id)
let defines_opaque_types = self.lower_defines(defines_opaque_types);
hir::ItemKind::Const(ty, body_id, defines_opaque_types)
}
ItemKind::Fn(box Fn {
sig: FnSig { decl, header, span: fn_sig_span },
Expand Down Expand Up @@ -1368,17 +1375,40 @@ impl<'hir> LoweringContext<'_, 'hir> {
let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
predicates.extend(impl_trait_bounds.into_iter());

let defines_opaque_types = self.lower_defines(&generics.defines_opaque_types);

let lowered_generics = self.arena.alloc(hir::Generics {
params: self.arena.alloc_from_iter(params),
predicates: self.arena.alloc_from_iter(predicates),
has_where_clause_predicates,
where_clause_span,
span,
defines_opaque_types,
});

(lowered_generics, res)
}

fn lower_defines(
&mut self,
defines_opaque_types: &[(NodeId, ast::Path)],
) -> &'hir [&'hir hir::Path<'hir>] {
let arena = self.arena;

let defines_opaque_types = defines_opaque_types.iter().map(|(id, path)| {
let qpath = self.lower_qpath(
*id,
&None,
path,
ParamMode::Explicit,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
);
let hir::QPath::Resolved(None, path) = qpath else { panic!("{qpath:?}") };
path
});
arena.alloc_from_iter(defines_opaque_types)
}

pub(super) fn lower_generic_bound_predicate(
&mut self,
ident: Ident,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1593,6 +1593,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
has_where_clause_predicates: false,
where_clause_span: lctx.lower_span(span),
span: lctx.lower_span(span),
defines_opaque_types: &[],
}),
bounds: hir_bounds,
origin,
Expand Down Expand Up @@ -2046,6 +2047,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
has_where_clause_predicates: false,
where_clause_span: this.lower_span(span),
span: this.lower_span(span),
defines_opaque_types: &[],
}),
bounds: arena_vec![this; future_bound],
origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1726,6 +1726,7 @@ impl<'a> State<'a> {
self.print_formal_generic_params(generic_params);
let generics = ast::Generics {
params: ThinVec::new(),
defines_opaque_types: ThinVec::new(),
where_clause: ast::WhereClause {
has_where_token: false,
predicates: ThinVec::new(),
Expand Down
23 changes: 19 additions & 4 deletions compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,12 @@ impl<'a> State<'a> {
self.print_use_tree(tree);
self.word(";");
}
ast::ItemKind::Static(box StaticItem { ty, mutability: mutbl, expr: body }) => {
ast::ItemKind::Static(box StaticItem {
ty,
mutability: mutbl,
expr: body,
defines_opaque_types: _,
}) => {
let def = ast::Defaultness::Final;
self.print_item_const(
item.ident,
Expand All @@ -168,7 +173,12 @@ impl<'a> State<'a> {
def,
);
}
ast::ItemKind::Const(box ast::ConstItem { defaultness, ty, expr }) => {
ast::ItemKind::Const(box ast::ConstItem {
defaultness,
ty,
expr,
defines_opaque_types: _,
}) => {
self.print_item_const(
item.ident,
None,
Expand Down Expand Up @@ -496,7 +506,7 @@ impl<'a> State<'a> {
pub(crate) fn print_variant(&mut self, v: &ast::Variant) {
self.head("");
self.print_visibility(&v.vis);
let generics = ast::Generics::default();
let generics = ast::Generics::new(v.span, Default::default());
self.print_struct(&v.data, &generics, v.ident, v.span, false);
if let Some(d) = &v.disr_expr {
self.space();
Expand All @@ -515,7 +525,12 @@ impl<'a> State<'a> {
ast::AssocItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
}
ast::AssocItemKind::Const(box ast::ConstItem { defaultness, ty, expr }) => {
ast::AssocItemKind::Const(box ast::ConstItem {
defaultness,
ty,
expr,
defines_opaque_types: _,
}) => {
self.print_item_const(ident, None, ty, expr.as_deref(), vis, *defaultness);
}
ast::AssocItemKind::Type(box ast::TyAlias {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_pretty/src/pprust/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fn test_fun_to_string() {
inputs: ThinVec::new(),
output: ast::FnRetTy::Default(rustc_span::DUMMY_SP),
};
let generics = ast::Generics::default();
let generics = ast::Generics::new(rustc_span::DUMMY_SP, Default::default());
assert_eq!(
fun_to_string(&decl, ast::FnHeader::default(), abba_ident, &generics),
"fn abba()"
Expand Down
Loading