Allow defining opaques in statics and consts
This commit is contained in:
parent
2bf0c2df14
commit
f8df298d74
17 changed files with 314 additions and 162 deletions
|
@ -3535,6 +3535,7 @@ pub struct StaticItem {
|
||||||
pub safety: Safety,
|
pub safety: Safety,
|
||||||
pub mutability: Mutability,
|
pub mutability: Mutability,
|
||||||
pub expr: Option<P<Expr>>,
|
pub expr: Option<P<Expr>>,
|
||||||
|
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
|
@ -3543,6 +3544,7 @@ pub struct ConstItem {
|
||||||
pub generics: Generics,
|
pub generics: Generics,
|
||||||
pub ty: P<Ty>,
|
pub ty: P<Ty>,
|
||||||
pub expr: Option<P<Expr>>,
|
pub expr: Option<P<Expr>>,
|
||||||
|
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`.
|
// Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`.
|
||||||
|
|
|
@ -987,10 +987,7 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
|
||||||
}
|
}
|
||||||
vis.visit_span(span);
|
vis.visit_span(span);
|
||||||
|
|
||||||
for (id, path) in define_opaque.iter_mut().flatten() {
|
walk_define_opaques(vis, define_opaque);
|
||||||
vis.visit_id(id);
|
|
||||||
vis.visit_path(path)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
FnKind::Closure(binder, coroutine_kind, decl, body) => {
|
FnKind::Closure(binder, coroutine_kind, decl, body) => {
|
||||||
vis.visit_closure_binder(binder);
|
vis.visit_closure_binder(binder);
|
||||||
|
@ -1258,12 +1255,19 @@ impl WalkItemKind for ItemKind {
|
||||||
match self {
|
match self {
|
||||||
ItemKind::ExternCrate(_orig_name) => {}
|
ItemKind::ExternCrate(_orig_name) => {}
|
||||||
ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
|
ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
|
||||||
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
|
ItemKind::Static(box StaticItem {
|
||||||
|
ty,
|
||||||
|
safety: _,
|
||||||
|
mutability: _,
|
||||||
|
expr,
|
||||||
|
define_opaque,
|
||||||
|
}) => {
|
||||||
vis.visit_ty(ty);
|
vis.visit_ty(ty);
|
||||||
visit_opt(expr, |expr| vis.visit_expr(expr));
|
visit_opt(expr, |expr| vis.visit_expr(expr));
|
||||||
|
walk_define_opaques(vis, define_opaque);
|
||||||
}
|
}
|
||||||
ItemKind::Const(item) => {
|
ItemKind::Const(item) => {
|
||||||
visit_const_item(item, vis);
|
walk_const_item(vis, item);
|
||||||
}
|
}
|
||||||
ItemKind::Fn(func) => {
|
ItemKind::Fn(func) => {
|
||||||
vis.visit_fn(FnKind::Fn(FnCtxt::Free, ident, visibility, &mut *func), span, id);
|
vis.visit_fn(FnKind::Fn(FnCtxt::Free, ident, visibility, &mut *func), span, id);
|
||||||
|
@ -1382,7 +1386,7 @@ impl WalkItemKind for AssocItemKind {
|
||||||
) {
|
) {
|
||||||
match self {
|
match self {
|
||||||
AssocItemKind::Const(item) => {
|
AssocItemKind::Const(item) => {
|
||||||
visit_const_item(item, visitor);
|
walk_const_item(visitor, item);
|
||||||
}
|
}
|
||||||
AssocItemKind::Fn(func) => {
|
AssocItemKind::Fn(func) => {
|
||||||
visitor.visit_fn(
|
visitor.visit_fn(
|
||||||
|
@ -1442,14 +1446,13 @@ impl WalkItemKind for AssocItemKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_const_item<T: MutVisitor>(
|
fn walk_const_item<T: MutVisitor>(vis: &mut T, item: &mut ConstItem) {
|
||||||
ConstItem { defaultness, generics, ty, expr }: &mut ConstItem,
|
let ConstItem { defaultness, generics, ty, expr, define_opaque } = item;
|
||||||
visitor: &mut T,
|
visit_defaultness(vis, defaultness);
|
||||||
) {
|
vis.visit_generics(generics);
|
||||||
visit_defaultness(visitor, defaultness);
|
vis.visit_ty(ty);
|
||||||
visitor.visit_generics(generics);
|
visit_opt(expr, |expr| vis.visit_expr(expr));
|
||||||
visitor.visit_ty(ty);
|
walk_define_opaques(vis, define_opaque);
|
||||||
visit_opt(expr, |expr| visitor.visit_expr(expr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn walk_fn_header<T: MutVisitor>(vis: &mut T, header: &mut FnHeader) {
|
fn walk_fn_header<T: MutVisitor>(vis: &mut T, header: &mut FnHeader) {
|
||||||
|
@ -1526,9 +1529,16 @@ impl WalkItemKind for ForeignItemKind {
|
||||||
visitor: &mut impl MutVisitor,
|
visitor: &mut impl MutVisitor,
|
||||||
) {
|
) {
|
||||||
match self {
|
match self {
|
||||||
ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => {
|
ForeignItemKind::Static(box StaticItem {
|
||||||
|
ty,
|
||||||
|
mutability: _,
|
||||||
|
expr,
|
||||||
|
safety: _,
|
||||||
|
define_opaque,
|
||||||
|
}) => {
|
||||||
visitor.visit_ty(ty);
|
visitor.visit_ty(ty);
|
||||||
visit_opt(expr, |expr| visitor.visit_expr(expr));
|
visit_opt(expr, |expr| visitor.visit_expr(expr));
|
||||||
|
walk_define_opaques(visitor, define_opaque);
|
||||||
}
|
}
|
||||||
ForeignItemKind::Fn(func) => {
|
ForeignItemKind::Fn(func) => {
|
||||||
visitor.visit_fn(
|
visitor.visit_fn(
|
||||||
|
@ -1929,6 +1939,18 @@ fn walk_capture_by<T: MutVisitor>(vis: &mut T, capture_by: &mut CaptureBy) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn walk_define_opaques<T: MutVisitor>(
|
||||||
|
vis: &mut T,
|
||||||
|
define_opaque: &mut Option<ThinVec<(NodeId, Path)>>,
|
||||||
|
) {
|
||||||
|
if let Some(define_opaque) = define_opaque {
|
||||||
|
for (id, path) in define_opaque {
|
||||||
|
vis.visit_id(id);
|
||||||
|
vis.visit_path(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Some value for the AST node that is valid but possibly meaningless. Similar
|
/// Some value for the AST node that is valid but possibly meaningless. Similar
|
||||||
/// to `Default` but not intended for wide use. The value will never be used
|
/// to `Default` but not intended for wide use. The value will never be used
|
||||||
/// meaningfully, it exists just to support unwinding in `visit_clobber` in the
|
/// meaningfully, it exists just to support unwinding in `visit_clobber` in the
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
pub use rustc_ast_ir::visit::VisitorResult;
|
pub use rustc_ast_ir::visit::VisitorResult;
|
||||||
pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
|
pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
|
||||||
use rustc_span::{Ident, Span};
|
use rustc_span::{Ident, Span};
|
||||||
|
use thin_vec::ThinVec;
|
||||||
|
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::ptr::P;
|
use crate::ptr::P;
|
||||||
|
@ -371,14 +372,28 @@ impl WalkItemKind for ItemKind {
|
||||||
match self {
|
match self {
|
||||||
ItemKind::ExternCrate(_rename) => {}
|
ItemKind::ExternCrate(_rename) => {}
|
||||||
ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)),
|
ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)),
|
||||||
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
|
ItemKind::Static(box StaticItem {
|
||||||
|
ty,
|
||||||
|
safety: _,
|
||||||
|
mutability: _,
|
||||||
|
expr,
|
||||||
|
define_opaque,
|
||||||
|
}) => {
|
||||||
try_visit!(visitor.visit_ty(ty));
|
try_visit!(visitor.visit_ty(ty));
|
||||||
visit_opt!(visitor, visit_expr, expr);
|
visit_opt!(visitor, visit_expr, expr);
|
||||||
|
try_visit!(walk_define_opaques(visitor, define_opaque));
|
||||||
}
|
}
|
||||||
ItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
|
ItemKind::Const(box ConstItem {
|
||||||
|
defaultness: _,
|
||||||
|
generics,
|
||||||
|
ty,
|
||||||
|
expr,
|
||||||
|
define_opaque,
|
||||||
|
}) => {
|
||||||
try_visit!(visitor.visit_generics(generics));
|
try_visit!(visitor.visit_generics(generics));
|
||||||
try_visit!(visitor.visit_ty(ty));
|
try_visit!(visitor.visit_ty(ty));
|
||||||
visit_opt!(visitor, visit_expr, expr);
|
visit_opt!(visitor, visit_expr, expr);
|
||||||
|
try_visit!(walk_define_opaques(visitor, define_opaque));
|
||||||
}
|
}
|
||||||
ItemKind::Fn(func) => {
|
ItemKind::Fn(func) => {
|
||||||
let kind = FnKind::Fn(FnCtxt::Free, ident, vis, &*func);
|
let kind = FnKind::Fn(FnCtxt::Free, ident, vis, &*func);
|
||||||
|
@ -729,9 +744,16 @@ impl WalkItemKind for ForeignItemKind {
|
||||||
visitor: &mut V,
|
visitor: &mut V,
|
||||||
) -> V::Result {
|
) -> V::Result {
|
||||||
match self {
|
match self {
|
||||||
ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => {
|
ForeignItemKind::Static(box StaticItem {
|
||||||
|
ty,
|
||||||
|
mutability: _,
|
||||||
|
expr,
|
||||||
|
safety: _,
|
||||||
|
define_opaque,
|
||||||
|
}) => {
|
||||||
try_visit!(visitor.visit_ty(ty));
|
try_visit!(visitor.visit_ty(ty));
|
||||||
visit_opt!(visitor, visit_expr, expr);
|
visit_opt!(visitor, visit_expr, expr);
|
||||||
|
try_visit!(walk_define_opaques(visitor, define_opaque));
|
||||||
}
|
}
|
||||||
ForeignItemKind::Fn(func) => {
|
ForeignItemKind::Fn(func) => {
|
||||||
let kind = FnKind::Fn(FnCtxt::Foreign, ident, vis, &*func);
|
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
|
||||||
try_visit!(visitor.visit_fn_decl(decl));
|
try_visit!(visitor.visit_fn_decl(decl));
|
||||||
visit_opt!(visitor, visit_contract, contract);
|
visit_opt!(visitor, visit_contract, contract);
|
||||||
visit_opt!(visitor, visit_block, body);
|
visit_opt!(visitor, visit_block, body);
|
||||||
for (id, path) in define_opaque.iter().flatten() {
|
try_visit!(walk_define_opaques(visitor, define_opaque));
|
||||||
try_visit!(visitor.visit_path(path, *id))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
FnKind::Closure(binder, coroutine_kind, decl, body) => {
|
FnKind::Closure(binder, coroutine_kind, decl, body) => {
|
||||||
try_visit!(visitor.visit_closure_binder(binder));
|
try_visit!(visitor.visit_closure_binder(binder));
|
||||||
|
@ -933,10 +953,17 @@ impl WalkItemKind for AssocItemKind {
|
||||||
visitor: &mut V,
|
visitor: &mut V,
|
||||||
) -> V::Result {
|
) -> V::Result {
|
||||||
match self {
|
match self {
|
||||||
AssocItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
|
AssocItemKind::Const(box ConstItem {
|
||||||
|
defaultness: _,
|
||||||
|
generics,
|
||||||
|
ty,
|
||||||
|
expr,
|
||||||
|
define_opaque,
|
||||||
|
}) => {
|
||||||
try_visit!(visitor.visit_generics(generics));
|
try_visit!(visitor.visit_generics(generics));
|
||||||
try_visit!(visitor.visit_ty(ty));
|
try_visit!(visitor.visit_ty(ty));
|
||||||
visit_opt!(visitor, visit_expr, expr);
|
visit_opt!(visitor, visit_expr, expr);
|
||||||
|
try_visit!(walk_define_opaques(visitor, define_opaque));
|
||||||
}
|
}
|
||||||
AssocItemKind::Fn(func) => {
|
AssocItemKind::Fn(func) => {
|
||||||
let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, vis, &*func);
|
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) -
|
||||||
}
|
}
|
||||||
V::Result::output()
|
V::Result::output()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn walk_define_opaques<'a, V: Visitor<'a>>(
|
||||||
|
visitor: &mut V,
|
||||||
|
define_opaque: &'a Option<ThinVec<(NodeId, Path)>>,
|
||||||
|
) -> V::Result {
|
||||||
|
if let Some(define_opaque) = define_opaque {
|
||||||
|
for (id, path) in define_opaque {
|
||||||
|
try_visit!(visitor.visit_path(path, *id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
V::Result::output()
|
||||||
|
}
|
||||||
|
|
|
@ -188,14 +188,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
|
|
||||||
self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs)
|
self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs)
|
||||||
}
|
}
|
||||||
ItemKind::Static(box ast::StaticItem { ty: t, safety: _, mutability: m, expr: e }) => {
|
ItemKind::Static(box ast::StaticItem {
|
||||||
|
ty: t,
|
||||||
|
safety: _,
|
||||||
|
mutability: m,
|
||||||
|
expr: e,
|
||||||
|
define_opaque,
|
||||||
|
}) => {
|
||||||
debug_assert_ne!(ident.name, kw::Empty);
|
debug_assert_ne!(ident.name, kw::Empty);
|
||||||
let ident = self.lower_ident(ident);
|
let ident = self.lower_ident(ident);
|
||||||
let (ty, body_id) =
|
let (ty, body_id) =
|
||||||
self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
|
self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
|
||||||
|
self.lower_define_opaque(hir_id, define_opaque);
|
||||||
hir::ItemKind::Static(ident, ty, *m, body_id)
|
hir::ItemKind::Static(ident, ty, *m, body_id)
|
||||||
}
|
}
|
||||||
ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
|
ItemKind::Const(box ast::ConstItem { generics, ty, expr, define_opaque, .. }) => {
|
||||||
debug_assert_ne!(ident.name, kw::Empty);
|
debug_assert_ne!(ident.name, kw::Empty);
|
||||||
let ident = self.lower_ident(ident);
|
let ident = self.lower_ident(ident);
|
||||||
let (generics, (ty, body_id)) = self.lower_generics(
|
let (generics, (ty, body_id)) = self.lower_generics(
|
||||||
|
@ -206,6 +213,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy)
|
this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
self.lower_define_opaque(hir_id, &define_opaque);
|
||||||
hir::ItemKind::Const(ident, ty, generics, body_id)
|
hir::ItemKind::Const(ident, ty, generics, body_id)
|
||||||
}
|
}
|
||||||
ItemKind::Fn(box Fn {
|
ItemKind::Fn(box Fn {
|
||||||
|
@ -243,7 +251,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
header: this.lower_fn_header(*header, hir::Safety::Safe, attrs),
|
header: this.lower_fn_header(*header, hir::Safety::Safe, attrs),
|
||||||
span: this.lower_span(*fn_sig_span),
|
span: this.lower_span(*fn_sig_span),
|
||||||
};
|
};
|
||||||
this.lower_define_opaque(hir_id, &define_opaque);
|
this.lower_define_opaque(hir_id, define_opaque);
|
||||||
let ident = this.lower_ident(ident);
|
let ident = this.lower_ident(ident);
|
||||||
hir::ItemKind::Fn {
|
hir::ItemKind::Fn {
|
||||||
ident,
|
ident,
|
||||||
|
@ -662,7 +670,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
owner_id,
|
owner_id,
|
||||||
ident: self.lower_ident(i.ident),
|
ident: self.lower_ident(i.ident),
|
||||||
kind: match &i.kind {
|
kind: match &i.kind {
|
||||||
ForeignItemKind::Fn(box Fn { sig, generics, .. }) => {
|
ForeignItemKind::Fn(box Fn { sig, generics, define_opaque, .. }) => {
|
||||||
let fdec = &sig.decl;
|
let fdec = &sig.decl;
|
||||||
let itctx = ImplTraitContext::Universal;
|
let itctx = ImplTraitContext::Universal;
|
||||||
let (generics, (decl, fn_args)) =
|
let (generics, (decl, fn_args)) =
|
||||||
|
@ -683,17 +691,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
// Unmarked safety in unsafe block defaults to unsafe.
|
// Unmarked safety in unsafe block defaults to unsafe.
|
||||||
let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs);
|
let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs);
|
||||||
|
|
||||||
|
if define_opaque.is_some() {
|
||||||
|
self.dcx().span_err(i.span, "foreign functions cannot define opaque types");
|
||||||
|
}
|
||||||
|
|
||||||
hir::ForeignItemKind::Fn(
|
hir::ForeignItemKind::Fn(
|
||||||
hir::FnSig { header, decl, span: self.lower_span(sig.span) },
|
hir::FnSig { header, decl, span: self.lower_span(sig.span) },
|
||||||
fn_args,
|
fn_args,
|
||||||
generics,
|
generics,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ForeignItemKind::Static(box StaticItem { ty, mutability, expr: _, safety }) => {
|
ForeignItemKind::Static(box StaticItem {
|
||||||
|
ty,
|
||||||
|
mutability,
|
||||||
|
expr: _,
|
||||||
|
safety,
|
||||||
|
define_opaque,
|
||||||
|
}) => {
|
||||||
let ty = self
|
let ty = self
|
||||||
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
|
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
|
||||||
let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
|
let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
|
||||||
|
|
||||||
|
if define_opaque.is_some() {
|
||||||
|
self.dcx().span_err(i.span, "foreign statics cannot define opaque types");
|
||||||
|
}
|
||||||
|
|
||||||
hir::ForeignItemKind::Static(ty, *mutability, safety)
|
hir::ForeignItemKind::Static(ty, *mutability, safety)
|
||||||
}
|
}
|
||||||
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
|
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
|
||||||
|
@ -801,7 +823,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let trait_item_def_id = hir_id.expect_owner();
|
let trait_item_def_id = hir_id.expect_owner();
|
||||||
|
|
||||||
let (generics, kind, has_default) = match &i.kind {
|
let (generics, kind, has_default) = match &i.kind {
|
||||||
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => {
|
AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => {
|
||||||
let (generics, kind) = self.lower_generics(
|
let (generics, kind) = self.lower_generics(
|
||||||
generics,
|
generics,
|
||||||
i.id,
|
i.id,
|
||||||
|
@ -814,6 +836,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
hir::TraitItemKind::Const(ty, body)
|
hir::TraitItemKind::Const(ty, body)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if define_opaque.is_some() {
|
||||||
|
if expr.is_some() {
|
||||||
|
self.lower_define_opaque(hir_id, &define_opaque);
|
||||||
|
} else {
|
||||||
|
self.dcx().span_err(
|
||||||
|
i.span,
|
||||||
|
"only trait consts with default bodies can define opaque types",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(generics, kind, expr.is_some())
|
(generics, kind, expr.is_some())
|
||||||
}
|
}
|
||||||
AssocItemKind::Fn(box Fn { sig, generics, body: None, define_opaque, .. }) => {
|
AssocItemKind::Fn(box Fn { sig, generics, body: None, define_opaque, .. }) => {
|
||||||
|
@ -951,18 +985,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
|
let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
|
||||||
|
|
||||||
let (generics, kind) = match &i.kind {
|
let (generics, kind) = match &i.kind {
|
||||||
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
|
AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => self
|
||||||
generics,
|
.lower_generics(
|
||||||
i.id,
|
generics,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
i.id,
|
||||||
|this| {
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
let ty =
|
|this| {
|
||||||
this.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
|
let ty = this
|
||||||
let body = this.lower_const_body(i.span, expr.as_deref());
|
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
|
||||||
|
let body = this.lower_const_body(i.span, expr.as_deref());
|
||||||
|
this.lower_define_opaque(hir_id, &define_opaque);
|
||||||
|
|
||||||
hir::ImplItemKind::Const(ty, body)
|
hir::ImplItemKind::Const(ty, body)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
AssocItemKind::Fn(box Fn { sig, generics, body, contract, define_opaque, .. }) => {
|
AssocItemKind::Fn(box Fn { sig, generics, body, contract, define_opaque, .. }) => {
|
||||||
let body_id = self.lower_maybe_coroutine_body(
|
let body_id = self.lower_maybe_coroutine_body(
|
||||||
sig.span,
|
sig.span,
|
||||||
|
|
|
@ -37,18 +37,23 @@ impl<'a> State<'a> {
|
||||||
ast::ForeignItemKind::Fn(func) => {
|
ast::ForeignItemKind::Fn(func) => {
|
||||||
self.print_fn_full(ident, vis, attrs, &*func);
|
self.print_fn_full(ident, vis, attrs, &*func);
|
||||||
}
|
}
|
||||||
ast::ForeignItemKind::Static(box ast::StaticItem { ty, mutability, expr, safety }) => {
|
ast::ForeignItemKind::Static(box ast::StaticItem {
|
||||||
self.print_item_const(
|
ty,
|
||||||
ident,
|
mutability,
|
||||||
Some(*mutability),
|
expr,
|
||||||
&ast::Generics::default(),
|
safety,
|
||||||
ty,
|
define_opaque,
|
||||||
expr.as_deref(),
|
}) => self.print_item_const(
|
||||||
vis,
|
ident,
|
||||||
*safety,
|
Some(*mutability),
|
||||||
ast::Defaultness::Final,
|
&ast::Generics::default(),
|
||||||
)
|
ty,
|
||||||
}
|
expr.as_deref(),
|
||||||
|
vis,
|
||||||
|
*safety,
|
||||||
|
ast::Defaultness::Final,
|
||||||
|
define_opaque.as_deref(),
|
||||||
|
),
|
||||||
ast::ForeignItemKind::TyAlias(box ast::TyAlias {
|
ast::ForeignItemKind::TyAlias(box ast::TyAlias {
|
||||||
defaultness,
|
defaultness,
|
||||||
generics,
|
generics,
|
||||||
|
@ -86,7 +91,9 @@ impl<'a> State<'a> {
|
||||||
vis: &ast::Visibility,
|
vis: &ast::Visibility,
|
||||||
safety: ast::Safety,
|
safety: ast::Safety,
|
||||||
defaultness: ast::Defaultness,
|
defaultness: ast::Defaultness,
|
||||||
|
define_opaque: Option<&[(ast::NodeId, ast::Path)]>,
|
||||||
) {
|
) {
|
||||||
|
self.print_define_opaques(define_opaque);
|
||||||
self.head("");
|
self.head("");
|
||||||
self.print_visibility(vis);
|
self.print_visibility(vis);
|
||||||
self.print_safety(safety);
|
self.print_safety(safety);
|
||||||
|
@ -174,7 +181,13 @@ impl<'a> State<'a> {
|
||||||
self.print_use_tree(tree);
|
self.print_use_tree(tree);
|
||||||
self.word(";");
|
self.word(";");
|
||||||
}
|
}
|
||||||
ast::ItemKind::Static(box StaticItem { ty, safety, mutability: mutbl, expr: body }) => {
|
ast::ItemKind::Static(box StaticItem {
|
||||||
|
ty,
|
||||||
|
safety,
|
||||||
|
mutability: mutbl,
|
||||||
|
expr: body,
|
||||||
|
define_opaque,
|
||||||
|
}) => {
|
||||||
self.print_safety(*safety);
|
self.print_safety(*safety);
|
||||||
self.print_item_const(
|
self.print_item_const(
|
||||||
item.ident,
|
item.ident,
|
||||||
|
@ -185,9 +198,16 @@ impl<'a> State<'a> {
|
||||||
&item.vis,
|
&item.vis,
|
||||||
ast::Safety::Default,
|
ast::Safety::Default,
|
||||||
ast::Defaultness::Final,
|
ast::Defaultness::Final,
|
||||||
|
define_opaque.as_deref(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ast::ItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => {
|
ast::ItemKind::Const(box ast::ConstItem {
|
||||||
|
defaultness,
|
||||||
|
generics,
|
||||||
|
ty,
|
||||||
|
expr,
|
||||||
|
define_opaque,
|
||||||
|
}) => {
|
||||||
self.print_item_const(
|
self.print_item_const(
|
||||||
item.ident,
|
item.ident,
|
||||||
None,
|
None,
|
||||||
|
@ -197,6 +217,7 @@ impl<'a> State<'a> {
|
||||||
&item.vis,
|
&item.vis,
|
||||||
ast::Safety::Default,
|
ast::Safety::Default,
|
||||||
*defaultness,
|
*defaultness,
|
||||||
|
define_opaque.as_deref(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ast::ItemKind::Fn(func) => {
|
ast::ItemKind::Fn(func) => {
|
||||||
|
@ -537,7 +558,13 @@ impl<'a> State<'a> {
|
||||||
ast::AssocItemKind::Fn(func) => {
|
ast::AssocItemKind::Fn(func) => {
|
||||||
self.print_fn_full(ident, vis, attrs, &*func);
|
self.print_fn_full(ident, vis, attrs, &*func);
|
||||||
}
|
}
|
||||||
ast::AssocItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => {
|
ast::AssocItemKind::Const(box ast::ConstItem {
|
||||||
|
defaultness,
|
||||||
|
generics,
|
||||||
|
ty,
|
||||||
|
expr,
|
||||||
|
define_opaque,
|
||||||
|
}) => {
|
||||||
self.print_item_const(
|
self.print_item_const(
|
||||||
ident,
|
ident,
|
||||||
None,
|
None,
|
||||||
|
@ -547,6 +574,7 @@ impl<'a> State<'a> {
|
||||||
vis,
|
vis,
|
||||||
ast::Safety::Default,
|
ast::Safety::Default,
|
||||||
*defaultness,
|
*defaultness,
|
||||||
|
define_opaque.as_deref(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ast::AssocItemKind::Type(box ast::TyAlias {
|
ast::AssocItemKind::Type(box ast::TyAlias {
|
||||||
|
@ -652,7 +680,7 @@ impl<'a> State<'a> {
|
||||||
) {
|
) {
|
||||||
let ast::Fn { defaultness, generics, sig, contract, body, define_opaque } = func;
|
let ast::Fn { defaultness, generics, sig, contract, body, define_opaque } = func;
|
||||||
|
|
||||||
self.print_define_opaques(define_opaque);
|
self.print_define_opaques(define_opaque.as_deref());
|
||||||
|
|
||||||
if body.is_some() {
|
if body.is_some() {
|
||||||
self.head("");
|
self.head("");
|
||||||
|
@ -672,10 +700,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_define_opaques(
|
fn print_define_opaques(&mut self, define_opaque: Option<&[(ast::NodeId, ast::Path)]>) {
|
||||||
&mut self,
|
|
||||||
define_opaque: Option<&[(ast::NodeId, ast::Path)]>,
|
|
||||||
) {
|
|
||||||
if let Some(define_opaque) = define_opaque {
|
if let Some(define_opaque) = define_opaque {
|
||||||
self.word("#[define_opaque(");
|
self.word("#[define_opaque(");
|
||||||
for (i, (_, path)) in define_opaque.iter().enumerate() {
|
for (i, (_, path)) in define_opaque.iter().enumerate() {
|
||||||
|
|
|
@ -11,15 +11,20 @@ pub(crate) fn expand(
|
||||||
let define_opaque = match &mut item {
|
let define_opaque = match &mut item {
|
||||||
Annotatable::Item(p) => match &mut p.kind {
|
Annotatable::Item(p) => match &mut p.kind {
|
||||||
ast::ItemKind::Fn(f) => Some(&mut f.define_opaque),
|
ast::ItemKind::Fn(f) => Some(&mut f.define_opaque),
|
||||||
|
ast::ItemKind::Const(ct) => Some(&mut ct.define_opaque),
|
||||||
|
ast::ItemKind::Static(si) => Some(&mut si.define_opaque),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
Annotatable::AssocItem(i, _assoc_ctxt) => match &mut i.kind {
|
Annotatable::AssocItem(i, _assoc_ctxt) => match &mut i.kind {
|
||||||
ast::AssocItemKind::Fn(func) => Some(&mut func.define_opaque),
|
ast::AssocItemKind::Fn(func) => Some(&mut func.define_opaque),
|
||||||
|
ast::AssocItemKind::Const(ct) => Some(&mut ct.define_opaque),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
Annotatable::Stmt(s) => match &mut s.kind {
|
Annotatable::Stmt(s) => match &mut s.kind {
|
||||||
ast::StmtKind::Item(p) => match &mut p.kind {
|
ast::StmtKind::Item(p) => match &mut p.kind {
|
||||||
ast::ItemKind::Fn(f) => Some(&mut f.define_opaque),
|
ast::ItemKind::Fn(f) => Some(&mut f.define_opaque),
|
||||||
|
ast::ItemKind::Const(ct) => Some(&mut ct.define_opaque),
|
||||||
|
ast::ItemKind::Static(si) => Some(&mut si.define_opaque),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
|
@ -285,6 +285,7 @@ pub(crate) fn expand_test_or_bench(
|
||||||
defaultness: ast::Defaultness::Final,
|
defaultness: ast::Defaultness::Final,
|
||||||
generics: ast::Generics::default(),
|
generics: ast::Generics::default(),
|
||||||
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
|
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
|
||||||
|
define_opaque: None,
|
||||||
// test::TestDescAndFn {
|
// test::TestDescAndFn {
|
||||||
expr: Some(
|
expr: Some(
|
||||||
cx.expr_struct(
|
cx.expr_struct(
|
||||||
|
|
|
@ -698,8 +698,14 @@ impl<'a> ExtCtxt<'a> {
|
||||||
name,
|
name,
|
||||||
AttrVec::new(),
|
AttrVec::new(),
|
||||||
ast::ItemKind::Static(
|
ast::ItemKind::Static(
|
||||||
ast::StaticItem { ty, safety: ast::Safety::Default, mutability, expr: Some(expr) }
|
ast::StaticItem {
|
||||||
.into(),
|
ty,
|
||||||
|
safety: ast::Safety::Default,
|
||||||
|
mutability,
|
||||||
|
expr: Some(expr),
|
||||||
|
define_opaque: None,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -723,6 +729,7 @@ impl<'a> ExtCtxt<'a> {
|
||||||
generics: ast::Generics::default(),
|
generics: ast::Generics::default(),
|
||||||
ty,
|
ty,
|
||||||
expr: Some(expr),
|
expr: Some(expr),
|
||||||
|
define_opaque: None,
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
|
|
|
@ -265,6 +265,7 @@ impl<'a> Parser<'a> {
|
||||||
generics,
|
generics,
|
||||||
ty,
|
ty,
|
||||||
expr,
|
expr,
|
||||||
|
define_opaque: None,
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -980,13 +981,20 @@ impl<'a> Parser<'a> {
|
||||||
let kind = match AssocItemKind::try_from(kind) {
|
let kind = match AssocItemKind::try_from(kind) {
|
||||||
Ok(kind) => kind,
|
Ok(kind) => kind,
|
||||||
Err(kind) => match kind {
|
Err(kind) => match kind {
|
||||||
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
|
ItemKind::Static(box StaticItem {
|
||||||
|
ty,
|
||||||
|
safety: _,
|
||||||
|
mutability: _,
|
||||||
|
expr,
|
||||||
|
define_opaque,
|
||||||
|
}) => {
|
||||||
self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
|
self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
|
||||||
AssocItemKind::Const(Box::new(ConstItem {
|
AssocItemKind::Const(Box::new(ConstItem {
|
||||||
defaultness: Defaultness::Final,
|
defaultness: Defaultness::Final,
|
||||||
generics: Generics::default(),
|
generics: Generics::default(),
|
||||||
ty,
|
ty,
|
||||||
expr,
|
expr,
|
||||||
|
define_opaque,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
_ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
|
_ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
|
||||||
|
@ -1254,6 +1262,7 @@ impl<'a> Parser<'a> {
|
||||||
mutability: Mutability::Not,
|
mutability: Mutability::Not,
|
||||||
expr,
|
expr,
|
||||||
safety: Safety::Default,
|
safety: Safety::Default,
|
||||||
|
define_opaque: None,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
_ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
|
_ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
|
||||||
|
@ -1397,7 +1406,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
self.expect_semi()?;
|
self.expect_semi()?;
|
||||||
|
|
||||||
Ok((ident, StaticItem { ty, safety, mutability, expr }))
|
Ok((ident, StaticItem { ty, safety, mutability, expr, define_opaque: None }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a constant item with the prefix `"const"` already parsed.
|
/// Parse a constant item with the prefix `"const"` already parsed.
|
||||||
|
|
|
@ -244,7 +244,13 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
|
||||||
|
|
||||||
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
||||||
let def_kind = match fi.kind {
|
let def_kind = match fi.kind {
|
||||||
ForeignItemKind::Static(box StaticItem { ty: _, mutability, expr: _, safety }) => {
|
ForeignItemKind::Static(box StaticItem {
|
||||||
|
ty: _,
|
||||||
|
mutability,
|
||||||
|
expr: _,
|
||||||
|
safety,
|
||||||
|
define_opaque: _,
|
||||||
|
}) => {
|
||||||
let safety = match safety {
|
let safety = match safety {
|
||||||
ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe,
|
ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe,
|
||||||
ast::Safety::Safe(_) => hir::Safety::Safe,
|
ast::Safety::Safe(_) => hir::Safety::Safe,
|
||||||
|
|
|
@ -36,6 +36,7 @@ use rustc_session::parse::feature_err;
|
||||||
use rustc_span::source_map::{Spanned, respan};
|
use rustc_span::source_map::{Spanned, respan};
|
||||||
use rustc_span::{BytePos, Ident, Span, Symbol, SyntaxContext, kw, sym};
|
use rustc_span::{BytePos, Ident, Span, Symbol, SyntaxContext, kw, sym};
|
||||||
use smallvec::{SmallVec, smallvec};
|
use smallvec::{SmallVec, smallvec};
|
||||||
|
use thin_vec::ThinVec;
|
||||||
use tracing::{debug, instrument, trace};
|
use tracing::{debug, instrument, trace};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -2662,10 +2663,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
},
|
},
|
||||||
|this| visit::walk_item(this, item),
|
|this| visit::walk_item(this, item),
|
||||||
);
|
);
|
||||||
|
self.resolve_define_opaques(define_opaque);
|
||||||
for (id, path) in define_opaque.iter().flatten() {
|
|
||||||
self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKind::Enum(_, ref generics)
|
ItemKind::Enum(_, ref generics)
|
||||||
|
@ -2751,7 +2749,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => {
|
ItemKind::Static(box ast::StaticItem {
|
||||||
|
ref ty, ref expr, ref define_opaque, ..
|
||||||
|
}) => {
|
||||||
self.with_static_rib(def_kind, |this| {
|
self.with_static_rib(def_kind, |this| {
|
||||||
this.with_lifetime_rib(
|
this.with_lifetime_rib(
|
||||||
LifetimeRibKind::Elided(LifetimeRes::Static {
|
LifetimeRibKind::Elided(LifetimeRes::Static {
|
||||||
|
@ -2767,9 +2767,16 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
this.resolve_const_body(expr, Some((item.ident, ConstantItemKind::Static)));
|
this.resolve_const_body(expr, Some((item.ident, ConstantItemKind::Static)));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
self.resolve_define_opaques(define_opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKind::Const(box ast::ConstItem { ref generics, ref ty, ref expr, .. }) => {
|
ItemKind::Const(box ast::ConstItem {
|
||||||
|
ref generics,
|
||||||
|
ref ty,
|
||||||
|
ref expr,
|
||||||
|
ref define_opaque,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
self.with_generic_param_rib(
|
self.with_generic_param_rib(
|
||||||
&generics.params,
|
&generics.params,
|
||||||
RibKind::Item(
|
RibKind::Item(
|
||||||
|
@ -2803,6 +2810,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
self.resolve_define_opaques(define_opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKind::Use(ref use_tree) => {
|
ItemKind::Use(ref use_tree) => {
|
||||||
|
@ -3102,7 +3110,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
for item in trait_items {
|
for item in trait_items {
|
||||||
self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
|
self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
|
||||||
match &item.kind {
|
match &item.kind {
|
||||||
AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
|
AssocItemKind::Const(box ast::ConstItem {
|
||||||
|
generics,
|
||||||
|
ty,
|
||||||
|
expr,
|
||||||
|
define_opaque,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
self.with_generic_param_rib(
|
self.with_generic_param_rib(
|
||||||
&generics.params,
|
&generics.params,
|
||||||
RibKind::AssocItem,
|
RibKind::AssocItem,
|
||||||
|
@ -3135,13 +3149,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.resolve_define_opaques(define_opaque);
|
||||||
}
|
}
|
||||||
AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
|
AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
|
||||||
walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
|
walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
|
||||||
|
|
||||||
for (id, path) in define_opaque.iter().flatten() {
|
self.resolve_define_opaques(define_opaque);
|
||||||
self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
AssocItemKind::Delegation(delegation) => {
|
AssocItemKind::Delegation(delegation) => {
|
||||||
self.with_generic_param_rib(
|
self.with_generic_param_rib(
|
||||||
|
@ -3306,7 +3320,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
use crate::ResolutionError::*;
|
use crate::ResolutionError::*;
|
||||||
self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis)));
|
self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis)));
|
||||||
match &item.kind {
|
match &item.kind {
|
||||||
AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
|
AssocItemKind::Const(box ast::ConstItem {
|
||||||
|
generics, ty, expr, define_opaque, ..
|
||||||
|
}) => {
|
||||||
debug!("resolve_implementation AssocItemKind::Const");
|
debug!("resolve_implementation AssocItemKind::Const");
|
||||||
self.with_generic_param_rib(
|
self.with_generic_param_rib(
|
||||||
&generics.params,
|
&generics.params,
|
||||||
|
@ -3350,6 +3366,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
self.resolve_define_opaques(define_opaque);
|
||||||
}
|
}
|
||||||
AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
|
AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
|
||||||
debug!("resolve_implementation AssocItemKind::Fn");
|
debug!("resolve_implementation AssocItemKind::Fn");
|
||||||
|
@ -3379,9 +3396,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
for (id, path) in define_opaque.iter().flatten() {
|
self.resolve_define_opaques(define_opaque);
|
||||||
self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
AssocItemKind::Type(box TyAlias { generics, .. }) => {
|
AssocItemKind::Type(box TyAlias { generics, .. }) => {
|
||||||
self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty());
|
self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty());
|
||||||
|
@ -5103,6 +5118,14 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_define_opaques(&mut self, define_opaque: &Option<ThinVec<(NodeId, Path)>>) {
|
||||||
|
if let Some(define_opaque) = define_opaque {
|
||||||
|
for (id, path) in define_opaque {
|
||||||
|
self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
|
/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
|
||||||
|
|
|
@ -336,12 +336,14 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
||||||
mutability: lm,
|
mutability: lm,
|
||||||
expr: le,
|
expr: le,
|
||||||
safety: ls,
|
safety: ls,
|
||||||
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
Static(box StaticItem {
|
Static(box StaticItem {
|
||||||
ty: rt,
|
ty: rt,
|
||||||
mutability: rm,
|
mutability: rm,
|
||||||
expr: re,
|
expr: re,
|
||||||
safety: rs,
|
safety: rs,
|
||||||
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
) => lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
|
) => lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
|
||||||
(
|
(
|
||||||
|
@ -350,12 +352,14 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
||||||
generics: lg,
|
generics: lg,
|
||||||
ty: lt,
|
ty: lt,
|
||||||
expr: le,
|
expr: le,
|
||||||
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
Const(box ConstItem {
|
Const(box ConstItem {
|
||||||
defaultness: rd,
|
defaultness: rd,
|
||||||
generics: rg,
|
generics: rg,
|
||||||
ty: rt,
|
ty: rt,
|
||||||
expr: re,
|
expr: re,
|
||||||
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
|
) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
|
||||||
(
|
(
|
||||||
|
@ -490,12 +494,14 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
|
||||||
mutability: lm,
|
mutability: lm,
|
||||||
expr: le,
|
expr: le,
|
||||||
safety: ls,
|
safety: ls,
|
||||||
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
Static(box StaticItem {
|
Static(box StaticItem {
|
||||||
ty: rt,
|
ty: rt,
|
||||||
mutability: rm,
|
mutability: rm,
|
||||||
expr: re,
|
expr: re,
|
||||||
safety: rs,
|
safety: rs,
|
||||||
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()) && ls == rs,
|
) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()) && ls == rs,
|
||||||
(
|
(
|
||||||
|
@ -557,12 +563,14 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
|
||||||
generics: lg,
|
generics: lg,
|
||||||
ty: lt,
|
ty: lt,
|
||||||
expr: le,
|
expr: le,
|
||||||
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
Const(box ConstItem {
|
Const(box ConstItem {
|
||||||
defaultness: rd,
|
defaultness: rd,
|
||||||
generics: rg,
|
generics: rg,
|
||||||
ty: rt,
|
ty: rt,
|
||||||
expr: re,
|
expr: re,
|
||||||
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
|
) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
|
||||||
(
|
(
|
||||||
|
|
12
tests/ui/impl-trait/define-via-const.rs
Normal file
12
tests/ui/impl-trait/define-via-const.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
type Closure = impl Fn(u32) -> u32;
|
||||||
|
|
||||||
|
#[define_opaque(Closure)]
|
||||||
|
const ADDER: Closure = |x| x + 1;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let z = (ADDER)(1);
|
||||||
|
}
|
|
@ -2,14 +2,15 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
type Bug<T, U> = impl Fn(T) -> U + Copy;
|
type Bug<T, U> = impl Fn(T) -> U + Copy;
|
||||||
|
//~^ ERROR cycle detected when computing type of `Bug::{opaque#0}`
|
||||||
|
|
||||||
#[define_opaque(Bug)]
|
#[define_opaque(Bug)]
|
||||||
//~^ ERROR: only functions and methods can define opaque types
|
|
||||||
const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
||||||
|
//~^ ERROR item does not constrain `Bug::{opaque#0}`
|
||||||
|
|
||||||
#[define_opaque(Bug)]
|
#[define_opaque(Bug)]
|
||||||
fn make_bug<T, U: From<T>>() -> Bug<T, U> {
|
fn make_bug<T, U: From<T>>() -> Bug<T, U> {
|
||||||
|x| x.into() //~ ERROR is not satisfied
|
|x| x.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -1,25 +1,42 @@
|
||||||
error: only functions and methods can define opaque types
|
error[E0391]: cycle detected when computing type of `Bug::{opaque#0}`
|
||||||
--> $DIR/issue-53092-2.rs:6:1
|
--> $DIR/issue-53092-2.rs:4:18
|
||||||
|
|
|
|
||||||
LL | #[define_opaque(Bug)]
|
LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: ...which requires computing type of opaque `Bug::{opaque#0}`...
|
||||||
|
--> $DIR/issue-53092-2.rs:4:18
|
||||||
|
|
|
||||||
|
LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: ...which requires type-checking `CONST_BUG`...
|
||||||
|
--> $DIR/issue-53092-2.rs:8:1
|
||||||
|
|
|
||||||
|
LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= note: ...which requires computing layout of `Bug<u8, ()>`...
|
||||||
|
= note: ...which requires normalizing `Bug<u8, ()>`...
|
||||||
|
= note: ...which again requires computing type of `Bug::{opaque#0}`, completing the cycle
|
||||||
|
note: cycle used when checking that `Bug::{opaque#0}` is well-formed
|
||||||
|
--> $DIR/issue-53092-2.rs:4:18
|
||||||
|
|
|
||||||
|
LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||||
|
|
||||||
error[E0277]: the trait bound `U: From<T>` is not satisfied
|
error: item does not constrain `Bug::{opaque#0}`
|
||||||
--> $DIR/issue-53092-2.rs:12:5
|
--> $DIR/issue-53092-2.rs:8:7
|
||||||
|
|
|
|
||||||
LL | |x| x.into()
|
LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
||||||
| ^^^^^^^^^^^^ the trait `From<T>` is not implemented for `U`
|
| ^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: required by a bound in `make_bug`
|
= note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
|
||||||
--> $DIR/issue-53092-2.rs:11:19
|
note: this opaque type is supposed to be constrained
|
||||||
|
--> $DIR/issue-53092-2.rs:4:18
|
||||||
|
|
|
|
||||||
LL | fn make_bug<T, U: From<T>>() -> Bug<T, U> {
|
LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
|
||||||
| ^^^^^^^ required by this bound in `make_bug`
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: consider restricting type parameter `U` with trait `From`
|
|
||||||
|
|
|
||||||
LL | type Bug<T, U: std::convert::From<T>> = impl Fn(T) -> U + Copy;
|
|
||||||
| +++++++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
For more information about this error, try `rustc --explain E0391`.
|
||||||
|
|
|
@ -1,19 +1,15 @@
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
// Ensures that `const` items can not constrain an opaque `impl Trait`.
|
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
pub type Foo = impl Debug;
|
pub type Foo = impl Debug;
|
||||||
//~^ ERROR unconstrained opaque type
|
|
||||||
|
|
||||||
#[define_opaque(Foo)]
|
#[define_opaque(Foo)]
|
||||||
//~^ ERROR only functions and methods can define opaque types
|
|
||||||
const _FOO: Foo = 5;
|
const _FOO: Foo = 5;
|
||||||
//~^ ERROR mismatched types
|
|
||||||
|
|
||||||
#[define_opaque(Foo)]
|
#[define_opaque(Foo)]
|
||||||
//~^ ERROR only functions and methods can define opaque types
|
static _BAR: Foo = 22_i32;
|
||||||
static _BAR: Foo = 22_u32;
|
|
||||||
//~^ ERROR mismatched types
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
error: only functions and methods can define opaque types
|
|
||||||
--> $DIR/type-alias-impl-trait-const.rs:9:1
|
|
||||||
|
|
|
||||||
LL | #[define_opaque(Foo)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: only functions and methods can define opaque types
|
|
||||||
--> $DIR/type-alias-impl-trait-const.rs:14:1
|
|
||||||
|
|
|
||||||
LL | #[define_opaque(Foo)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: unconstrained opaque type
|
|
||||||
--> $DIR/type-alias-impl-trait-const.rs:6:16
|
|
||||||
|
|
|
||||||
LL | pub type Foo = impl Debug;
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: `Foo` must be used in combination with a concrete type within the same crate
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
|
||||||
--> $DIR/type-alias-impl-trait-const.rs:11:19
|
|
||||||
|
|
|
||||||
LL | pub type Foo = impl Debug;
|
|
||||||
| ---------- the expected opaque type
|
|
||||||
...
|
|
||||||
LL | const _FOO: Foo = 5;
|
|
||||||
| ^ expected opaque type, found integer
|
|
||||||
|
|
|
||||||
= note: expected opaque type `Foo`
|
|
||||||
found type `{integer}`
|
|
||||||
note: this item must have a `#[define_opaque(Foo)]` attribute to be able to define hidden types
|
|
||||||
--> $DIR/type-alias-impl-trait-const.rs:11:7
|
|
||||||
|
|
|
||||||
LL | const _FOO: Foo = 5;
|
|
||||||
| ^^^^
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
|
||||||
--> $DIR/type-alias-impl-trait-const.rs:16:20
|
|
||||||
|
|
|
||||||
LL | pub type Foo = impl Debug;
|
|
||||||
| ---------- the expected opaque type
|
|
||||||
...
|
|
||||||
LL | static _BAR: Foo = 22_u32;
|
|
||||||
| ^^^^^^ expected opaque type, found `u32`
|
|
||||||
|
|
|
||||||
= note: expected opaque type `Foo`
|
|
||||||
found type `u32`
|
|
||||||
note: this item must have a `#[define_opaque(Foo)]` attribute to be able to define hidden types
|
|
||||||
--> $DIR/type-alias-impl-trait-const.rs:16:8
|
|
||||||
|
|
|
||||||
LL | static _BAR: Foo = 22_u32;
|
|
||||||
| ^^^^
|
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
|
Loading…
Add table
Add a link
Reference in a new issue