Skip to content

Commit f8df298

Browse files
Allow defining opaques in statics and consts
1 parent 2bf0c2d commit f8df298

File tree

17 files changed

+315
-163
lines changed

17 files changed

+315
-163
lines changed

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

+2
Original file line numberDiff line numberDiff line change
@@ -3535,6 +3535,7 @@ pub struct StaticItem {
35353535
pub safety: Safety,
35363536
pub mutability: Mutability,
35373537
pub expr: Option<P<Expr>>,
3538+
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
35383539
}
35393540

35403541
#[derive(Clone, Encodable, Decodable, Debug)]
@@ -3543,6 +3544,7 @@ pub struct ConstItem {
35433544
pub generics: Generics,
35443545
pub ty: P<Ty>,
35453546
pub expr: Option<P<Expr>>,
3547+
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
35463548
}
35473549

35483550
// Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`.

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

+38-16
Original file line numberDiff line numberDiff line change
@@ -987,10 +987,7 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
987987
}
988988
vis.visit_span(span);
989989

990-
for (id, path) in define_opaque.iter_mut().flatten() {
991-
vis.visit_id(id);
992-
vis.visit_path(path)
993-
}
990+
walk_define_opaques(vis, define_opaque);
994991
}
995992
FnKind::Closure(binder, coroutine_kind, decl, body) => {
996993
vis.visit_closure_binder(binder);
@@ -1258,12 +1255,19 @@ impl WalkItemKind for ItemKind {
12581255
match self {
12591256
ItemKind::ExternCrate(_orig_name) => {}
12601257
ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
1261-
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
1258+
ItemKind::Static(box StaticItem {
1259+
ty,
1260+
safety: _,
1261+
mutability: _,
1262+
expr,
1263+
define_opaque,
1264+
}) => {
12621265
vis.visit_ty(ty);
12631266
visit_opt(expr, |expr| vis.visit_expr(expr));
1267+
walk_define_opaques(vis, define_opaque);
12641268
}
12651269
ItemKind::Const(item) => {
1266-
visit_const_item(item, vis);
1270+
walk_const_item(vis, item);
12671271
}
12681272
ItemKind::Fn(func) => {
12691273
vis.visit_fn(FnKind::Fn(FnCtxt::Free, ident, visibility, &mut *func), span, id);
@@ -1382,7 +1386,7 @@ impl WalkItemKind for AssocItemKind {
13821386
) {
13831387
match self {
13841388
AssocItemKind::Const(item) => {
1385-
visit_const_item(item, visitor);
1389+
walk_const_item(visitor, item);
13861390
}
13871391
AssocItemKind::Fn(func) => {
13881392
visitor.visit_fn(
@@ -1442,14 +1446,13 @@ impl WalkItemKind for AssocItemKind {
14421446
}
14431447
}
14441448

1445-
fn visit_const_item<T: MutVisitor>(
1446-
ConstItem { defaultness, generics, ty, expr }: &mut ConstItem,
1447-
visitor: &mut T,
1448-
) {
1449-
visit_defaultness(visitor, defaultness);
1450-
visitor.visit_generics(generics);
1451-
visitor.visit_ty(ty);
1452-
visit_opt(expr, |expr| visitor.visit_expr(expr));
1449+
fn walk_const_item<T: MutVisitor>(vis: &mut T, item: &mut ConstItem) {
1450+
let ConstItem { defaultness, generics, ty, expr, define_opaque } = item;
1451+
visit_defaultness(vis, defaultness);
1452+
vis.visit_generics(generics);
1453+
vis.visit_ty(ty);
1454+
visit_opt(expr, |expr| vis.visit_expr(expr));
1455+
walk_define_opaques(vis, define_opaque);
14531456
}
14541457

14551458
fn walk_fn_header<T: MutVisitor>(vis: &mut T, header: &mut FnHeader) {
@@ -1526,9 +1529,16 @@ impl WalkItemKind for ForeignItemKind {
15261529
visitor: &mut impl MutVisitor,
15271530
) {
15281531
match self {
1529-
ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => {
1532+
ForeignItemKind::Static(box StaticItem {
1533+
ty,
1534+
mutability: _,
1535+
expr,
1536+
safety: _,
1537+
define_opaque,
1538+
}) => {
15301539
visitor.visit_ty(ty);
15311540
visit_opt(expr, |expr| visitor.visit_expr(expr));
1541+
walk_define_opaques(visitor, define_opaque);
15321542
}
15331543
ForeignItemKind::Fn(func) => {
15341544
visitor.visit_fn(
@@ -1929,6 +1939,18 @@ fn walk_capture_by<T: MutVisitor>(vis: &mut T, capture_by: &mut CaptureBy) {
19291939
}
19301940
}
19311941

1942+
fn walk_define_opaques<T: MutVisitor>(
1943+
vis: &mut T,
1944+
define_opaque: &mut Option<ThinVec<(NodeId, Path)>>,
1945+
) {
1946+
if let Some(define_opaque) = define_opaque {
1947+
for (id, path) in define_opaque {
1948+
vis.visit_id(id);
1949+
vis.visit_path(path)
1950+
}
1951+
}
1952+
}
1953+
19321954
/// Some value for the AST node that is valid but possibly meaningless. Similar
19331955
/// to `Default` but not intended for wide use. The value will never be used
19341956
/// meaningfully, it exists just to support unwinding in `visit_clobber` in the

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

+46-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
pub use rustc_ast_ir::visit::VisitorResult;
1717
pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
1818
use rustc_span::{Ident, Span};
19+
use thin_vec::ThinVec;
1920

2021
use crate::ast::*;
2122
use crate::ptr::P;
@@ -371,14 +372,28 @@ impl WalkItemKind for ItemKind {
371372
match self {
372373
ItemKind::ExternCrate(_rename) => {}
373374
ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)),
374-
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
375+
ItemKind::Static(box StaticItem {
376+
ty,
377+
safety: _,
378+
mutability: _,
379+
expr,
380+
define_opaque,
381+
}) => {
375382
try_visit!(visitor.visit_ty(ty));
376383
visit_opt!(visitor, visit_expr, expr);
384+
try_visit!(walk_define_opaques(visitor, define_opaque));
377385
}
378-
ItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
386+
ItemKind::Const(box ConstItem {
387+
defaultness: _,
388+
generics,
389+
ty,
390+
expr,
391+
define_opaque,
392+
}) => {
379393
try_visit!(visitor.visit_generics(generics));
380394
try_visit!(visitor.visit_ty(ty));
381395
visit_opt!(visitor, visit_expr, expr);
396+
try_visit!(walk_define_opaques(visitor, define_opaque));
382397
}
383398
ItemKind::Fn(func) => {
384399
let kind = FnKind::Fn(FnCtxt::Free, ident, vis, &*func);
@@ -729,9 +744,16 @@ impl WalkItemKind for ForeignItemKind {
729744
visitor: &mut V,
730745
) -> V::Result {
731746
match self {
732-
ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => {
747+
ForeignItemKind::Static(box StaticItem {
748+
ty,
749+
mutability: _,
750+
expr,
751+
safety: _,
752+
define_opaque,
753+
}) => {
733754
try_visit!(visitor.visit_ty(ty));
734755
visit_opt!(visitor, visit_expr, expr);
756+
try_visit!(walk_define_opaques(visitor, define_opaque));
735757
}
736758
ForeignItemKind::Fn(func) => {
737759
let kind = FnKind::Fn(FnCtxt::Foreign, ident, vis, &*func);
@@ -907,9 +929,7 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
907929
try_visit!(visitor.visit_fn_decl(decl));
908930
visit_opt!(visitor, visit_contract, contract);
909931
visit_opt!(visitor, visit_block, body);
910-
for (id, path) in define_opaque.iter().flatten() {
911-
try_visit!(visitor.visit_path(path, *id))
912-
}
932+
try_visit!(walk_define_opaques(visitor, define_opaque));
913933
}
914934
FnKind::Closure(binder, coroutine_kind, decl, body) => {
915935
try_visit!(visitor.visit_closure_binder(binder));
@@ -933,10 +953,17 @@ impl WalkItemKind for AssocItemKind {
933953
visitor: &mut V,
934954
) -> V::Result {
935955
match self {
936-
AssocItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
956+
AssocItemKind::Const(box ConstItem {
957+
defaultness: _,
958+
generics,
959+
ty,
960+
expr,
961+
define_opaque,
962+
}) => {
937963
try_visit!(visitor.visit_generics(generics));
938964
try_visit!(visitor.visit_ty(ty));
939965
visit_opt!(visitor, visit_expr, expr);
966+
try_visit!(walk_define_opaques(visitor, define_opaque));
940967
}
941968
AssocItemKind::Fn(func) => {
942969
let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, vis, &*func);
@@ -1337,3 +1364,15 @@ pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -
13371364
}
13381365
V::Result::output()
13391366
}
1367+
1368+
fn walk_define_opaques<'a, V: Visitor<'a>>(
1369+
visitor: &mut V,
1370+
define_opaque: &'a Option<ThinVec<(NodeId, Path)>>,
1371+
) -> V::Result {
1372+
if let Some(define_opaque) = define_opaque {
1373+
for (id, path) in define_opaque {
1374+
try_visit!(visitor.visit_path(path, *id));
1375+
}
1376+
}
1377+
V::Result::output()
1378+
}

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

+54-18
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
188188

189189
self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs)
190190
}
191-
ItemKind::Static(box ast::StaticItem { ty: t, safety: _, mutability: m, expr: e }) => {
191+
ItemKind::Static(box ast::StaticItem {
192+
ty: t,
193+
safety: _,
194+
mutability: m,
195+
expr: e,
196+
define_opaque,
197+
}) => {
192198
debug_assert_ne!(ident.name, kw::Empty);
193199
let ident = self.lower_ident(ident);
194200
let (ty, body_id) =
195201
self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
202+
self.lower_define_opaque(hir_id, define_opaque);
196203
hir::ItemKind::Static(ident, ty, *m, body_id)
197204
}
198-
ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
205+
ItemKind::Const(box ast::ConstItem { generics, ty, expr, define_opaque, .. }) => {
199206
debug_assert_ne!(ident.name, kw::Empty);
200207
let ident = self.lower_ident(ident);
201208
let (generics, (ty, body_id)) = self.lower_generics(
@@ -206,6 +213,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
206213
this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy)
207214
},
208215
);
216+
self.lower_define_opaque(hir_id, &define_opaque);
209217
hir::ItemKind::Const(ident, ty, generics, body_id)
210218
}
211219
ItemKind::Fn(box Fn {
@@ -243,7 +251,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
243251
header: this.lower_fn_header(*header, hir::Safety::Safe, attrs),
244252
span: this.lower_span(*fn_sig_span),
245253
};
246-
this.lower_define_opaque(hir_id, &define_opaque);
254+
this.lower_define_opaque(hir_id, define_opaque);
247255
let ident = this.lower_ident(ident);
248256
hir::ItemKind::Fn {
249257
ident,
@@ -662,7 +670,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
662670
owner_id,
663671
ident: self.lower_ident(i.ident),
664672
kind: match &i.kind {
665-
ForeignItemKind::Fn(box Fn { sig, generics, .. }) => {
673+
ForeignItemKind::Fn(box Fn { sig, generics, define_opaque, .. }) => {
666674
let fdec = &sig.decl;
667675
let itctx = ImplTraitContext::Universal;
668676
let (generics, (decl, fn_args)) =
@@ -683,17 +691,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
683691
// Unmarked safety in unsafe block defaults to unsafe.
684692
let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs);
685693

694+
if define_opaque.is_some() {
695+
self.dcx().span_err(i.span, "foreign functions cannot define opaque types");
696+
}
697+
686698
hir::ForeignItemKind::Fn(
687699
hir::FnSig { header, decl, span: self.lower_span(sig.span) },
688700
fn_args,
689701
generics,
690702
)
691703
}
692-
ForeignItemKind::Static(box StaticItem { ty, mutability, expr: _, safety }) => {
704+
ForeignItemKind::Static(box StaticItem {
705+
ty,
706+
mutability,
707+
expr: _,
708+
safety,
709+
define_opaque,
710+
}) => {
693711
let ty = self
694712
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
695713
let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
696714

715+
if define_opaque.is_some() {
716+
self.dcx().span_err(i.span, "foreign statics cannot define opaque types");
717+
}
718+
697719
hir::ForeignItemKind::Static(ty, *mutability, safety)
698720
}
699721
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
@@ -801,7 +823,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
801823
let trait_item_def_id = hir_id.expect_owner();
802824

803825
let (generics, kind, has_default) = match &i.kind {
804-
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => {
826+
AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => {
805827
let (generics, kind) = self.lower_generics(
806828
generics,
807829
i.id,
@@ -814,6 +836,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
814836
hir::TraitItemKind::Const(ty, body)
815837
},
816838
);
839+
840+
if define_opaque.is_some() {
841+
if expr.is_some() {
842+
self.lower_define_opaque(hir_id, &define_opaque);
843+
} else {
844+
self.dcx().span_err(
845+
i.span,
846+
"only trait consts with default bodies can define opaque types",
847+
);
848+
}
849+
}
850+
817851
(generics, kind, expr.is_some())
818852
}
819853
AssocItemKind::Fn(box Fn { sig, generics, body: None, define_opaque, .. }) => {
@@ -951,18 +985,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
951985
let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
952986

953987
let (generics, kind) = match &i.kind {
954-
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
955-
generics,
956-
i.id,
957-
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
958-
|this| {
959-
let ty =
960-
this.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
961-
let body = this.lower_const_body(i.span, expr.as_deref());
962-
963-
hir::ImplItemKind::Const(ty, body)
964-
},
965-
),
988+
AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => self
989+
.lower_generics(
990+
generics,
991+
i.id,
992+
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
993+
|this| {
994+
let ty = this
995+
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
996+
let body = this.lower_const_body(i.span, expr.as_deref());
997+
this.lower_define_opaque(hir_id, &define_opaque);
998+
999+
hir::ImplItemKind::Const(ty, body)
1000+
},
1001+
),
9661002
AssocItemKind::Fn(box Fn { sig, generics, body, contract, define_opaque, .. }) => {
9671003
let body_id = self.lower_maybe_coroutine_body(
9681004
sig.span,

0 commit comments

Comments
 (0)