Skip to content

Commit cb4751d

Browse files
committed
Implement #[define_opaque] attribute for functions.
1 parent 2c6a12e commit cb4751d

File tree

653 files changed

+2798
-2467
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

653 files changed

+2798
-2467
lines changed

Diff for: Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4529,6 +4529,7 @@ version = "0.0.0"
45294529
dependencies = [
45304530
"itertools",
45314531
"rustc_abi",
4532+
"rustc_attr_parsing",
45324533
"rustc_data_structures",
45334534
"rustc_errors",
45344535
"rustc_fluent_macro",

Diff for: compiler/rustc_ast/src/ast.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3466,6 +3466,7 @@ pub struct Fn {
34663466
pub generics: Generics,
34673467
pub sig: FnSig,
34683468
pub contract: Option<P<FnContract>>,
3469+
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
34693470
pub body: Option<P<Block>>,
34703471
}
34713472

@@ -3763,7 +3764,7 @@ mod size_asserts {
37633764
static_assert_size!(Block, 32);
37643765
static_assert_size!(Expr, 72);
37653766
static_assert_size!(ExprKind, 40);
3766-
static_assert_size!(Fn, 168);
3767+
static_assert_size!(Fn, 176);
37673768
static_assert_size!(ForeignItem, 88);
37683769
static_assert_size!(ForeignItemKind, 16);
37693770
static_assert_size!(GenericArg, 24);

Diff for: compiler/rustc_ast/src/mut_visit.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,14 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
973973
_ctxt,
974974
_ident,
975975
_vis,
976-
Fn { defaultness, generics, contract, body, sig: FnSig { header, decl, span } },
976+
Fn {
977+
defaultness,
978+
generics,
979+
contract,
980+
body,
981+
sig: FnSig { header, decl, span },
982+
define_opaque,
983+
},
977984
) => {
978985
// Identifier and visibility are visited as a part of the item.
979986
visit_defaultness(vis, defaultness);
@@ -987,6 +994,11 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
987994
vis.visit_block(body);
988995
}
989996
vis.visit_span(span);
997+
998+
for (id, path) in define_opaque.iter_mut().flatten() {
999+
vis.visit_id(id);
1000+
vis.visit_path(path)
1001+
}
9901002
}
9911003
FnKind::Closure(binder, coroutine_kind, decl, body) => {
9921004
vis.visit_closure_binder(binder);

Diff for: compiler/rustc_ast/src/visit.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -892,14 +892,24 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
892892
_ctxt,
893893
_ident,
894894
_vis,
895-
Fn { defaultness: _, sig: FnSig { header, decl, span: _ }, generics, contract, body },
895+
Fn {
896+
defaultness: _,
897+
sig: FnSig { header, decl, span: _ },
898+
generics,
899+
contract,
900+
body,
901+
define_opaque,
902+
},
896903
) => {
897904
// Identifier and visibility are visited as a part of the item.
898905
try_visit!(visitor.visit_fn_header(header));
899906
try_visit!(visitor.visit_generics(generics));
900907
try_visit!(visitor.visit_fn_decl(decl));
901908
visit_opt!(visitor, visit_contract, contract);
902909
visit_opt!(visitor, visit_block, body);
910+
for (id, path) in define_opaque.iter().flatten() {
911+
try_visit!(visitor.visit_path(path, *id))
912+
}
903913
}
904914
FnKind::Closure(binder, coroutine_kind, decl, body) => {
905915
try_visit!(visitor.visit_closure_binder(binder));
@@ -1203,7 +1213,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
12031213
FnKind::Closure(binder, coroutine_kind, fn_decl, body),
12041214
*span,
12051215
*id
1206-
))
1216+
));
12071217
}
12081218
ExprKind::Block(block, opt_label) => {
12091219
visit_opt!(visitor, visit_label, opt_label);

Diff for: compiler/rustc_ast_lowering/src/item.rs

+46-5
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@ use rustc_ast::ptr::P;
33
use rustc_ast::visit::AssocCtxt;
44
use rustc_ast::*;
55
use rustc_errors::ErrorGuaranteed;
6-
use rustc_hir as hir;
7-
use rustc_hir::PredicateOrigin;
86
use rustc_hir::def::{DefKind, Res};
97
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
8+
use rustc_hir::{self as hir, HirId, PredicateOrigin};
109
use rustc_index::{IndexSlice, IndexVec};
1110
use rustc_middle::span_bug;
1211
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
@@ -209,6 +208,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
209208
generics,
210209
body,
211210
contract,
211+
define_opaque,
212212
..
213213
}) => {
214214
self.with_new_scopes(*fn_sig_span, |this| {
@@ -237,6 +237,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
237237
header: this.lower_fn_header(*header, hir::Safety::Safe, attrs),
238238
span: this.lower_span(*fn_sig_span),
239239
};
240+
this.lower_define_opaque(hir_id, &define_opaque);
240241
hir::ItemKind::Fn { sig, generics, body: body_id, has_body: body.is_some() }
241242
})
242243
}
@@ -779,7 +780,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
779780
);
780781
(generics, kind, expr.is_some())
781782
}
782-
AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => {
783+
AssocItemKind::Fn(box Fn { sig, generics, body: None, define_opaque, .. }) => {
783784
// FIXME(contracts): Deny contract here since it won't apply to
784785
// any impl method or callees.
785786
let names = self.lower_fn_params_to_names(&sig.decl);
@@ -791,9 +792,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
791792
sig.header.coroutine_kind,
792793
attrs,
793794
);
795+
if define_opaque.is_some() {
796+
self.dcx().span_err(
797+
i.span,
798+
"only trait methods with default bodies can define opaque types",
799+
);
800+
}
794801
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
795802
}
796-
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), contract, .. }) => {
803+
AssocItemKind::Fn(box Fn {
804+
sig,
805+
generics,
806+
body: Some(body),
807+
contract,
808+
define_opaque,
809+
..
810+
}) => {
797811
let body_id = self.lower_maybe_coroutine_body(
798812
sig.span,
799813
i.span,
@@ -812,6 +826,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
812826
sig.header.coroutine_kind,
813827
attrs,
814828
);
829+
self.lower_define_opaque(hir_id, &define_opaque);
815830
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
816831
}
817832
AssocItemKind::Type(box TyAlias { generics, where_clauses, bounds, ty, .. }) => {
@@ -911,7 +926,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
911926
hir::ImplItemKind::Const(ty, body)
912927
},
913928
),
914-
AssocItemKind::Fn(box Fn { sig, generics, body, contract, .. }) => {
929+
AssocItemKind::Fn(box Fn { sig, generics, body, contract, define_opaque, .. }) => {
915930
let body_id = self.lower_maybe_coroutine_body(
916931
sig.span,
917932
i.span,
@@ -930,6 +945,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
930945
sig.header.coroutine_kind,
931946
attrs,
932947
);
948+
self.lower_define_opaque(hir_id, &define_opaque);
933949

934950
(generics, hir::ImplItemKind::Fn(sig, body_id))
935951
}
@@ -1657,6 +1673,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
16571673
(lowered_generics, res)
16581674
}
16591675

1676+
pub(super) fn lower_define_opaque(
1677+
&mut self,
1678+
hir_id: HirId,
1679+
define_opaque: &Option<ThinVec<(NodeId, Path)>>,
1680+
) {
1681+
assert_eq!(self.define_opaque, None);
1682+
assert!(hir_id.is_owner());
1683+
let Some(define_opaque) = define_opaque.as_ref() else {
1684+
return;
1685+
};
1686+
let define_opaque = define_opaque
1687+
.iter()
1688+
// TODO: error reporting for non-local items being mentioned and tests that go through these code paths
1689+
.map(|(id, _path)| {
1690+
self.resolver
1691+
.get_partial_res(*id)
1692+
.unwrap()
1693+
.expect_full_res()
1694+
.def_id()
1695+
.expect_local()
1696+
});
1697+
let define_opaque = self.arena.alloc_from_iter(define_opaque);
1698+
self.define_opaque = Some(define_opaque);
1699+
}
1700+
16601701
pub(super) fn lower_generic_bound_predicate(
16611702
&mut self,
16621703
ident: Ident,

Diff for: compiler/rustc_ast_lowering/src/lib.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#![doc(rust_logo)]
3636
#![feature(assert_matches)]
3737
#![feature(box_patterns)]
38+
#![feature(exact_size_is_empty)]
3839
#![feature(if_let_guard)]
3940
#![feature(let_chains)]
4041
#![feature(rustdoc_internals)]
@@ -97,6 +98,8 @@ struct LoweringContext<'a, 'hir> {
9798

9899
/// Bodies inside the owner being lowered.
99100
bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
101+
/// `#[define_opaque]` attributes
102+
define_opaque: Option<&'hir [LocalDefId]>,
100103
/// Attributes inside the owner being lowered.
101104
attrs: SortedMap<hir::ItemLocalId, &'hir [hir::Attribute]>,
102105
/// Collect items that were created by lowering the current owner.
@@ -154,6 +157,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
154157

155158
// HirId handling.
156159
bodies: Vec::new(),
160+
define_opaque: None,
157161
attrs: SortedMap::default(),
158162
children: Vec::default(),
159163
contract_ensures: None,
@@ -546,6 +550,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
546550

547551
let current_attrs = std::mem::take(&mut self.attrs);
548552
let current_bodies = std::mem::take(&mut self.bodies);
553+
let current_define_opaque = std::mem::take(&mut self.define_opaque);
549554
let current_ident_and_label_to_local_id =
550555
std::mem::take(&mut self.ident_and_label_to_local_id);
551556

@@ -579,6 +584,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
579584

580585
self.attrs = current_attrs;
581586
self.bodies = current_bodies;
587+
self.define_opaque = current_define_opaque;
582588
self.ident_and_label_to_local_id = current_ident_and_label_to_local_id;
583589

584590
#[cfg(debug_assertions)]
@@ -598,6 +604,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
598604
fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {
599605
let attrs = std::mem::take(&mut self.attrs);
600606
let mut bodies = std::mem::take(&mut self.bodies);
607+
let define_opaque = std::mem::take(&mut self.define_opaque);
601608
let trait_map = std::mem::take(&mut self.trait_map);
602609

603610
#[cfg(debug_assertions)]
@@ -617,7 +624,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
617624
let num_nodes = self.item_local_id_counter.as_usize();
618625
let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes);
619626
let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies };
620-
let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash };
627+
let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash, define_opaque };
621628

622629
self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map })
623630
}

Diff for: compiler/rustc_ast_passes/src/ast_validation.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
917917
walk_list!(self, visit_attribute, &item.attrs);
918918
return; // Avoid visiting again.
919919
}
920-
ItemKind::Fn(func @ box Fn { defaultness, generics: _, sig, contract: _, body }) => {
920+
ItemKind::Fn(
921+
func
922+
@ box Fn { defaultness, generics: _, sig, contract: _, body, define_opaque: _ },
923+
) => {
921924
self.check_defaultness(item.span, *defaultness);
922925

923926
let is_intrinsic =

Diff for: compiler/rustc_ast_pretty/src/pprust/state.rs

+1-10
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ use rustc_span::edition::Edition;
2424
use rustc_span::source_map::{SourceMap, Spanned};
2525
use rustc_span::symbol::IdentPrinter;
2626
use rustc_span::{BytePos, CharPos, DUMMY_SP, FileName, Ident, Pos, Span, Symbol, kw, sym};
27-
use thin_vec::ThinVec;
2827

2928
use crate::pp::Breaks::{Consistent, Inconsistent};
3029
use crate::pp::{self, Breaks};
@@ -1978,15 +1977,7 @@ impl<'a> State<'a> {
19781977
) {
19791978
self.ibox(INDENT_UNIT);
19801979
self.print_formal_generic_params(generic_params);
1981-
let generics = ast::Generics {
1982-
params: ThinVec::new(),
1983-
where_clause: ast::WhereClause {
1984-
has_where_token: false,
1985-
predicates: ThinVec::new(),
1986-
span: DUMMY_SP,
1987-
},
1988-
span: DUMMY_SP,
1989-
};
1980+
let generics = ast::Generics::default();
19901981
let header = ast::FnHeader { safety, ext, ..ast::FnHeader::default() };
19911982
self.print_fn(decl, header, name, &generics);
19921983
self.end();

Diff for: compiler/rustc_ast_pretty/src/pprust/state/item.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,16 @@ impl<'a> State<'a> {
650650
attrs: &[ast::Attribute],
651651
func: &ast::Fn,
652652
) {
653-
let ast::Fn { defaultness, generics, sig, contract, body } = func;
653+
let ast::Fn { defaultness, generics, sig, contract, body, define_opaque } = func;
654+
655+
if let Some(define_opaque) = define_opaque {
656+
for (_, path) in define_opaque {
657+
self.word("define opaques from ");
658+
self.print_path(path, false, 0);
659+
self.word(",");
660+
}
661+
}
662+
654663
if body.is_some() {
655664
self.head("");
656665
}
@@ -698,7 +707,7 @@ impl<'a> State<'a> {
698707
}
699708
self.print_generic_params(&generics.params);
700709
self.print_fn_params_and_ret(decl, false);
701-
self.print_where_clause(&generics.where_clause)
710+
self.print_where_clause(&generics.where_clause);
702711
}
703712

704713
pub(crate) fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl, is_closure: bool) {

Diff for: compiler/rustc_borrowck/src/type_check/opaque_types.rs

+1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ pub(super) fn take_opaques_and_register_member_constraints<'tcx>(
180180
/// // Equivalent to:
181181
/// # mod dummy { use super::*;
182182
/// type FooReturn<'a, T> = impl Foo<'a>;
183+
/// #[define_opaque(FooReturn)]
183184
/// fn foo<'a, T>(x: &'a u32, y: T) -> FooReturn<'a, T> {
184185
/// (x, y)
185186
/// }

Diff for: compiler/rustc_builtin_macros/src/alloc_error_handler.rs

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
8888
generics: Generics::default(),
8989
contract: None,
9090
body,
91+
define_opaque: None,
9192
}));
9293

9394
let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)];

Diff for: compiler/rustc_builtin_macros/src/autodiff.rs

+1
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ mod llvm_enzyme {
247247
generics: Generics::default(),
248248
contract: None,
249249
body: Some(d_body),
250+
define_opaque: None,
250251
});
251252
let mut rustc_ad_attr =
252253
P(ast::NormalAttr::from_ident(Ident::with_dummy_span(sym::rustc_autodiff)));

0 commit comments

Comments
 (0)