Skip to content

Commit f347697

Browse files
Allow defining opaques in statics and consts
1 parent 25de0ca commit f347697

File tree

16 files changed

+307
-163
lines changed

16 files changed

+307
-163
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 2 additions & 0 deletions
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`.

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 38 additions & 16 deletions
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

compiler/rustc_ast/src/visit.rs

Lines changed: 46 additions & 7 deletions
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+
}

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
191191

192192
self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs)
193193
}
194-
ItemKind::Static(box ast::StaticItem { ty: t, safety: _, mutability: m, expr: e }) => {
194+
ItemKind::Static(box ast::StaticItem {
195+
ty: t,
196+
safety: _,
197+
mutability: m,
198+
expr: e,
199+
define_opaque,
200+
}) => {
195201
debug_assert_ne!(ident.name, kw::Empty);
196202
let ident = self.lower_ident(ident);
197203
let (ty, body_id) =
198204
self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
205+
self.lower_define_opaque(hir_id, define_opaque);
199206
hir::ItemKind::Static(ident, ty, *m, body_id)
200207
}
201-
ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
208+
ItemKind::Const(box ast::ConstItem { generics, ty, expr, define_opaque, .. }) => {
202209
debug_assert_ne!(ident.name, kw::Empty);
203210
let ident = self.lower_ident(ident);
204211
let (generics, (ty, body_id)) = self.lower_generics(
@@ -209,6 +216,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
209216
this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy)
210217
},
211218
);
219+
self.lower_define_opaque(hir_id, &define_opaque);
212220
hir::ItemKind::Const(ident, ty, generics, body_id)
213221
}
214222
ItemKind::Fn(box Fn {
@@ -246,7 +254,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
246254
header: this.lower_fn_header(*header, hir::Safety::Safe, attrs),
247255
span: this.lower_span(*fn_sig_span),
248256
};
249-
this.lower_define_opaque(hir_id, &define_opaque);
257+
this.lower_define_opaque(hir_id, define_opaque);
250258
let ident = this.lower_ident(ident);
251259
hir::ItemKind::Fn {
252260
ident,
@@ -665,7 +673,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
665673
owner_id,
666674
ident: self.lower_ident(i.ident),
667675
kind: match &i.kind {
668-
ForeignItemKind::Fn(box Fn { sig, generics, .. }) => {
676+
ForeignItemKind::Fn(box Fn { sig, generics, define_opaque, .. }) => {
669677
let fdec = &sig.decl;
670678
let itctx = ImplTraitContext::Universal;
671679
let (generics, (decl, fn_args)) =
@@ -686,17 +694,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
686694
// Unmarked safety in unsafe block defaults to unsafe.
687695
let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs);
688696

697+
if define_opaque.is_some() {
698+
self.dcx().span_err(i.span, "foreign functions cannot define opaque types");
699+
}
700+
689701
hir::ForeignItemKind::Fn(
690702
hir::FnSig { header, decl, span: self.lower_span(sig.span) },
691703
fn_args,
692704
generics,
693705
)
694706
}
695-
ForeignItemKind::Static(box StaticItem { ty, mutability, expr: _, safety }) => {
707+
ForeignItemKind::Static(box StaticItem {
708+
ty,
709+
mutability,
710+
expr: _,
711+
safety,
712+
define_opaque,
713+
}) => {
696714
let ty = self
697715
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
698716
let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
699717

718+
if define_opaque.is_some() {
719+
self.dcx().span_err(i.span, "foreign statics cannot define opaque types");
720+
}
721+
700722
hir::ForeignItemKind::Static(ty, *mutability, safety)
701723
}
702724
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
@@ -804,7 +826,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
804826
let trait_item_def_id = hir_id.expect_owner();
805827

806828
let (generics, kind, has_default) = match &i.kind {
807-
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => {
829+
AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => {
808830
let (generics, kind) = self.lower_generics(
809831
generics,
810832
i.id,
@@ -817,6 +839,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
817839
hir::TraitItemKind::Const(ty, body)
818840
},
819841
);
842+
843+
if define_opaque.is_some() {
844+
if expr.is_some() {
845+
self.lower_define_opaque(hir_id, &define_opaque);
846+
} else {
847+
self.dcx().span_err(
848+
i.span,
849+
"only trait consts with default bodies can define opaque types",
850+
);
851+
}
852+
}
853+
820854
(generics, kind, expr.is_some())
821855
}
822856
AssocItemKind::Fn(box Fn { sig, generics, body: None, define_opaque, .. }) => {
@@ -954,18 +988,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
954988
let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
955989

956990
let (generics, kind) = match &i.kind {
957-
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
958-
generics,
959-
i.id,
960-
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
961-
|this| {
962-
let ty =
963-
this.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
964-
let body = this.lower_const_body(i.span, expr.as_deref());
965-
966-
hir::ImplItemKind::Const(ty, body)
967-
},
968-
),
991+
AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => self
992+
.lower_generics(
993+
generics,
994+
i.id,
995+
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
996+
|this| {
997+
let ty = this
998+
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
999+
let body = this.lower_const_body(i.span, expr.as_deref());
1000+
this.lower_define_opaque(hir_id, &define_opaque);
1001+
1002+
hir::ImplItemKind::Const(ty, body)
1003+
},
1004+
),
9691005
AssocItemKind::Fn(box Fn { sig, generics, body, contract, define_opaque, .. }) => {
9701006
let body_id = self.lower_maybe_coroutine_body(
9711007
sig.span,

0 commit comments

Comments
 (0)