Auto merge of #123413 - petrochenkov:delegmulti2, r=fmease
delegation: Implement list delegation ```rust reuse prefix::{a, b, c}; ``` Using design described in https://github.com/rust-lang/rfcs/pull/3530#issuecomment-2020869823 (the lists are desugared at macro expansion time). List delegations are expanded eagerly when encountered, similarly to `#[cfg]`s, and not enqueued for later resolution/expansion like regular macros or glob delegation (https://github.com/rust-lang/rust/pull/124135). Part of https://github.com/rust-lang/rust/issues/118212.
This commit is contained in:
commit
3cb0030fe9
@ -2961,6 +2961,7 @@ pub fn opt_generics(&self) -> Option<&Generics> {
|
||||
| ItemKind::GlobalAsm(_)
|
||||
| ItemKind::MacCall(_)
|
||||
| ItemKind::Delegation(_)
|
||||
| ItemKind::DelegationMac(_)
|
||||
| ItemKind::MacroDef(_) => None,
|
||||
ItemKind::Static(_) => None,
|
||||
ItemKind::Const(i) => Some(&i.generics),
|
||||
@ -3123,8 +3124,16 @@ pub struct Delegation {
|
||||
/// Path resolution id.
|
||||
pub id: NodeId,
|
||||
pub qself: Option<P<QSelf>>,
|
||||
pub rename: Option<Ident>,
|
||||
pub path: Path,
|
||||
pub rename: Option<Ident>,
|
||||
pub body: Option<P<Block>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct DelegationMac {
|
||||
pub qself: Option<P<QSelf>>,
|
||||
pub prefix: Path,
|
||||
pub suffixes: ThinVec<(Ident, Option<Ident>)>,
|
||||
pub body: Option<P<Block>>,
|
||||
}
|
||||
|
||||
@ -3243,10 +3252,13 @@ pub enum ItemKind {
|
||||
/// A macro definition.
|
||||
MacroDef(MacroDef),
|
||||
|
||||
/// A delegation item (`reuse`).
|
||||
/// A single delegation item (`reuse`).
|
||||
///
|
||||
/// E.g. `reuse <Type as Trait>::name { target_expr_template }`.
|
||||
Delegation(Box<Delegation>),
|
||||
/// A list delegation item (`reuse prefix::{a, b, c}`).
|
||||
/// Treated similarly to a macro call and expanded early.
|
||||
DelegationMac(Box<DelegationMac>),
|
||||
}
|
||||
|
||||
impl ItemKind {
|
||||
@ -3255,7 +3267,7 @@ pub fn article(&self) -> &'static str {
|
||||
match self {
|
||||
Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
|
||||
| Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..)
|
||||
| Delegation(..) => "a",
|
||||
| Delegation(..) | DelegationMac(..) => "a",
|
||||
ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
|
||||
}
|
||||
}
|
||||
@ -3280,6 +3292,7 @@ pub fn descr(&self) -> &'static str {
|
||||
ItemKind::MacroDef(..) => "macro definition",
|
||||
ItemKind::Impl { .. } => "implementation",
|
||||
ItemKind::Delegation(..) => "delegated function",
|
||||
ItemKind::DelegationMac(..) => "delegation",
|
||||
}
|
||||
}
|
||||
|
||||
@ -3323,6 +3336,8 @@ pub enum AssocItemKind {
|
||||
MacCall(P<MacCall>),
|
||||
/// An associated delegation item.
|
||||
Delegation(Box<Delegation>),
|
||||
/// An associated delegation item list.
|
||||
DelegationMac(Box<DelegationMac>),
|
||||
}
|
||||
|
||||
impl AssocItemKind {
|
||||
@ -3331,7 +3346,9 @@ pub fn defaultness(&self) -> Defaultness {
|
||||
Self::Const(box ConstItem { defaultness, .. })
|
||||
| Self::Fn(box Fn { defaultness, .. })
|
||||
| Self::Type(box TyAlias { defaultness, .. }) => defaultness,
|
||||
Self::MacCall(..) | Self::Delegation(..) => Defaultness::Final,
|
||||
Self::MacCall(..) | Self::Delegation(..) | Self::DelegationMac(..) => {
|
||||
Defaultness::Final
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3344,6 +3361,7 @@ fn from(assoc_item_kind: AssocItemKind) -> ItemKind {
|
||||
AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
|
||||
AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
|
||||
AssocItemKind::Delegation(delegation) => ItemKind::Delegation(delegation),
|
||||
AssocItemKind::DelegationMac(delegation) => ItemKind::DelegationMac(delegation),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3358,6 +3376,7 @@ fn try_from(item_kind: ItemKind) -> Result<AssocItemKind, ItemKind> {
|
||||
ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind),
|
||||
ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
|
||||
ItemKind::Delegation(d) => AssocItemKind::Delegation(d),
|
||||
ItemKind::DelegationMac(d) => AssocItemKind::DelegationMac(d),
|
||||
_ => return Err(item_kind),
|
||||
})
|
||||
}
|
||||
|
@ -1170,6 +1170,19 @@ fn noop_visit(&mut self, vis: &mut impl MutVisitor) {
|
||||
vis.visit_block(body);
|
||||
}
|
||||
}
|
||||
ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
|
||||
vis.visit_qself(qself);
|
||||
vis.visit_path(prefix);
|
||||
for (ident, rename) in suffixes {
|
||||
vis.visit_ident(ident);
|
||||
if let Some(rename) = rename {
|
||||
vis.visit_ident(rename);
|
||||
}
|
||||
}
|
||||
if let Some(body) = body {
|
||||
vis.visit_block(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1213,6 +1226,19 @@ fn noop_visit(&mut self, visitor: &mut impl MutVisitor) {
|
||||
visitor.visit_block(body);
|
||||
}
|
||||
}
|
||||
AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
|
||||
visitor.visit_qself(qself);
|
||||
visitor.visit_path(prefix);
|
||||
for (ident, rename) in suffixes {
|
||||
visitor.visit_ident(ident);
|
||||
if let Some(rename) = rename {
|
||||
visitor.visit_ident(rename);
|
||||
}
|
||||
}
|
||||
if let Some(body) = body {
|
||||
visitor.visit_block(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -403,6 +403,19 @@ fn walk<'a, V: Visitor<'a>>(
|
||||
visit_opt!(visitor, visit_ident, *rename);
|
||||
visit_opt!(visitor, visit_block, body);
|
||||
}
|
||||
ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
|
||||
if let Some(qself) = qself {
|
||||
try_visit!(visitor.visit_ty(&qself.ty));
|
||||
}
|
||||
try_visit!(visitor.visit_path(prefix, item.id));
|
||||
for (ident, rename) in suffixes {
|
||||
visitor.visit_ident(*ident);
|
||||
if let Some(rename) = rename {
|
||||
visitor.visit_ident(*rename);
|
||||
}
|
||||
}
|
||||
visit_opt!(visitor, visit_block, body);
|
||||
}
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
@ -815,6 +828,19 @@ fn walk<'a, V: Visitor<'a>>(
|
||||
visit_opt!(visitor, visit_ident, *rename);
|
||||
visit_opt!(visitor, visit_block, body);
|
||||
}
|
||||
AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
|
||||
if let Some(qself) = qself {
|
||||
try_visit!(visitor.visit_ty(&qself.ty));
|
||||
}
|
||||
try_visit!(visitor.visit_path(prefix, item.id));
|
||||
for (ident, rename) in suffixes {
|
||||
visitor.visit_ident(*ident);
|
||||
if let Some(rename) = rename {
|
||||
visitor.visit_ident(*rename);
|
||||
}
|
||||
}
|
||||
visit_opt!(visitor, visit_block, body);
|
||||
}
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
|
@ -460,8 +460,8 @@ fn lower_item_kind(
|
||||
delegation_results.body_id,
|
||||
)
|
||||
}
|
||||
ItemKind::MacCall(..) => {
|
||||
panic!("`TyMac` should have been expanded by now")
|
||||
ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {
|
||||
panic!("macros should have been expanded by now")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -845,7 +845,9 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
|
||||
);
|
||||
(delegation_results.generics, item_kind, true)
|
||||
}
|
||||
AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
|
||||
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
|
||||
panic!("macros should have been expanded by now")
|
||||
}
|
||||
};
|
||||
|
||||
let item = hir::TraitItem {
|
||||
@ -869,7 +871,9 @@ fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
|
||||
AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
|
||||
has_self: self.delegation_has_self(i.id, delegation.id, i.span),
|
||||
},
|
||||
AssocItemKind::MacCall(..) => unimplemented!(),
|
||||
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
|
||||
panic!("macros should have been expanded by now")
|
||||
}
|
||||
};
|
||||
let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
|
||||
hir::TraitItemRef {
|
||||
@ -964,7 +968,9 @@ fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
|
||||
hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
|
||||
)
|
||||
}
|
||||
AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"),
|
||||
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
|
||||
panic!("macros should have been expanded by now")
|
||||
}
|
||||
};
|
||||
|
||||
let item = hir::ImplItem {
|
||||
@ -993,7 +999,9 @@ fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
|
||||
AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
|
||||
has_self: self.delegation_has_self(i.id, delegation.id, i.span),
|
||||
},
|
||||
AssocItemKind::MacCall(..) => unimplemented!(),
|
||||
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
|
||||
panic!("macros should have been expanded by now")
|
||||
}
|
||||
},
|
||||
trait_item_def_id: self
|
||||
.resolver
|
||||
|
@ -5,6 +5,7 @@
|
||||
use ast::StaticItem;
|
||||
use itertools::{Itertools, Position};
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::ModKind;
|
||||
use rustc_span::symbol::Ident;
|
||||
|
||||
@ -374,9 +375,22 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
|
||||
state.print_visibility(&item.vis)
|
||||
});
|
||||
}
|
||||
ast::ItemKind::Delegation(box delegation) => {
|
||||
self.print_delegation(delegation, &item.vis, &item.attrs)
|
||||
}
|
||||
ast::ItemKind::Delegation(deleg) => self.print_delegation(
|
||||
&item.attrs,
|
||||
&item.vis,
|
||||
&deleg.qself,
|
||||
&deleg.path,
|
||||
None,
|
||||
&deleg.body,
|
||||
),
|
||||
ast::ItemKind::DelegationMac(deleg) => self.print_delegation(
|
||||
&item.attrs,
|
||||
&item.vis,
|
||||
&deleg.qself,
|
||||
&deleg.prefix,
|
||||
Some(&deleg.suffixes),
|
||||
&deleg.body,
|
||||
),
|
||||
}
|
||||
self.ann.post(self, AnnNode::Item(item))
|
||||
}
|
||||
@ -553,31 +567,63 @@ fn print_assoc_item(&mut self, item: &ast::AssocItem) {
|
||||
self.word(";");
|
||||
}
|
||||
}
|
||||
ast::AssocItemKind::Delegation(box delegation) => {
|
||||
self.print_delegation(delegation, vis, &item.attrs)
|
||||
}
|
||||
ast::AssocItemKind::Delegation(deleg) => self.print_delegation(
|
||||
&item.attrs,
|
||||
vis,
|
||||
&deleg.qself,
|
||||
&deleg.path,
|
||||
None,
|
||||
&deleg.body,
|
||||
),
|
||||
ast::AssocItemKind::DelegationMac(deleg) => self.print_delegation(
|
||||
&item.attrs,
|
||||
vis,
|
||||
&deleg.qself,
|
||||
&deleg.prefix,
|
||||
Some(&deleg.suffixes),
|
||||
&deleg.body,
|
||||
),
|
||||
}
|
||||
self.ann.post(self, AnnNode::SubItem(id))
|
||||
}
|
||||
|
||||
pub(crate) fn print_delegation(
|
||||
&mut self,
|
||||
delegation: &ast::Delegation,
|
||||
vis: &ast::Visibility,
|
||||
attrs: &[ast::Attribute],
|
||||
vis: &ast::Visibility,
|
||||
qself: &Option<P<ast::QSelf>>,
|
||||
path: &ast::Path,
|
||||
suffixes: Option<&[(Ident, Option<Ident>)]>,
|
||||
body: &Option<P<ast::Block>>,
|
||||
) {
|
||||
if delegation.body.is_some() {
|
||||
if body.is_some() {
|
||||
self.head("");
|
||||
}
|
||||
self.print_visibility(vis);
|
||||
self.word_space("reuse");
|
||||
self.word_nbsp("reuse");
|
||||
|
||||
if let Some(qself) = &delegation.qself {
|
||||
self.print_qpath(&delegation.path, qself, false);
|
||||
if let Some(qself) = qself {
|
||||
self.print_qpath(path, qself, false);
|
||||
} else {
|
||||
self.print_path(&delegation.path, false, 0);
|
||||
self.print_path(path, false, 0);
|
||||
}
|
||||
if let Some(body) = &delegation.body {
|
||||
if let Some(suffixes) = suffixes {
|
||||
self.word("::");
|
||||
self.word("{");
|
||||
for (i, (ident, rename)) in suffixes.iter().enumerate() {
|
||||
self.print_ident(*ident);
|
||||
if let Some(rename) = rename {
|
||||
self.nbsp();
|
||||
self.word_nbsp("as");
|
||||
self.print_ident(*rename);
|
||||
}
|
||||
if i != suffixes.len() - 1 {
|
||||
self.word_space(",");
|
||||
}
|
||||
}
|
||||
self.word("}");
|
||||
}
|
||||
if let Some(body) = body {
|
||||
self.nbsp();
|
||||
self.print_block_with_attrs(body, attrs);
|
||||
} else {
|
||||
|
@ -30,6 +30,9 @@ expand_duplicate_matcher_binding = duplicate matcher binding
|
||||
.label = duplicate binding
|
||||
.label2 = previous binding
|
||||
|
||||
expand_empty_delegation_list =
|
||||
empty list delegation is not supported
|
||||
|
||||
expand_expected_paren_or_brace =
|
||||
expected `(` or `{"{"}`, found `{$token}`
|
||||
|
||||
|
@ -433,3 +433,10 @@ pub struct ExpectedParenOrBrace<'a> {
|
||||
pub span: Span,
|
||||
pub token: Cow<'a, str>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(expand_empty_delegation_list)]
|
||||
pub(crate) struct EmptyDelegationList {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::base::*;
|
||||
use crate::config::StripUnconfigured;
|
||||
use crate::errors::{
|
||||
IncompleteParse, RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported,
|
||||
UnsupportedKeyValue, WrongFragmentKind,
|
||||
EmptyDelegationList, IncompleteParse, RecursionLimitReached, RemoveExprNotSupported,
|
||||
RemoveNodeNotSupported, UnsupportedKeyValue, WrongFragmentKind,
|
||||
};
|
||||
use crate::mbe::diagnostics::annotate_err_with_kind;
|
||||
use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
|
||||
@ -1041,6 +1041,7 @@ enum AddSemicolon {
|
||||
trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
|
||||
type OutputTy = SmallVec<[Self; 1]>;
|
||||
type AttrsTy: Deref<Target = [ast::Attribute]> = ast::AttrVec;
|
||||
type ItemKind = ItemKind;
|
||||
const KIND: AstFragmentKind;
|
||||
fn to_annotatable(self) -> Annotatable;
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy;
|
||||
@ -1059,6 +1060,18 @@ fn is_mac_call(&self) -> bool {
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
unreachable!()
|
||||
}
|
||||
fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
|
||||
None
|
||||
}
|
||||
fn delegation_item_kind(_deleg: Box<ast::Delegation>) -> Self::ItemKind {
|
||||
unreachable!()
|
||||
}
|
||||
fn from_item(_item: ast::Item<Self::ItemKind>) -> Self {
|
||||
unreachable!()
|
||||
}
|
||||
fn flatten_outputs(_outputs: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
|
||||
unreachable!()
|
||||
}
|
||||
fn pre_flat_map_node_collect_attr(_cfg: &StripUnconfigured<'_>, _attr: &ast::Attribute) {}
|
||||
fn post_flat_map_node_collect_bang(_output: &mut Self::OutputTy, _add_semicolon: AddSemicolon) {
|
||||
}
|
||||
@ -1106,6 +1119,21 @@ fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
|
||||
match &self.kind {
|
||||
ItemKind::DelegationMac(deleg) => Some((deleg, self)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
|
||||
ItemKind::Delegation(deleg)
|
||||
}
|
||||
fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
|
||||
P(item)
|
||||
}
|
||||
fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
|
||||
items.flatten().collect()
|
||||
}
|
||||
fn wrap_flat_map_node_noop_flat_map(
|
||||
mut node: Self,
|
||||
collector: &mut InvocationCollector<'_, '_>,
|
||||
@ -1214,6 +1242,7 @@ fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec<Ident>) {
|
||||
struct TraitItemTag;
|
||||
impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitItemTag> {
|
||||
type OutputTy = SmallVec<[P<ast::AssocItem>; 1]>;
|
||||
type ItemKind = AssocItemKind;
|
||||
const KIND: AstFragmentKind = AstFragmentKind::TraitItems;
|
||||
fn to_annotatable(self) -> Annotatable {
|
||||
Annotatable::TraitItem(self.wrapped)
|
||||
@ -1234,11 +1263,27 @@ fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
|
||||
match &self.wrapped.kind {
|
||||
AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
|
||||
AssocItemKind::Delegation(deleg)
|
||||
}
|
||||
fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
|
||||
AstNodeWrapper::new(P(item), TraitItemTag)
|
||||
}
|
||||
fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
|
||||
items.flatten().collect()
|
||||
}
|
||||
}
|
||||
|
||||
struct ImplItemTag;
|
||||
impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag> {
|
||||
type OutputTy = SmallVec<[P<ast::AssocItem>; 1]>;
|
||||
type ItemKind = AssocItemKind;
|
||||
const KIND: AstFragmentKind = AstFragmentKind::ImplItems;
|
||||
fn to_annotatable(self) -> Annotatable {
|
||||
Annotatable::ImplItem(self.wrapped)
|
||||
@ -1259,6 +1304,21 @@ fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
|
||||
match &self.wrapped.kind {
|
||||
AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
|
||||
AssocItemKind::Delegation(deleg)
|
||||
}
|
||||
fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
|
||||
AstNodeWrapper::new(P(item), ImplItemTag)
|
||||
}
|
||||
fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
|
||||
items.flatten().collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl InvocationCollectorNode for P<ast::ForeignItem> {
|
||||
@ -1420,6 +1480,24 @@ fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
};
|
||||
(mac, attrs, if add_semicolon { AddSemicolon::Yes } else { AddSemicolon::No })
|
||||
}
|
||||
fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
|
||||
match &self.kind {
|
||||
StmtKind::Item(item) => match &item.kind {
|
||||
ItemKind::DelegationMac(deleg) => Some((deleg, item)),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
|
||||
ItemKind::Delegation(deleg)
|
||||
}
|
||||
fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
|
||||
ast::Stmt { id: ast::DUMMY_NODE_ID, span: item.span, kind: StmtKind::Item(P(item)) }
|
||||
}
|
||||
fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
|
||||
items.flatten().collect()
|
||||
}
|
||||
fn post_flat_map_node_collect_bang(stmts: &mut Self::OutputTy, add_semicolon: AddSemicolon) {
|
||||
// If this is a macro invocation with a semicolon, then apply that
|
||||
// semicolon to the final statement produced by expansion.
|
||||
@ -1818,6 +1896,40 @@ fn flat_map_node<Node: InvocationCollectorNode<OutputTy: Default>>(
|
||||
Node::post_flat_map_node_collect_bang(&mut res, add_semicolon);
|
||||
res
|
||||
}
|
||||
None if let Some((deleg, item)) = node.delegation_list() => {
|
||||
if deleg.suffixes.is_empty() {
|
||||
// Report an error for now, to avoid keeping stem for resolution and
|
||||
// stability checks.
|
||||
self.cx.dcx().emit_err(EmptyDelegationList { span: item.span });
|
||||
}
|
||||
|
||||
Node::flatten_outputs(deleg.suffixes.iter().map(|&(ident, rename)| {
|
||||
let mut path = deleg.prefix.clone();
|
||||
path.segments.push(ast::PathSegment {
|
||||
ident,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
args: None,
|
||||
});
|
||||
|
||||
let mut item = Node::from_item(ast::Item {
|
||||
attrs: item.attrs.clone(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: ident.span,
|
||||
vis: item.vis.clone(),
|
||||
ident: rename.unwrap_or(ident),
|
||||
kind: Node::delegation_item_kind(Box::new(ast::Delegation {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
qself: deleg.qself.clone(),
|
||||
path,
|
||||
rename,
|
||||
body: deleg.body.clone(),
|
||||
})),
|
||||
tokens: None,
|
||||
});
|
||||
|
||||
assign_id!(self, item.node_id_mut(), || item.noop_flat_map(self))
|
||||
}))
|
||||
}
|
||||
None => {
|
||||
match Node::wrap_flat_map_node_noop_flat_map(node, self, |mut node, this| {
|
||||
assign_id!(this, node.node_id_mut(), || node.noop_flat_map(this))
|
||||
@ -1866,6 +1978,7 @@ fn visit_node<Node: InvocationCollectorNode<OutputTy = Node> + DummyAstNode>(
|
||||
self.collect_bang(mac, Node::KIND).make_ast::<Node>()
|
||||
})
|
||||
}
|
||||
None if node.delegation_list().is_some() => unreachable!(),
|
||||
None => {
|
||||
assign_id!(self, node.node_id_mut(), || node.noop_visit(self))
|
||||
}
|
||||
|
@ -685,20 +685,35 @@ fn parse_item_delegation(&mut self) -> PResult<'a, ItemInfo> {
|
||||
(None, self.parse_path(PathStyle::Expr)?)
|
||||
};
|
||||
|
||||
let rename = if self.eat_keyword(kw::As) { Some(self.parse_ident()?) } else { None };
|
||||
|
||||
let body = if self.check(&token::OpenDelim(Delimiter::Brace)) {
|
||||
Some(self.parse_block()?)
|
||||
} else {
|
||||
self.expect(&token::Semi)?;
|
||||
None
|
||||
let rename = |this: &mut Self| {
|
||||
Ok(if this.eat_keyword(kw::As) { Some(this.parse_ident()?) } else { None })
|
||||
};
|
||||
let body = |this: &mut Self| {
|
||||
Ok(if this.check(&token::OpenDelim(Delimiter::Brace)) {
|
||||
Some(this.parse_block()?)
|
||||
} else {
|
||||
this.expect(&token::Semi)?;
|
||||
None
|
||||
})
|
||||
};
|
||||
|
||||
let (ident, item_kind) = if self.eat(&token::PathSep) {
|
||||
let (suffixes, _) = self.parse_delim_comma_seq(Delimiter::Brace, |p| {
|
||||
Ok((p.parse_path_segment_ident()?, rename(p)?))
|
||||
})?;
|
||||
let deleg = DelegationMac { qself, prefix: path, suffixes, body: body(self)? };
|
||||
(Ident::empty(), ItemKind::DelegationMac(Box::new(deleg)))
|
||||
} else {
|
||||
let rename = rename(self)?;
|
||||
let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
|
||||
let deleg = Delegation { id: DUMMY_NODE_ID, qself, path, rename, body: body(self)? };
|
||||
(ident, ItemKind::Delegation(Box::new(deleg)))
|
||||
};
|
||||
|
||||
let span = span.to(self.prev_token.span);
|
||||
self.psess.gated_spans.gate(sym::fn_delegation, span);
|
||||
|
||||
let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
|
||||
let deleg = Delegation { id: DUMMY_NODE_ID, qself, path, rename, body };
|
||||
Ok((ident, ItemKind::Delegation(Box::new(deleg))))
|
||||
Ok((ident, item_kind))
|
||||
}
|
||||
|
||||
fn parse_item_list<T>(
|
||||
|
@ -95,12 +95,15 @@ pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (P<QSelf>,
|
||||
debug!("parse_qpath: (decrement) count={:?}", self.unmatched_angle_bracket_count);
|
||||
}
|
||||
|
||||
if !self.recover_colon_before_qpath_proj() {
|
||||
let is_import_coupler = self.is_import_coupler();
|
||||
if !is_import_coupler && !self.recover_colon_before_qpath_proj() {
|
||||
self.expect(&token::PathSep)?;
|
||||
}
|
||||
|
||||
let qself = P(QSelf { ty, path_span, position: path.segments.len() });
|
||||
self.parse_path_segments(&mut path.segments, style, None)?;
|
||||
if !is_import_coupler {
|
||||
self.parse_path_segments(&mut path.segments, style, None)?;
|
||||
}
|
||||
|
||||
Ok((
|
||||
qself,
|
||||
|
@ -522,7 +522,8 @@ fn visit_item(&mut self, i: &'v ast::Item) {
|
||||
Impl,
|
||||
MacCall,
|
||||
MacroDef,
|
||||
Delegation
|
||||
Delegation,
|
||||
DelegationMac
|
||||
]
|
||||
);
|
||||
ast_visit::walk_item(self, i)
|
||||
@ -650,7 +651,7 @@ fn visit_fn(&mut self, fk: ast_visit::FnKind<'v>, _: Span, _: NodeId) {
|
||||
fn visit_assoc_item(&mut self, i: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
|
||||
record_variants!(
|
||||
(self, i, i.kind, Id::None, ast, AssocItem, AssocItemKind),
|
||||
[Const, Fn, Type, MacCall, Delegation]
|
||||
[Const, Fn, Type, MacCall, Delegation, DelegationMac]
|
||||
);
|
||||
ast_visit::walk_assoc_item(self, i, ctxt);
|
||||
}
|
||||
|
@ -285,7 +285,9 @@ fn visit_item(&mut self, i: &'ast ast::Item) {
|
||||
ast::ItemKind::TraitAlias(_, _) => Target::TraitAlias,
|
||||
ast::ItemKind::Impl(_) => Target::Impl,
|
||||
ast::ItemKind::MacroDef(_) => Target::MacroDef,
|
||||
ast::ItemKind::MacCall(_) => unreachable!("macros should have been expanded"),
|
||||
ast::ItemKind::MacCall(_) | ast::ItemKind::DelegationMac(_) => {
|
||||
unreachable!("macros should have been expanded")
|
||||
}
|
||||
};
|
||||
|
||||
self.check_for_lang(
|
||||
@ -340,7 +342,9 @@ fn visit_assoc_item(&mut self, i: &'ast ast::AssocItem, ctxt: visit::AssocCtxt)
|
||||
}
|
||||
ast::AssocItemKind::Const(ct) => (Target::AssocConst, Some(&ct.generics)),
|
||||
ast::AssocItemKind::Type(ty) => (Target::AssocTy, Some(&ty.generics)),
|
||||
ast::AssocItemKind::MacCall(_) => unreachable!("macros should have been expanded"),
|
||||
ast::AssocItemKind::MacCall(_) | ast::AssocItemKind::DelegationMac(_) => {
|
||||
unreachable!("macros should have been expanded")
|
||||
}
|
||||
};
|
||||
|
||||
self.check_for_lang(
|
||||
|
@ -825,7 +825,9 @@ fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
|
||||
}
|
||||
ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
|
||||
|
||||
ItemKind::MacroDef(..) | ItemKind::MacCall(_) => unreachable!(),
|
||||
ItemKind::MacroDef(..) | ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1381,7 +1383,7 @@ fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) {
|
||||
| AssocItemKind::Delegation(..)
|
||||
| AssocItemKind::Fn(..) => ValueNS,
|
||||
AssocItemKind::Type(..) => TypeNS,
|
||||
AssocItemKind::MacCall(_) => bug!(), // handled above
|
||||
AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => bug!(), // handled above
|
||||
};
|
||||
|
||||
let parent = self.parent_scope.module;
|
||||
|
@ -139,6 +139,7 @@ fn visit_item(&mut self, i: &'a Item) {
|
||||
ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
|
||||
ItemKind::Use(..) => return visit::walk_item(self, i),
|
||||
ItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
|
||||
ItemKind::DelegationMac(..) => unreachable!(),
|
||||
};
|
||||
let def_id = self.create_def(i.id, i.ident.name, def_kind, i.span);
|
||||
|
||||
@ -278,6 +279,7 @@ fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
|
||||
AssocItemKind::Const(..) => DefKind::AssocConst,
|
||||
AssocItemKind::Type(..) => DefKind::AssocTy,
|
||||
AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
|
||||
AssocItemKind::DelegationMac(..) => unreachable!(),
|
||||
};
|
||||
|
||||
let def = self.create_def(i.id, i.ident.name, def_kind, i.span);
|
||||
|
@ -236,7 +236,7 @@ fn visit_item(&mut self, item: &'ast ast::Item) {
|
||||
ast::ItemKind::Impl(..) => return,
|
||||
|
||||
// Should be unreachable at this stage
|
||||
ast::ItemKind::MacCall(..) => panic!(
|
||||
ast::ItemKind::MacCall(..) | ast::ItemKind::DelegationMac(..) => panic!(
|
||||
"ast::ItemKind::MacCall encountered, this should not anymore appear at this stage"
|
||||
),
|
||||
|
||||
|
@ -2561,7 +2561,9 @@ fn resolve_item(&mut self, item: &'ast Item) {
|
||||
|
||||
ItemKind::ExternCrate(..) => {}
|
||||
|
||||
ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"),
|
||||
ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => {
|
||||
panic!("unexpanded macro in resolve!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2849,7 +2851,7 @@ fn resolve_trait_items(&mut self, trait_items: &'ast [P<AssocItem>]) {
|
||||
.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
|
||||
walk_assoc_item(this, generics, LifetimeBinderKind::Item, item)
|
||||
}),
|
||||
AssocItemKind::MacCall(_) => {
|
||||
AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => {
|
||||
panic!("unexpanded macro in resolve!")
|
||||
}
|
||||
};
|
||||
@ -3116,7 +3118,7 @@ fn resolve_impl_item(
|
||||
},
|
||||
);
|
||||
}
|
||||
AssocItemKind::MacCall(_) => {
|
||||
AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => {
|
||||
panic!("unexpanded macro in resolve!")
|
||||
}
|
||||
}
|
||||
@ -3218,7 +3220,9 @@ fn check_trait_item<F>(
|
||||
AssocItemKind::Fn(..) => (E0324, "method"),
|
||||
AssocItemKind::Type(..) => (E0325, "type"),
|
||||
AssocItemKind::Delegation(..) => (E0324, "method"),
|
||||
AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"),
|
||||
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
|
||||
span_bug!(span, "unexpanded macro")
|
||||
}
|
||||
};
|
||||
let trait_path = path_names_to_string(path);
|
||||
self.report_error(
|
||||
@ -4790,7 +4794,8 @@ fn visit_item(&mut self, item: &'ast Item) {
|
||||
| ItemKind::ExternCrate(..)
|
||||
| ItemKind::MacroDef(..)
|
||||
| ItemKind::GlobalAsm(..)
|
||||
| ItemKind::MacCall(..) => {}
|
||||
| ItemKind::MacCall(..)
|
||||
| ItemKind::DelegationMac(..) => {}
|
||||
ItemKind::Delegation(..) => {
|
||||
// Delegated functions have lifetimes, their count is not necessarily zero.
|
||||
// But skipping the delegation items here doesn't mean that the count will be considered zero,
|
||||
|
@ -2045,7 +2045,9 @@ fn extract_node_id(t: &Ty) -> Option<NodeId> {
|
||||
AssocSuggestion::MethodWithSelf { called }
|
||||
}
|
||||
ast::AssocItemKind::Delegation(..) => AssocSuggestion::AssocFn { called },
|
||||
ast::AssocItemKind::MacCall(_) => continue,
|
||||
ast::AssocItemKind::MacCall(_) | ast::AssocItemKind::DelegationMac(..) => {
|
||||
continue;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -739,8 +739,8 @@ fn visit_impl_items(&mut self, items: &[ptr::P<ast::AssocItem>]) {
|
||||
(_, Const(..)) => Ordering::Greater,
|
||||
(MacCall(..), _) => Ordering::Less,
|
||||
(_, MacCall(..)) => Ordering::Greater,
|
||||
(Delegation(..), _) => Ordering::Less,
|
||||
(_, Delegation(..)) => Ordering::Greater,
|
||||
(Delegation(..), _) | (DelegationMac(..), _) => Ordering::Less,
|
||||
(_, Delegation(..)) | (_, DelegationMac(..)) => Ordering::Greater,
|
||||
});
|
||||
let mut prev_kind = None;
|
||||
for (buf, item) in buffer {
|
||||
|
@ -586,7 +586,7 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
|
||||
);
|
||||
self.push_rewrite(item.span, rewrite);
|
||||
}
|
||||
ast::ItemKind::Delegation(..) => {
|
||||
ast::ItemKind::Delegation(..) | ast::ItemKind::DelegationMac(..) => {
|
||||
// TODO: rewrite delegation items once syntax is established.
|
||||
// For now, leave the contents of the Span unformatted.
|
||||
self.push_rewrite(item.span, None)
|
||||
|
@ -36,4 +36,8 @@ impl Trait for S {
|
||||
//~^ ERROR cannot find function `foo` in this scope
|
||||
}
|
||||
|
||||
mod prefix {}
|
||||
reuse unresolved_prefix::{a, b, c}; //~ ERROR use of undeclared crate or module `unresolved_prefix`
|
||||
reuse prefix::{self, super, crate}; //~ ERROR `crate` in paths can only be used in start position
|
||||
|
||||
fn main() {}
|
||||
|
@ -63,7 +63,19 @@ LL | type Type;
|
||||
LL | impl Trait for S {
|
||||
| ^^^^^^^^^^^^^^^^ missing `Type` in implementation
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error[E0433]: failed to resolve: use of undeclared crate or module `unresolved_prefix`
|
||||
--> $DIR/bad-resolve.rs:40:7
|
||||
|
|
||||
LL | reuse unresolved_prefix::{a, b, c};
|
||||
| ^^^^^^^^^^^^^^^^^ use of undeclared crate or module `unresolved_prefix`
|
||||
|
||||
Some errors have detailed explanations: E0046, E0324, E0407, E0423, E0425, E0575, E0576.
|
||||
error[E0433]: failed to resolve: `crate` in paths can only be used in start position
|
||||
--> $DIR/bad-resolve.rs:41:29
|
||||
|
|
||||
LL | reuse prefix::{self, super, crate};
|
||||
| ^^^^^ `crate` in paths can only be used in start position
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0046, E0324, E0407, E0423, E0425, E0433, E0575, E0576.
|
||||
For more information about an error, try `rustc --explain E0046`.
|
||||
|
32
tests/ui/delegation/body-identity-list.rs
Normal file
32
tests/ui/delegation/body-identity-list.rs
Normal file
@ -0,0 +1,32 @@
|
||||
//@ check-pass
|
||||
|
||||
#![feature(fn_delegation)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
fn foo(&self) {}
|
||||
fn bar(&self) {}
|
||||
}
|
||||
|
||||
impl Trait for u8 {}
|
||||
|
||||
struct S(u8);
|
||||
|
||||
mod to_import {
|
||||
pub fn check(arg: &u8) -> &u8 { arg }
|
||||
}
|
||||
|
||||
impl Trait for S {
|
||||
reuse Trait::{foo, bar} {
|
||||
use to_import::check;
|
||||
|
||||
let _arr = Some(self.0).map(|x| [x * 2; 3]);
|
||||
check(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = S(0);
|
||||
s.foo();
|
||||
s.bar();
|
||||
}
|
8
tests/ui/delegation/empty-list.rs
Normal file
8
tests/ui/delegation/empty-list.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#![feature(fn_delegation)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
mod m {}
|
||||
|
||||
reuse m::{}; //~ ERROR empty list delegation is not supported
|
||||
|
||||
fn main() {}
|
8
tests/ui/delegation/empty-list.stderr
Normal file
8
tests/ui/delegation/empty-list.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
error: empty list delegation is not supported
|
||||
--> $DIR/empty-list.rs:6:1
|
||||
|
|
||||
LL | reuse m::{};
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
8
tests/ui/delegation/inner-attr.rs
Normal file
8
tests/ui/delegation/inner-attr.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#![feature(fn_delegation)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
fn a() {}
|
||||
|
||||
reuse a as b { #![rustc_dummy] self } //~ ERROR an inner attribute is not permitted in this context
|
||||
|
||||
fn main() {}
|
18
tests/ui/delegation/inner-attr.stderr
Normal file
18
tests/ui/delegation/inner-attr.stderr
Normal file
@ -0,0 +1,18 @@
|
||||
error: an inner attribute is not permitted in this context
|
||||
--> $DIR/inner-attr.rs:6:16
|
||||
|
|
||||
LL | reuse a as b { #![rustc_dummy] self }
|
||||
| ^^^^^^^^^^^^^^^
|
||||
LL |
|
||||
LL | fn main() {}
|
||||
| ------------ the inner attribute doesn't annotate this function
|
||||
|
|
||||
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
|
||||
help: to annotate the function, change the attribute from inner to outer style
|
||||
|
|
||||
LL - reuse a as b { #![rustc_dummy] self }
|
||||
LL + reuse a as b { #[rustc_dummy] self }
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
46
tests/ui/delegation/list.rs
Normal file
46
tests/ui/delegation/list.rs
Normal file
@ -0,0 +1,46 @@
|
||||
//@ check-pass
|
||||
|
||||
#![feature(fn_delegation)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
fn foo(&self) -> u8 { 0 }
|
||||
fn bar(&self) -> u8 { 1 }
|
||||
}
|
||||
|
||||
impl Trait for u8 {}
|
||||
|
||||
struct S(u8);
|
||||
struct Z(u8);
|
||||
|
||||
impl Trait for S {
|
||||
reuse Trait::{foo, bar} { &self.0 }
|
||||
}
|
||||
|
||||
impl Trait for Z {
|
||||
reuse <u8 as Trait>::{foo, bar} { &self.0 }
|
||||
}
|
||||
|
||||
trait Trait2 where Self: Trait {
|
||||
reuse Trait::{foo, bar};
|
||||
}
|
||||
|
||||
mod to_reuse {
|
||||
pub fn a() {}
|
||||
pub fn b() {}
|
||||
}
|
||||
|
||||
reuse to_reuse::{a, b};
|
||||
|
||||
fn main() {
|
||||
let s = S(2);
|
||||
s.foo();
|
||||
s.bar();
|
||||
|
||||
let z = Z(3);
|
||||
z.foo();
|
||||
z.bar();
|
||||
|
||||
a();
|
||||
b();
|
||||
}
|
26
tests/ui/delegation/macro-inside-list.rs
Normal file
26
tests/ui/delegation/macro-inside-list.rs
Normal file
@ -0,0 +1,26 @@
|
||||
//@ check-pass
|
||||
|
||||
#![feature(fn_delegation)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
fn foo(&self) -> u8 { 0 }
|
||||
fn bar(&self) -> u8 { 1 }
|
||||
}
|
||||
|
||||
impl Trait for u8 {}
|
||||
|
||||
struct S(u8);
|
||||
|
||||
// Macro expansion works inside delegation items.
|
||||
macro_rules! u8 { () => { u8 } }
|
||||
macro_rules! self_0 { () => { &self.0 } }
|
||||
impl Trait for S {
|
||||
reuse <u8!() as Trait>::{foo, bar} { self_0!() }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = S(2);
|
||||
s.foo();
|
||||
s.bar();
|
||||
}
|
@ -5,16 +5,23 @@
|
||||
|
||||
mod to_reuse {
|
||||
pub fn a() {}
|
||||
pub fn b() {}
|
||||
}
|
||||
|
||||
reuse to_reuse::a as b;
|
||||
reuse to_reuse::a as x;
|
||||
reuse to_reuse::{a as y, b as z};
|
||||
|
||||
struct S;
|
||||
impl S {
|
||||
reuse to_reuse::a as b;
|
||||
reuse to_reuse::a as x;
|
||||
reuse to_reuse::{a as y, b as z};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
b();
|
||||
S::b();
|
||||
x();
|
||||
y();
|
||||
z();
|
||||
S::x();
|
||||
S::y();
|
||||
S::z();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user