Skip to content

Commit 6650252

Browse files
committed
Auto merge of #128440 - oli-obk:defines, r=lcnr
Add `#[define_opaques]` attribute and require it for all type-alias-impl-trait sites that register a hidden type Instead of relying on the signature of items to decide whether they are constraining an opaque type, the opaque types that the item constrains must be explicitly listed. A previous version of this PR used an actual attribute, but had to keep the resolved `DefId`s in a side table. Now we just lower to fields in the AST that have no surface syntax, instead a builtin attribute macro fills in those fields where applicable. Note that for convenience referencing opaque types in associated types from associated methods on the same impl will not require an attribute. If that causes problems `#[defines()]` can be used to overwrite the default of searching for opaques in the signature. One wart of this design is that closures and static items do not have generics. So since I stored the opaques in the generics of functions, consts and methods, I would need to add a custom field to closures and statics to track this information. During a T-types discussion we decided to just not do this for now. fixes #131298
2 parents f2d69d5 + 69a1bb8 commit 6650252

File tree

666 files changed

+2912
-2469
lines changed

Some content is hidden

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

666 files changed

+2912
-2469
lines changed

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",

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);

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);

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);

compiler/rustc_ast_lowering/src/item.rs

+50-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,35 @@ 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.iter().filter_map(|(id, path)| {
1687+
let res = self.resolver.get_partial_res(*id).unwrap();
1688+
let Some(did) = res.expect_full_res().opt_def_id() else {
1689+
self.dcx().span_delayed_bug(path.span, "should have errored in resolve");
1690+
return None;
1691+
};
1692+
let Some(did) = did.as_local() else {
1693+
self.dcx().span_err(
1694+
path.span,
1695+
"only opaque types defined in the local crate can be defined",
1696+
);
1697+
return None;
1698+
};
1699+
Some((self.lower_span(path.span), did))
1700+
});
1701+
let define_opaque = self.arena.alloc_from_iter(define_opaque);
1702+
self.define_opaque = Some(define_opaque);
1703+
}
1704+
16601705
pub(super) fn lower_generic_bound_predicate(
16611706
&mut self,
16621707
ident: Ident,

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)]
@@ -98,6 +99,8 @@ struct LoweringContext<'a, 'hir> {
9899

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

156159
// HirId handling.
157160
bodies: Vec::new(),
161+
define_opaque: None,
158162
attrs: SortedMap::default(),
159163
children: Vec::default(),
160164
contract_ensures: None,
@@ -547,6 +551,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
547551

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

@@ -580,6 +585,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
580585

581586
self.attrs = current_attrs;
582587
self.bodies = current_bodies;
588+
self.define_opaque = current_define_opaque;
583589
self.ident_and_label_to_local_id = current_ident_and_label_to_local_id;
584590

585591
#[cfg(debug_assertions)]
@@ -599,6 +605,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
599605
fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {
600606
let attrs = std::mem::take(&mut self.attrs);
601607
let mut bodies = std::mem::take(&mut self.bodies);
608+
let define_opaque = std::mem::take(&mut self.define_opaque);
602609
let trait_map = std::mem::take(&mut self.trait_map);
603610

604611
#[cfg(debug_assertions)]
@@ -618,7 +625,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
618625
let num_nodes = self.item_local_id_counter.as_usize();
619626
let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes);
620627
let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies };
621-
let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash };
628+
let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash, define_opaque };
622629

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

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 =

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();

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) {

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
/// }

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)];

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)