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

Add #[defines] attribute and require it for all type-alias-impl-trait sites that register a hidden type #128440

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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
  •  
  •  
  •  
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4513,6 +4513,7 @@ version = "0.0.0"
dependencies = [
"itertools",
"rustc_abi",
"rustc_attr_parsing",
"rustc_data_structures",
"rustc_errors",
"rustc_fluent_macro",
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3381,6 +3381,7 @@ pub struct Fn {
pub generics: Generics,
pub sig: FnSig,
pub contract: Option<P<FnContract>>,
pub define_opaques: Option<ThinVec<(NodeId, Path)>>,
pub body: Option<P<Block>>,
}

Expand Down Expand Up @@ -3678,7 +3679,7 @@ mod size_asserts {
static_assert_size!(Block, 32);
static_assert_size!(Expr, 72);
static_assert_size!(ExprKind, 40);
static_assert_size!(Fn, 168);
static_assert_size!(Fn, 176);
static_assert_size!(ForeignItem, 88);
static_assert_size!(ForeignItemKind, 16);
static_assert_size!(GenericArg, 24);
Expand Down
14 changes: 13 additions & 1 deletion compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,14 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
_ctxt,
_ident,
_vis,
Fn { defaultness, generics, contract, body, sig: FnSig { header, decl, span } },
Fn {
defaultness,
generics,
contract,
body,
sig: FnSig { header, decl, span },
define_opaques,
},
) => {
// Identifier and visibility are visited as a part of the item.
visit_defaultness(vis, defaultness);
Expand All @@ -992,6 +999,11 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
vis.visit_block(body);
}
vis.visit_span(span);

for (id, path) in define_opaques.iter_mut().flatten() {
vis.visit_id(id);
vis.visit_path(path)
}
}
FnKind::Closure(binder, coroutine_kind, decl, body) => {
vis.visit_closure_binder(binder);
Expand Down
15 changes: 13 additions & 2 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,7 @@ pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics
let WhereClause { has_where_token: _, predicates, span: _ } = where_clause;
walk_list!(visitor, visit_generic_param, params);
walk_list!(visitor, visit_where_predicate, predicates);

V::Result::output()
}

Expand Down Expand Up @@ -891,14 +892,24 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
_ctxt,
_ident,
_vis,
Fn { defaultness: _, sig: FnSig { header, decl, span: _ }, generics, contract, body },
Fn {
defaultness: _,
sig: FnSig { header, decl, span: _ },
generics,
contract,
body,
define_opaques,
},
) => {
// Identifier and visibility are visited as a part of the item.
try_visit!(visitor.visit_fn_header(header));
try_visit!(visitor.visit_generics(generics));
try_visit!(visitor.visit_fn_decl(decl));
visit_opt!(visitor, visit_contract, contract);
visit_opt!(visitor, visit_block, body);
for (id, path) in define_opaques.iter().flatten() {
try_visit!(visitor.visit_path(path, *id))
}
}
FnKind::Closure(binder, coroutine_kind, decl, body) => {
try_visit!(visitor.visit_closure_binder(binder));
Expand Down Expand Up @@ -1202,7 +1213,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
FnKind::Closure(binder, coroutine_kind, fn_decl, body),
*span,
*id
))
));
}
ExprKind::Block(block, opt_label) => {
visit_opt!(visitor, visit_label, opt_label);
Expand Down
46 changes: 43 additions & 3 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use rustc_abi::ExternAbi;
use rustc_ast::ptr::P;
use rustc_ast::visit::AssocCtxt;
use rustc_ast::*;
use rustc_attr_parsing::AttributeKind;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::PredicateOrigin;
Expand Down Expand Up @@ -158,7 +159,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
let mut ident = i.ident;
let vis_span = self.lower_span(i.vis.span);
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
let define_opaques = match &i.kind {
ItemKind::Fn(f) => self.lower_define_opaques(&f.define_opaques),
_ => None,
};
let attrs = self.lower_attrs_with_extra(hir_id, &i.attrs, i.span, define_opaques);
let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind);
let item = hir::Item {
owner_id: hir_id.expect_owner(),
Expand Down Expand Up @@ -760,7 +765,12 @@ impl<'hir> LoweringContext<'_, 'hir> {

fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
let define_opaques = match &i.kind {
AssocItemKind::Fn(f) => self.lower_define_opaques(&f.define_opaques),
_ => None,
};
let attrs = self.lower_attrs_with_extra(hir_id, &i.attrs, i.span, define_opaques);

let trait_item_def_id = hir_id.expect_owner();

let (generics, kind, has_default) = match &i.kind {
Expand Down Expand Up @@ -896,7 +906,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
let has_value = true;
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
let define_opaques = match &i.kind {
AssocItemKind::Fn(f) => self.lower_define_opaques(&f.define_opaques),
_ => None,
};
let attrs = self.lower_attrs_with_extra(hir_id, &i.attrs, i.span, define_opaques);

let (generics, kind) = match &i.kind {
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
Expand Down Expand Up @@ -1657,6 +1671,32 @@ impl<'hir> LoweringContext<'_, 'hir> {
(lowered_generics, res)
}

pub(super) fn lower_define_opaques(
&mut self,
define_opaques: &Option<ThinVec<(NodeId, Path)>>,
) -> Option<hir::Attribute> {
let define_opaques = define_opaques.as_ref()?;
let define_opaques = define_opaques
.iter()
.filter_map(|(id, path)| {
let res = self.resolver.get_partial_res(*id).unwrap();
let Some(did) = res.expect_full_res().opt_def_id() else {
self.dcx().span_delayed_bug(path.span, "should have errored in resolve");
return None;
};
let Some(did) = did.as_local() else {
self.dcx().span_err(
path.span,
"only opaque types defined in the local crate can be defined",
);
return None;
};
Some((self.lower_span(path.span), did))
})
.collect();
Some(hir::Attribute::Parsed(AttributeKind::DefineOpaques(define_opaques)))
}

pub(super) fn lower_generic_bound_predicate(
&mut self,
ident: Ident,
Expand Down
16 changes: 14 additions & 2 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(exact_size_is_empty)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(rustdoc_internals)]
Expand Down Expand Up @@ -867,13 +868,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
attrs: &[Attribute],
target_span: Span,
) -> &'hir [hir::Attribute] {
if attrs.is_empty() {
self.lower_attrs_with_extra(id, attrs, target_span, std::iter::empty())
}

fn lower_attrs_with_extra(
&mut self,
id: HirId,
attrs: &[Attribute],
target_span: Span,
extra: impl IntoIterator<Item = hir::Attribute, IntoIter: ExactSizeIterator>,
) -> &'hir [hir::Attribute] {
let extra = extra.into_iter();
if attrs.is_empty() && extra.is_empty() {
&[]
} else {
let lowered_attrs = self.lower_attrs_vec(attrs, self.lower_span(target_span));

debug_assert_eq!(id.owner, self.current_hir_id_owner);
let ret = self.arena.alloc_from_iter(lowered_attrs);
let ret = self.arena.alloc_from_iter(lowered_attrs.into_iter().chain(extra));

// this is possible if an item contained syntactical attribute,
// but none of them parse succesfully or all of them were ignored
Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
walk_list!(self, visit_attribute, &item.attrs);
return; // Avoid visiting again.
}
ItemKind::Fn(func @ box Fn { defaultness, generics: _, sig, contract: _, body }) => {
ItemKind::Fn(
func @ box Fn {
defaultness,
generics: _,
sig,
contract: _,
body,
define_opaques: _,
},
) => {
self.check_defaultness(item.span, *defaultness);

let is_intrinsic =
Expand Down
11 changes: 1 addition & 10 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ use rustc_span::edition::Edition;
use rustc_span::source_map::{SourceMap, Spanned};
use rustc_span::symbol::IdentPrinter;
use rustc_span::{BytePos, CharPos, DUMMY_SP, FileName, Ident, Pos, Span, Symbol, kw, sym};
use thin_vec::ThinVec;

use crate::pp::Breaks::{Consistent, Inconsistent};
use crate::pp::{self, Breaks};
Expand Down Expand Up @@ -1970,15 +1969,7 @@ impl<'a> State<'a> {
) {
self.ibox(INDENT_UNIT);
self.print_formal_generic_params(generic_params);
let generics = ast::Generics {
params: ThinVec::new(),
where_clause: ast::WhereClause {
has_where_token: false,
predicates: ThinVec::new(),
span: DUMMY_SP,
},
span: DUMMY_SP,
};
let generics = ast::Generics::default();
let header = ast::FnHeader { safety, ext, ..ast::FnHeader::default() };
self.print_fn(decl, header, name, &generics);
self.end();
Expand Down
13 changes: 11 additions & 2 deletions compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,16 @@ impl<'a> State<'a> {
attrs: &[ast::Attribute],
func: &ast::Fn,
) {
let ast::Fn { defaultness, generics, sig, contract, body } = func;
let ast::Fn { defaultness, generics, sig, contract, body, define_opaques } = func;

if let Some(define_opaques) = define_opaques {
for (_, path) in define_opaques {
self.word("define opaques from ");
self.print_path(path, false, 0);
self.word(",");
}
}

if body.is_some() {
self.head("");
}
Expand Down Expand Up @@ -698,7 +707,7 @@ impl<'a> State<'a> {
}
self.print_generic_params(&generics.params);
self.print_fn_params_and_ret(decl, false);
self.print_where_clause(&generics.where_clause)
self.print_where_clause(&generics.where_clause);
}

pub(crate) fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl, is_closure: bool) {
Expand Down
23 changes: 23 additions & 0 deletions compiler/rustc_attr_data_structures/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use rustc_abi::Align;
use rustc_ast::token::CommentKind;
use rustc_ast::{self as ast, AttrStyle};
use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::Transparency;
use rustc_span::{Span, Symbol};
use thin_vec::ThinVec;
Expand Down Expand Up @@ -175,6 +176,8 @@ pub enum AttributeKind {
span: Span,
},
ConstStabilityIndirect,
/// List of type aliases that contain the opaque types that can be defined by the current item.
DefineOpaques(ThinVec<(Span, LocalDefId)>),
Deprecation {
deprecation: Deprecation,
span: Span,
Expand All @@ -195,3 +198,23 @@ pub enum AttributeKind {
},
// tidy-alphabetical-end
}

impl AttributeKind {
pub fn encode_cross_crate(&self) -> bool {
match self {
AttributeKind::DefineOpaques(..) => false,
AttributeKind::AllowConstFnUnstable(..)
| AttributeKind::AllowInternalUnstable(..)
| AttributeKind::BodyStability { .. }
| AttributeKind::Confusables { .. }
| AttributeKind::ConstStability { .. }
| AttributeKind::ConstStabilityIndirect
| AttributeKind::Deprecation { .. }
| AttributeKind::Diagnostic(..)
| AttributeKind::DocComment { .. }
| AttributeKind::MacroTransparency(..)
| AttributeKind::Repr(..)
| AttributeKind::Stability { .. } => true,
}
}
}
3 changes: 2 additions & 1 deletion compiler/rustc_attr_data_structures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use rustc_abi::Align;
use rustc_ast::token::CommentKind;
use rustc_ast::{AttrStyle, IntTy, UintTy};
use rustc_ast_pretty::pp::Printer;
use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::Transparency;
use rustc_span::{Span, Symbol};
pub use stability::*;
Expand Down Expand Up @@ -148,4 +149,4 @@ macro_rules! print_tup {
print_tup!(A B C D E F G H);
print_skip!(Span, ());
print_disp!(Symbol, u16, bool, NonZero<u32>);
print_debug!(UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
print_debug!(UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency, LocalDefId);
1 change: 1 addition & 0 deletions compiler/rustc_builtin_macros/src/alloc_error_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
generics: Generics::default(),
contract: None,
body,
define_opaques: None,
}));

let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)];
Expand Down
54 changes: 54 additions & 0 deletions compiler/rustc_builtin_macros/src/define_opaques.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use rustc_ast::{DUMMY_NODE_ID, ast};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::Span;

pub(crate) fn expand(
ecx: &mut ExtCtxt<'_>,
_expand_span: Span,
meta_item: &ast::MetaItem,
mut item: Annotatable,
) -> Vec<Annotatable> {
let define_opaques = match &mut item {
Annotatable::Item(p) => match &mut p.kind {
ast::ItemKind::Fn(f) => Some(&mut f.define_opaques),
_ => None,
},
Annotatable::AssocItem(i, _assoc_ctxt) => match &mut i.kind {
ast::AssocItemKind::Fn(func) => Some(&mut func.define_opaques),
_ => None,
},
Annotatable::Stmt(s) => match &mut s.kind {
ast::StmtKind::Item(p) => match &mut p.kind {
ast::ItemKind::Fn(f) => Some(&mut f.define_opaques),
_ => None,
},
_ => None,
},
_ => None,
};

let Some(list) = meta_item.meta_item_list() else {
ecx.dcx().span_err(meta_item.span, "expected list of type aliases");
return vec![item];
};

if let Some(define_opaques) = define_opaques {
*define_opaques = Some(
list.iter()
.filter_map(|entry| match entry {
ast::MetaItemInner::MetaItem(meta_item) if meta_item.is_word() => {
Some((DUMMY_NODE_ID, meta_item.path.clone()))
}
_ => {
ecx.dcx().span_err(entry.span(), "expected path to type alias");
None
}
})
.collect(),
);
} else {
ecx.dcx().span_err(meta_item.span, "only functions and methods can define opaque types");
}

vec![item]
}
Loading
Loading