Skip to content

Commit fd127a3

Browse files
committed
Auto merge of #135031 - RalfJung:intrinsics-without-body, r=oli-obk
rustc_intrinsic: support functions without body We synthesize a HIR body `loop {}` but such bodyless intrinsics. Most of the diff is due to turning `ItemKind::Fn` into a brace (named-field) enum variant, because it carries a `bool`-typed field now. This is to remember whether the function has a body. MIR building panics to avoid ever translating the fake `loop {}` body, and the intrinsic logic uses the lack of a body to implicitly mark that intrinsic as must-be-overridden. I first tried actually having no body rather than generating the fake body, but there's a *lot* of code that assumes that all function items have HIR and MIR, so this didn't work very well. Then I noticed that even `rustc_intrinsic_must_be_overridden` intrinsics have MIR generated (they are filled with an `Unreachable` terminator) so I guess I am not the first to discover this. ;) r? `@oli-obk`
2 parents f17cf74 + 3cd3649 commit fd127a3

File tree

81 files changed

+272
-175
lines changed

Some content is hidden

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

81 files changed

+272
-175
lines changed

compiler/rustc_ast_lowering/src/item.rs

+44-24
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
222222
decl,
223223
coroutine_kind,
224224
body.as_deref(),
225+
attrs,
225226
);
226227

227228
let itctx = ImplTraitContext::Universal;
@@ -233,7 +234,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
233234
header: this.lower_fn_header(*header, hir::Safety::Safe),
234235
span: this.lower_span(*fn_sig_span),
235236
};
236-
hir::ItemKind::Fn(sig, generics, body_id)
237+
hir::ItemKind::Fn { sig, generics, body: body_id, has_body: body.is_some() }
237238
})
238239
}
239240
ItemKind::Mod(_, mod_kind) => match mod_kind {
@@ -435,11 +436,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
435436
}
436437
ItemKind::Delegation(box delegation) => {
437438
let delegation_results = self.lower_delegation(delegation, id);
438-
hir::ItemKind::Fn(
439-
delegation_results.sig,
440-
delegation_results.generics,
441-
delegation_results.body_id,
442-
)
439+
hir::ItemKind::Fn {
440+
sig: delegation_results.sig,
441+
generics: delegation_results.generics,
442+
body: delegation_results.body_id,
443+
has_body: true,
444+
}
443445
}
444446
ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {
445447
panic!("macros should have been expanded by now")
@@ -747,7 +749,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
747749

748750
fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
749751
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
750-
self.lower_attrs(hir_id, &i.attrs);
752+
let attrs = self.lower_attrs(hir_id, &i.attrs);
751753
let trait_item_def_id = hir_id.expect_owner();
752754

753755
let (generics, kind, has_default) = match &i.kind {
@@ -785,6 +787,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
785787
&sig.decl,
786788
sig.header.coroutine_kind,
787789
Some(body),
790+
attrs,
788791
);
789792
let (generics, sig) = self.lower_method_sig(
790793
generics,
@@ -877,7 +880,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
877880
let has_value = true;
878881
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
879882
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
880-
self.lower_attrs(hir_id, &i.attrs);
883+
let attrs = self.lower_attrs(hir_id, &i.attrs);
881884

882885
let (generics, kind) = match &i.kind {
883886
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
@@ -900,6 +903,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
900903
&sig.decl,
901904
sig.header.coroutine_kind,
902905
body.as_deref(),
906+
attrs,
903907
);
904908
let (generics, sig) = self.lower_method_sig(
905909
generics,
@@ -1054,20 +1058,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
10541058
})
10551059
}
10561060

1057-
fn lower_fn_body_block(
1058-
&mut self,
1059-
span: Span,
1060-
decl: &FnDecl,
1061-
body: Option<&Block>,
1062-
) -> hir::BodyId {
1063-
self.lower_fn_body(decl, |this| this.lower_block_expr_opt(span, body))
1064-
}
1065-
1066-
fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr<'hir> {
1067-
match block {
1068-
Some(block) => self.lower_block_expr(block),
1069-
None => self.expr_err(span, self.dcx().has_errors().unwrap()),
1070-
}
1061+
fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId {
1062+
self.lower_fn_body(decl, |this| this.lower_block_expr(body))
10711063
}
10721064

10731065
pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId {
@@ -1089,9 +1081,37 @@ impl<'hir> LoweringContext<'_, 'hir> {
10891081
decl: &FnDecl,
10901082
coroutine_kind: Option<CoroutineKind>,
10911083
body: Option<&Block>,
1084+
attrs: &'hir [hir::Attribute],
10921085
) -> hir::BodyId {
1093-
let (Some(coroutine_kind), Some(body)) = (coroutine_kind, body) else {
1094-
return self.lower_fn_body_block(span, decl, body);
1086+
let Some(body) = body else {
1087+
// Functions without a body are an error, except if this is an intrinsic. For those we
1088+
// create a fake body so that the entire rest of the compiler doesn't have to deal with
1089+
// this as a special case.
1090+
return self.lower_fn_body(decl, |this| {
1091+
if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic) {
1092+
let empty_block = hir::Block {
1093+
hir_id: this.next_id(),
1094+
stmts: &[],
1095+
expr: None,
1096+
rules: hir::BlockCheckMode::DefaultBlock,
1097+
span,
1098+
targeted_by_break: false,
1099+
};
1100+
let loop_ = hir::ExprKind::Loop(
1101+
this.arena.alloc(empty_block),
1102+
None,
1103+
hir::LoopSource::Loop,
1104+
span,
1105+
);
1106+
hir::Expr { hir_id: this.next_id(), kind: loop_, span }
1107+
} else {
1108+
this.expr_err(span, this.dcx().has_errors().unwrap())
1109+
}
1110+
});
1111+
};
1112+
let Some(coroutine_kind) = coroutine_kind else {
1113+
// Typical case: not a coroutine.
1114+
return self.lower_fn_body_block(decl, body);
10951115
};
10961116
self.lower_body(|this| {
10971117
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(

compiler/rustc_ast_passes/src/ast_validation.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -920,7 +920,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
920920
ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => {
921921
self.check_defaultness(item.span, *defaultness);
922922

923-
if body.is_none() {
923+
let is_intrinsic =
924+
item.attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic);
925+
if body.is_none() && !is_intrinsic {
924926
self.dcx().emit_err(errors::FnWithoutBody {
925927
span: item.span,
926928
replace_span: self.ending_semi_or_hi(item.span),

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
981981

982982
let arg = match hir.get_if_local(callee_def_id) {
983983
Some(
984-
hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. })
984+
hir::Node::Item(hir::Item {
985+
ident, kind: hir::ItemKind::Fn { sig, .. }, ..
986+
})
985987
| hir::Node::TraitItem(hir::TraitItem {
986988
ident,
987989
kind: hir::TraitItemKind::Fn(sig, _),
@@ -1020,7 +1022,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
10201022
// ...otherwise we are probably in the tail expression of the function, point at the
10211023
// return type.
10221024
match self.infcx.tcx.hir_node_by_def_id(hir.get_parent_item(fn_call_id).def_id) {
1023-
hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. })
1025+
hir::Node::Item(hir::Item {
1026+
ident, kind: hir::ItemKind::Fn { sig, .. }, ..
1027+
})
10241028
| hir::Node::TraitItem(hir::TraitItem {
10251029
ident,
10261030
kind: hir::TraitItemKind::Fn(sig, _),

compiler/rustc_const_eval/src/interpret/call.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
566566
| ty::InstanceKind::ThreadLocalShim(..)
567567
| ty::InstanceKind::AsyncDropGlueCtorShim(..)
568568
| ty::InstanceKind::Item(_) => {
569-
// We need MIR for this fn
569+
// We need MIR for this fn.
570+
// Note that this can be an intrinsic, if we are executing its fallback body.
570571
let Some((body, instance)) = M::find_mir_or_eval_fn(
571572
self,
572573
instance,

compiler/rustc_feature/src/builtin_attrs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
10131013
),
10141014
gated!(
10151015
rustc_intrinsic, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,
1016-
"the `#[rustc_intrinsic]` attribute is used to declare intrinsics with function bodies",
1016+
"the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items",
10171017
),
10181018
gated!(
10191019
rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,

compiler/rustc_hir/src/hir.rs

+19-11
Original file line numberDiff line numberDiff line change
@@ -3640,7 +3640,7 @@ impl<'hir> Item<'hir> {
36403640
ItemKind::Const(ty, generics, body), (ty, generics, *body);
36413641

36423642
expect_fn, (&FnSig<'hir>, &'hir Generics<'hir>, BodyId),
3643-
ItemKind::Fn(sig, generics, body), (sig, generics, *body);
3643+
ItemKind::Fn { sig, generics, body, .. }, (sig, generics, *body);
36443644

36453645
expect_macro, (&ast::MacroDef, MacroKind), ItemKind::Macro(def, mk), (def, *mk);
36463646

@@ -3768,7 +3768,15 @@ pub enum ItemKind<'hir> {
37683768
/// A `const` item.
37693769
Const(&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId),
37703770
/// A function declaration.
3771-
Fn(FnSig<'hir>, &'hir Generics<'hir>, BodyId),
3771+
Fn {
3772+
sig: FnSig<'hir>,
3773+
generics: &'hir Generics<'hir>,
3774+
body: BodyId,
3775+
/// Whether this function actually has a body.
3776+
/// For functions without a body, `body` is synthesized (to avoid ICEs all over the
3777+
/// compiler), but that code should never be translated.
3778+
has_body: bool,
3779+
},
37723780
/// A MBE macro definition (`macro_rules!` or `macro`).
37733781
Macro(&'hir ast::MacroDef, MacroKind),
37743782
/// A module.
@@ -3819,7 +3827,7 @@ pub struct Impl<'hir> {
38193827
impl ItemKind<'_> {
38203828
pub fn generics(&self) -> Option<&Generics<'_>> {
38213829
Some(match *self {
3822-
ItemKind::Fn(_, ref generics, _)
3830+
ItemKind::Fn { ref generics, .. }
38233831
| ItemKind::TyAlias(_, ref generics)
38243832
| ItemKind::Const(_, ref generics, _)
38253833
| ItemKind::Enum(_, ref generics)
@@ -3838,7 +3846,7 @@ impl ItemKind<'_> {
38383846
ItemKind::Use(..) => "`use` import",
38393847
ItemKind::Static(..) => "static item",
38403848
ItemKind::Const(..) => "constant item",
3841-
ItemKind::Fn(..) => "function",
3849+
ItemKind::Fn { .. } => "function",
38423850
ItemKind::Macro(..) => "macro",
38433851
ItemKind::Mod(..) => "module",
38443852
ItemKind::ForeignMod { .. } => "extern block",
@@ -4004,7 +4012,7 @@ impl<'hir> OwnerNode<'hir> {
40044012
match self {
40054013
OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
40064014
| OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
4007-
| OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
4015+
| OwnerNode::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
40084016
| OwnerNode::ForeignItem(ForeignItem {
40094017
kind: ForeignItemKind::Fn(fn_sig, _, _), ..
40104018
}) => Some(fn_sig),
@@ -4016,7 +4024,7 @@ impl<'hir> OwnerNode<'hir> {
40164024
match self {
40174025
OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
40184026
| OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
4019-
| OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
4027+
| OwnerNode::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
40204028
| OwnerNode::ForeignItem(ForeignItem {
40214029
kind: ForeignItemKind::Fn(fn_sig, _, _), ..
40224030
}) => Some(fn_sig.decl),
@@ -4030,7 +4038,7 @@ impl<'hir> OwnerNode<'hir> {
40304038
kind:
40314039
ItemKind::Static(_, _, body)
40324040
| ItemKind::Const(_, _, body)
4033-
| ItemKind::Fn(_, _, body),
4041+
| ItemKind::Fn { body, .. },
40344042
..
40354043
})
40364044
| OwnerNode::TraitItem(TraitItem {
@@ -4206,7 +4214,7 @@ impl<'hir> Node<'hir> {
42064214
match self {
42074215
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
42084216
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
4209-
| Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
4217+
| Node::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
42104218
| Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => {
42114219
Some(fn_sig.decl)
42124220
}
@@ -4236,7 +4244,7 @@ impl<'hir> Node<'hir> {
42364244
match self {
42374245
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
42384246
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
4239-
| Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
4247+
| Node::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
42404248
| Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => {
42414249
Some(fn_sig)
42424250
}
@@ -4281,7 +4289,7 @@ impl<'hir> Node<'hir> {
42814289
Node::Item(Item {
42824290
owner_id,
42834291
kind:
4284-
ItemKind::Const(_, _, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body),
4292+
ItemKind::Const(_, _, body) | ItemKind::Static(.., body) | ItemKind::Fn { body, .. },
42854293
..
42864294
})
42874295
| Node::TraitItem(TraitItem {
@@ -4338,7 +4346,7 @@ impl<'hir> Node<'hir> {
43384346
pub fn fn_kind(self) -> Option<FnKind<'hir>> {
43394347
match self {
43404348
Node::Item(i) => match i.kind {
4341-
ItemKind::Fn(ref sig, ref generics, _) => {
4349+
ItemKind::Fn { sig, generics, .. } => {
43424350
Some(FnKind::ItemFn(i.ident, generics, sig.header))
43434351
}
43444352
_ => None,

compiler/rustc_hir/src/intravisit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
509509
try_visit!(visitor.visit_generics(generics));
510510
try_visit!(visitor.visit_nested_body(body));
511511
}
512-
ItemKind::Fn(ref sig, ref generics, body_id) => {
512+
ItemKind::Fn { sig, generics, body: body_id, .. } => {
513513
try_visit!(visitor.visit_id(item.hir_id()));
514514
try_visit!(visitor.visit_fn(
515515
FnKind::ItemFn(item.ident, generics, sig.header),

compiler/rustc_hir/src/target.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ impl Target {
106106
ItemKind::Use(..) => Target::Use,
107107
ItemKind::Static { .. } => Target::Static,
108108
ItemKind::Const(..) => Target::Const,
109-
ItemKind::Fn(..) => Target::Fn,
109+
ItemKind::Fn { .. } => Target::Fn,
110110
ItemKind::Macro(..) => Target::MacroDef,
111111
ItemKind::Mod(..) => Target::Mod,
112112
ItemKind::ForeignMod { .. } => Target::ForeignMod,

compiler/rustc_hir_analysis/src/check/entry.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
4444
return None;
4545
}
4646
match tcx.hir_node_by_def_id(def_id.expect_local()) {
47-
Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => {
47+
Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. }) => {
4848
generics.params.is_empty().not().then_some(generics.span)
4949
}
5050
_ => {
@@ -58,7 +58,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
5858
return None;
5959
}
6060
match tcx.hir_node_by_def_id(def_id.expect_local()) {
61-
Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => {
61+
Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. }) => {
6262
Some(generics.where_clause_span)
6363
}
6464
_ => {
@@ -79,7 +79,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
7979
return None;
8080
}
8181
match tcx.hir_node_by_def_id(def_id.expect_local()) {
82-
Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. }) => {
82+
Node::Item(hir::Item { kind: hir::ItemKind::Fn { sig: fn_sig, .. }, .. }) => {
8383
Some(fn_sig.decl.output.span())
8484
}
8585
_ => {
@@ -201,7 +201,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
201201
match start_t.kind() {
202202
ty::FnDef(..) => {
203203
if let Node::Item(it) = tcx.hir_node(start_id) {
204-
if let hir::ItemKind::Fn(sig, generics, _) = &it.kind {
204+
if let hir::ItemKind::Fn { sig, generics, .. } = &it.kind {
205205
let mut error = false;
206206
if !generics.params.is_empty() {
207207
tcx.dcx().emit_err(errors::StartFunctionParameters { span: generics.span });

compiler/rustc_hir_analysis/src/check/intrinsic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ fn equate_intrinsic_type<'tcx>(
2626
sig: ty::PolyFnSig<'tcx>,
2727
) {
2828
let (generics, span) = match tcx.hir_node_by_def_id(def_id) {
29-
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
29+
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. })
3030
| hir::Node::ForeignItem(hir::ForeignItem {
3131
kind: hir::ForeignItemKind::Fn(_, _, generics),
3232
..

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
293293
}
294294
res
295295
}
296-
hir::ItemKind::Fn(ref sig, ..) => {
296+
hir::ItemKind::Fn { sig, .. } => {
297297
check_item_fn(tcx, def_id, item.ident, item.span, sig.decl)
298298
}
299299
hir::ItemKind::Static(ty, ..) => {

compiler/rustc_hir_analysis/src/collect.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
795795
}
796796
}
797797

798-
hir::ItemKind::Fn(..) => {
798+
hir::ItemKind::Fn { .. } => {
799799
tcx.ensure().generics_of(def_id);
800800
tcx.ensure().type_of(def_id);
801801
tcx.ensure().predicates_of(def_id);
@@ -1325,7 +1325,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
13251325
generics,
13261326
..
13271327
})
1328-
| Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), .. }) => {
1328+
| Item(hir::Item { kind: ItemKind::Fn { sig, generics, .. }, .. }) => {
13291329
lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
13301330
}
13311331

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ pub(super) fn const_conditions<'tcx>(
969969
{
970970
Node::Item(item) => match item.kind {
971971
hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
972-
hir::ItemKind::Fn(_, generics, _) => (generics, None, false),
972+
hir::ItemKind::Fn { generics, .. } => (generics, None, false),
973973
hir::ItemKind::Trait(_, _, generics, supertraits, _) => {
974974
(generics, Some((item.owner_id.def_id, supertraits)), false)
975975
}

0 commit comments

Comments
 (0)