diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 1c4c5728b04a4..01503f05f0ca2 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -3003,10 +3003,11 @@ pub struct Fn {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Delegation {
+ /// Path resolution id.
pub id: NodeId,
- pub path: (Option
>, Path),
- pub target_expr: Option
>,
- pub span: Span,
+ pub qself: Option
>,
+ pub path: Path,
+ pub body: Option
>,
}
#[derive(Clone, Encodable, Decodable, Debug)]
@@ -3131,7 +3132,7 @@ impl ItemKind {
ItemKind::MacCall(..) => "item macro invocation",
ItemKind::MacroDef(..) => "macro definition",
ItemKind::Impl { .. } => "implementation",
- ItemKind::Delegation(..) => "delegation",
+ ItemKind::Delegation(..) => "delegated function",
}
}
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index 2b5377c3457dd..4dc9c30a2c807 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -5,7 +5,7 @@
use crate::ptr::P;
use crate::token::Nonterminal;
use crate::tokenstream::LazyAttrTokenStream;
-use crate::{Arm, Crate, Delegation, ExprField, FieldDef, GenericParam, Param, PatField, Variant};
+use crate::{Arm, Crate, ExprField, FieldDef, GenericParam, Param, PatField, Variant};
use crate::{AssocItem, Expr, ForeignItem, Item, NodeId};
use crate::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility};
use crate::{AttrVec, Attribute, Stmt, StmtKind};
@@ -80,7 +80,6 @@ impl_has_node_id!(
Stmt,
Ty,
Variant,
- Delegation
);
impl> HasNodeId for T {
@@ -109,19 +108,7 @@ macro_rules! impl_has_span {
};
}
-impl_has_span!(
- AssocItem,
- Block,
- Expr,
- ForeignItem,
- Item,
- Pat,
- Path,
- Stmt,
- Ty,
- Visibility,
- Delegation
-);
+impl_has_span!(AssocItem, Block, Expr, ForeignItem, Item, Pat, Path, Stmt, Ty, Visibility);
impl> HasSpan for T {
fn span(&self) -> Span {
@@ -172,7 +159,7 @@ macro_rules! impl_has_tokens_none {
}
impl_has_tokens!(AssocItem, AttrItem, Block, Expr, ForeignItem, Item, Pat, Path, Ty, Visibility);
-impl_has_tokens_none!(Arm, ExprField, FieldDef, GenericParam, Param, PatField, Variant, Delegation);
+impl_has_tokens_none!(Arm, ExprField, FieldDef, GenericParam, Param, PatField, Variant);
impl> HasTokens for T {
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index d16c2ee7aa1bf..c491fded88f72 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1119,10 +1119,10 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) {
ItemKind::MacroDef(def) => vis.visit_macro_def(def),
ItemKind::Delegation(box delegation) => {
vis.visit_id(&mut delegation.id);
- vis.visit_qself(&mut delegation.path.0);
- vis.visit_path(&mut delegation.path.1);
- if let Some(target_expr) = &mut delegation.target_expr {
- vis.visit_expr(target_expr);
+ vis.visit_qself(&mut delegation.qself);
+ vis.visit_path(&mut delegation.path);
+ if let Some(body) = &mut delegation.body {
+ vis.visit_block(body);
}
}
}
@@ -1165,10 +1165,10 @@ pub fn noop_flat_map_assoc_item(
AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
AssocItemKind::Delegation(box delegation) => {
visitor.visit_id(&mut delegation.id);
- visitor.visit_qself(&mut delegation.path.0);
- visitor.visit_path(&mut delegation.path.1);
- if let Some(target_expr) = &mut delegation.target_expr {
- visitor.visit_expr(target_expr);
+ visitor.visit_qself(&mut delegation.qself);
+ visitor.visit_path(&mut delegation.path);
+ if let Some(body) = &mut delegation.body {
+ visitor.visit_block(body);
}
}
}
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 2fca9724bbac3..eb0c1c67f0f6f 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -376,12 +376,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
ItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
ItemKind::MacroDef(ts) => visitor.visit_mac_def(ts, item.id),
ItemKind::Delegation(box delegation) => {
- if let Some(qself) = &delegation.path.0 {
+ if let Some(qself) = &delegation.qself {
visitor.visit_ty(&qself.ty);
}
- walk_path(visitor, &delegation.path.1);
- if let Some(target_expr) = &delegation.target_expr {
- visitor.visit_expr(target_expr);
+ walk_path(visitor, &delegation.path);
+ if let Some(body) = &delegation.body {
+ visitor.visit_block(body);
}
}
}
@@ -714,12 +714,12 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
visitor.visit_mac_call(mac);
}
AssocItemKind::Delegation(box delegation) => {
- if let Some(qself) = &delegation.path.0 {
+ if let Some(qself) = &delegation.qself {
visitor.visit_ty(&qself.ty);
}
- walk_path(visitor, &delegation.path.1);
- if let Some(target_expr) = &delegation.target_expr {
- visitor.visit_expr(target_expr);
+ walk_path(visitor, &delegation.path);
+ if let Some(body) = &delegation.body {
+ visitor.visit_block(body);
}
}
}
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index 97b0792e9e529..cc907fbcb6552 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -3,8 +3,7 @@ use crate::{ImplTraitPosition, ResolverAstLoweringExt};
use super::{ImplTraitContext, LoweringContext, ParamMode};
use ast::visit::Visitor;
-use hir::def::DefKind;
-use hir::def::PartialRes;
+use hir::def::{DefKind, PartialRes, Res};
use hir::{BodyId, HirId};
use rustc_ast as ast;
use rustc_ast::*;
@@ -24,13 +23,9 @@ pub struct DelegationResults<'hir> {
}
impl<'hir> LoweringContext<'_, 'hir> {
- pub fn delegation_has_self(&self, delegation: &Delegation) -> bool {
- let res_id = self.get_delegation_res_id(delegation.id);
+ pub fn delegation_has_self(&self, node_id: NodeId, span: Span) -> bool {
+ let res_id = self.get_delegation_res_id(node_id, span);
let Some(res_id) = res_id else {
- self.tcx.sess.span_delayed_bug(
- delegation.span,
- "LoweringContext: couldn't resolve delegation item",
- );
return false;
};
@@ -40,37 +35,50 @@ impl<'hir> LoweringContext<'_, 'hir> {
match self.tcx.def_kind(res_id) {
DefKind::Fn => false,
DefKind::AssocFn => self.tcx.associated_item(res_id).fn_has_self_parameter,
- _ => span_bug!(delegation.span, "unexpected DefKind for delegation item"),
+ _ => span_bug!(span, "unexpected DefKind for delegation item"),
}
}
}
- pub fn lower_delegation(&mut self, delegation: &Delegation) -> DelegationResults<'hir> {
- let res_id = self.get_delegation_res_id(delegation.id);
+ pub fn lower_delegation(
+ &mut self,
+ delegation: &Delegation,
+ node_id: NodeId,
+ span: Span,
+ ) -> DelegationResults<'hir> {
+ let res_id = self.get_delegation_res_id(node_id, span);
let Some(res_id) = res_id else {
- self.tcx.sess.span_delayed_bug(
- delegation.span,
- "LoweringContext: couldn't resolve delegation item",
- );
- return self.generate_delegation_error(delegation);
+ return self.generate_delegation_error(span);
};
- let decl = self.lower_delegation_decl(res_id, delegation.span);
- let sig = self.lower_delegation_sig(delegation.span, decl);
- let body_id = self.lower_delegation_body(sig.decl, delegation);
+ let decl = self.lower_delegation_decl(res_id, span);
+ let sig = self.lower_delegation_sig(span, decl);
+ let body_id = self.lower_delegation_body(sig.decl, delegation, node_id, span);
- let generics = self.lower_delegation_generics(delegation.span);
+ let generics = self.lower_delegation_generics(span);
DelegationResults { body_id, sig, generics }
}
- fn get_delegation_res_id(&self, node_id: NodeId) -> Option {
- self.resolver.get_partial_res(node_id).map(|r| r.base_res().opt_def_id()).unwrap_or(None)
+ fn get_delegation_res_id(&self, node_id: NodeId, span: Span) -> Option {
+ let res = self
+ .resolver
+ .get_partial_res(node_id)
+ .map(|or| or.full_res().map(|r| r.opt_def_id()).unwrap_or(None))
+ .unwrap_or(None);
+
+ if res.is_none() {
+ self.tcx
+ .sess
+ .span_delayed_bug(span, "LoweringContext: couldn't resolve delegation item");
+ }
+
+ res
}
fn lower_delegation_generics(&mut self, span: Span) -> &'hir hir::Generics<'hir> {
self.arena.alloc(hir::Generics {
- params: self.arena.alloc_from_iter([]),
- predicates: self.arena.alloc_from_iter([]),
+ params: &[],
+ predicates: &[],
has_where_clause_predicates: false,
where_clause_span: span,
span,
@@ -78,20 +86,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
fn lower_delegation_decl(&mut self, res_id: DefId, span: Span) -> &'hir hir::FnDecl<'hir> {
- let args_count = if res_id.is_local() {
- self.resolver.fns_arguments_count[&res_id]
+ let args_count = if let Some(local_res_id) = res_id.as_local() {
+ // Map may be filled incorrectly due to recursive delegation.
+ // Error will be emmited later in astconv.
+ self.resolver.fn_parameter_counts.get(&local_res_id).cloned().unwrap_or_default()
} else {
self.tcx.fn_arg_names(res_id).len()
};
let inputs = self.arena.alloc_from_iter((0..args_count).into_iter().map(|arg| hir::Ty {
hir_id: self.next_id(),
- kind: hir::TyKind::InferDelegation(res_id, hir::InferDelegationVar::Input(arg)),
+ kind: hir::TyKind::InferDelegation(res_id, hir::InferDelegationKind::Input(arg)),
span,
}));
let output = self.arena.alloc(hir::Ty {
hir_id: self.next_id(),
- kind: hir::TyKind::InferDelegation(res_id, hir::InferDelegationVar::Output),
+ kind: hir::TyKind::InferDelegation(res_id, hir::InferDelegationKind::Output),
span,
});
@@ -138,16 +148,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment {
ident: Ident::empty(),
hir_id: self.next_id(),
- res: hir::def::Res::Local(param_id),
+ res: Res::Local(param_id),
args: None,
infer_args: false,
}));
- let path = self.arena.alloc(hir::Path {
- span: ty.span,
- res: hir::def::Res::Local(param_id),
- segments,
- });
+ let path =
+ self.arena.alloc(hir::Path { span: ty.span, res: Res::Local(param_id), segments });
hir::Expr {
hir_id: self.next_id(),
@@ -160,17 +167,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
&mut self,
decl: &'hir hir::FnDecl<'hir>,
delegation: &Delegation,
+ node_id: NodeId,
+ span: Span,
) -> BodyId {
- let (qself, path) = &delegation.path;
+ let path_id = if self.is_in_trait_impl { delegation.id } else { node_id };
let path = self.lower_qpath(
- delegation.id,
- qself,
- path,
+ path_id,
+ &delegation.qself,
+ &delegation.path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
- let expr = delegation.target_expr.as_deref();
+ let block = delegation.body.as_deref();
self.lower_body(|this| {
let mut parameters: Vec> = Vec::new();
@@ -180,18 +189,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (param, pat_node_id) = this.generate_param(param_ty);
parameters.push(param);
- if idx != 0 || expr.is_none() {
- let pat_hir_id = this.lower_node_id(pat_node_id);
- let arg = this.generate_arg(param_ty, pat_hir_id);
- args.push(arg);
+ let arg = if let Some(block) = block
+ && idx == 0
+ {
+ let mut self_resolver = SelfResolver {
+ resolver: this.resolver,
+ delegation_id: delegation.id,
+ self_param_id: pat_node_id,
+ };
+ self_resolver.visit_block(block);
+ let block = this.lower_block(block, false);
+ hir::Expr {
+ hir_id: this.next_id(),
+ kind: hir::ExprKind::Block(block, None),
+ span,
+ }
} else {
- let expr = expr.unwrap();
- let mut self_resolver =
- SelfResolver { res_id: pat_node_id, resolver: this.resolver };
- self_resolver.visit_expr(expr);
- let target_expr = this.lower_expr_mut(expr);
- args.push(target_expr);
+ let pat_hir_id = this.lower_node_id(pat_node_id);
+ this.generate_arg(param_ty, pat_hir_id)
};
+ args.push(arg);
}
let args = self.arena.alloc_from_iter(args);
@@ -218,7 +235,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
});
let block = self.arena.alloc(hir::Block {
- stmts: self.arena.alloc_from_iter([]),
+ stmts: &[],
expr: Some(expr),
hir_id: self.next_id(),
rules: hir::BlockCheckMode::DefaultBlock,
@@ -233,29 +250,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}
- fn generate_delegation_error(&mut self, delegation: &Delegation) -> DelegationResults<'hir> {
- let generics = self.lower_delegation_generics(delegation.span);
+ fn generate_delegation_error(&mut self, span: Span) -> DelegationResults<'hir> {
+ let generics = self.lower_delegation_generics(span);
let decl = self.arena.alloc(hir::FnDecl {
- inputs: self.arena.alloc_from_iter([]),
- output: hir::FnRetTy::DefaultReturn(delegation.span),
+ inputs: &[],
+ output: hir::FnRetTy::DefaultReturn(span),
c_variadic: false,
lifetime_elision_allowed: true,
implicit_self: hir::ImplicitSelfKind::None,
});
- let sig = self.lower_delegation_sig(delegation.span, decl);
+ let sig = self.lower_delegation_sig(span, decl);
let body_id = self.lower_body(|this| {
- let err = this.tcx.sess.span_delayed_bug(
- delegation.span,
- "LoweringContext: couldn't resolve delegation item",
- );
- let expr = hir::Expr {
- hir_id: this.next_id(),
- kind: hir::ExprKind::Err(err),
- span: delegation.span,
- };
- (this.arena.alloc_from_iter([]), expr)
+ let err = this
+ .tcx
+ .sess
+ .span_delayed_bug(span, "LoweringContext: couldn't resolve delegation item");
+ let expr = hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span };
+ (&[], expr)
});
DelegationResults { generics, body_id, sig }
}
@@ -263,15 +276,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
struct SelfResolver<'a> {
resolver: &'a mut ResolverAstLowering,
- res_id: NodeId,
+ delegation_id: NodeId,
+ self_param_id: NodeId,
+}
+
+impl<'a> SelfResolver<'a> {
+ fn try_replace_id(&mut self, id: NodeId) {
+ if let Some(res) = self.resolver.partial_res_map.get(&id)
+ && let Some(Res::Local(res_id)) = res.full_res()
+ && res_id == self.delegation_id
+ {
+ let new_res = PartialRes::new(Res::Local(self.self_param_id));
+ self.resolver.partial_res_map.insert(id, new_res);
+ }
+ }
}
-impl<'ast, 'a> ast::visit::Visitor<'ast> for SelfResolver<'a> {
+impl<'ast, 'a> Visitor<'ast> for SelfResolver<'a> {
fn visit_path(&mut self, path: &'ast Path, id: NodeId) {
- if path.segments.len() == 1 && path.segments[0].ident.name == kw::SelfLower {
- let res = PartialRes::new(hir::def::Res::Local(self.res_id));
- self.resolver.partial_res_map.insert(id, res);
- self.resolver.partial_res_map.insert(path.segments[0].id, res);
+ self.try_replace_id(id);
+ visit::walk_path(self, path);
+ }
+
+ fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) {
+ if kw::SelfLower == path_segment.ident.name {
+ self.try_replace_id(path_segment.id);
}
}
}
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index d7dd58dc6671f..4d24b3eb9899c 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -432,16 +432,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules });
hir::ItemKind::Macro(macro_def, macro_kind)
}
- ItemKind::Delegation(box delegation) => self.with_new_scopes(ident.span, |this| {
- this.current_item = Some(ident.span);
-
- let delegation_results = this.lower_delegation(delegation);
+ ItemKind::Delegation(box delegation) => {
+ let delegation_results = self.lower_delegation(delegation, id, span);
hir::ItemKind::Fn(
delegation_results.sig,
delegation_results.generics,
delegation_results.body_id,
)
- }),
+ }
ItemKind::MacCall(..) => {
panic!("`TyMac` should have been expanded by now")
}
@@ -803,15 +801,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
(generics, kind, ty.is_some())
}
AssocItemKind::Delegation(box delegation) => {
- let delegation_results = self.lower_delegation(delegation);
- (
- delegation_results.generics,
- hir::TraitItemKind::Fn(
- delegation_results.sig,
- hir::TraitFn::Provided(delegation_results.body_id),
- ),
- true,
- )
+ let delegation_results = self.lower_delegation(delegation, i.id, i.span);
+ let item_kind = hir::TraitItemKind::Fn(
+ delegation_results.sig,
+ hir::TraitFn::Provided(delegation_results.body_id),
+ );
+ (delegation_results.generics, item_kind, true)
}
AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
};
@@ -834,8 +829,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
AssocItemKind::Fn(box Fn { sig, .. }) => {
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
}
- AssocItemKind::Delegation(box delegation) => {
- hir::AssocItemKind::Fn { has_self: self.delegation_has_self(delegation) }
+ AssocItemKind::Delegation(..) => {
+ hir::AssocItemKind::Fn { has_self: self.delegation_has_self(i.id, i.span) }
}
AssocItemKind::MacCall(..) => unimplemented!(),
};
@@ -920,7 +915,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
}
AssocItemKind::Delegation(box delegation) => {
- let delegation_results = self.lower_delegation(delegation);
+ let delegation_results = self.lower_delegation(delegation, i.id, i.span);
(
delegation_results.generics,
hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
@@ -952,15 +947,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
AssocItemKind::Fn(box Fn { sig, .. }) => {
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
}
- AssocItemKind::Delegation(box delegation) => {
- hir::AssocItemKind::Fn { has_self: self.delegation_has_self(delegation) }
+ AssocItemKind::Delegation(..) => {
+ hir::AssocItemKind::Fn { has_self: self.delegation_has_self(i.id, i.span) }
}
AssocItemKind::MacCall(..) => unimplemented!(),
},
trait_item_def_id: self
.resolver
.get_partial_res(i.id)
- .map(|r| r.expect_full_res().def_id()),
+ .map(|or| or.full_res().map(|r| r.opt_def_id()).unwrap_or(None))
+ .unwrap_or(None),
}
}
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index e22759ae31364..18a39a703d4da 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -574,7 +574,7 @@ impl<'a> State<'a> {
pub(crate) fn print_delegation(&mut self, delegation: &ast::Delegation) {
self.ibox(0);
self.word_space("reuse");
- let (qself, path, expr) = (&delegation.path.0, &delegation.path.1, &delegation.target_expr);
+ let (qself, path, body) = (&delegation.qself, &delegation.path, &delegation.body);
if let Some(qself) = qself {
self.print_qpath(path, qself.ast_deref(), false);
@@ -582,9 +582,9 @@ impl<'a> State<'a> {
self.print_path(path, false, 0);
}
self.space();
- if let Some(target_expr) = expr {
+ if let Some(body) = body {
self.word_space("{");
- self.print_expr(target_expr.ast_deref(), FixupContext::default());
+ self.print_block(body.ast_deref());
self.word(" }");
} else {
self.word(";");
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 58126340e2d77..c7f69164ab26b 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2522,7 +2522,7 @@ pub enum OpaqueTyOrigin {
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)]
-pub enum InferDelegationVar {
+pub enum InferDelegationKind {
Input(usize),
Output,
}
@@ -2530,7 +2530,8 @@ pub enum InferDelegationVar {
/// The various kinds of types recognized by the compiler.
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum TyKind<'hir> {
- InferDelegation(DefId, InferDelegationVar),
+ /// Actual type should be inherited from `DefId` signature
+ InferDelegation(DefId, InferDelegationKind),
/// A variable length slice (i.e., `[T]`).
Slice(&'hir Ty<'hir>),
/// A fixed length array (i.e., `[T; n]`).
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 348cdfb0a291b..35798b7618bbc 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -264,7 +264,7 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation
hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
hir_analysis_not_supported_delegation =
- delegation with {$descr} is not supported yet
+ {$descr} is not supported yet
.label = callee defined here
hir_analysis_only_current_traits_arbitrary = only traits defined in the current crate can be implemented for arbitrary types
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 4d0ac9d46a87d..2cd5642abd17d 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2332,66 +2332,66 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
fn check_delegation_constraints(&self, res_id: DefId, span: Span, emit: bool) -> bool {
+ #[inline]
+ fn generics_param_count(param_count: ty::GenericParamCount) -> usize {
+ param_count.lifetimes + param_count.types + param_count.consts
+ }
+
let mut error_occured = false;
- let mut try_emit = |error| {
+ let res_span = self.tcx().def_span(res_id);
+ let mut try_emit = |descr| {
if emit {
- self.tcx().sess.emit_err(error);
+ self.tcx().sess.emit_err(crate::errors::NotSupportedDelegation {
+ span,
+ descr,
+ res_span,
+ });
}
error_occured = true;
};
- let res_span = self.tcx().def_span(res_id);
+
+ if let Some(node) = self.tcx().hir().get_if_local(res_id)
+ && let Some(decl) = node.fn_decl()
+ && let hir::FnRetTy::Return(ty) = decl.output
+ {
+ match ty.kind {
+ hir::TyKind::InferDelegation(_, _) => try_emit("recursive delegation"),
+ hir::TyKind::OpaqueDef(_, _, _) => {
+ try_emit("delegation to a function with opaque type")
+ }
+ _ => {}
+ }
+ }
let res_generics = self.tcx().generics_of(res_id);
let parent = self.tcx().parent(self.item_def_id());
let parent_generics = self.tcx().generics_of(parent);
let self_ty_bias = (self.tcx().def_kind(parent) == DefKind::Trait) as usize;
- if parent_generics.count() + res_generics.own_counts().count() > self_ty_bias {
- try_emit(super::errors::NotSupportedDelegation {
- span,
- descr: "early bound generics",
- res_span,
- });
+ if parent_generics.count() + generics_param_count(res_generics.own_counts()) > self_ty_bias
+ {
+ try_emit("delegation with early bound generics");
}
+
if self.tcx().asyncness(res_id) == ty::Asyncness::Yes {
- try_emit(super::errors::NotSupportedDelegation {
- span,
- descr: "async functions",
- res_span,
- });
+ try_emit("delegation to async functions");
}
if self.tcx().constness(res_id) == hir::Constness::Const {
- try_emit(super::errors::NotSupportedDelegation {
- span,
- descr: "const functions",
- res_span,
- });
+ try_emit("delegation to const functions");
}
let res_sig = self.tcx().fn_sig(res_id).instantiate_identity();
if res_sig.c_variadic() {
- try_emit(super::errors::NotSupportedDelegation {
- span,
- descr: "variadic functions",
- res_span,
- });
+ try_emit("delegation to variadic functions");
return error_occured;
}
if let hir::Unsafety::Unsafe = res_sig.unsafety() {
- try_emit(super::errors::NotSupportedDelegation {
- span,
- descr: "unsafe functions",
- res_span,
- });
+ try_emit("delegation to unsafe functions");
}
if abi::Abi::Rust != res_sig.abi() {
- try_emit(super::errors::NotSupportedDelegation {
- span,
- descr: "non Rust ABI functions",
- res_span,
- });
+ try_emit("delegation to non Rust ABI functions");
}
error_occured
@@ -2400,10 +2400,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
fn ty_from_delegation(
&self,
res_id: DefId,
- idx: hir::InferDelegationVar,
+ idx: hir::InferDelegationKind,
span: Span,
) -> Ty<'tcx> {
- if self.check_delegation_constraints(res_id, span, idx == hir::InferDelegationVar::Output) {
+ if self.check_delegation_constraints(res_id, span, idx == hir::InferDelegationKind::Output)
+ {
let e = self.tcx().sess.span_delayed_bug(span, "not supported delegation case");
self.set_tainted_by_errors(e);
return Ty::new_error(self.tcx(), e);
@@ -2411,26 +2412,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let res_sig = self.tcx().fn_sig(res_id);
let parent = self.tcx().parent(self.item_def_id());
- let item_def_kind = self.tcx().def_kind(self.item_def_id());
let parent_def_kind = self.tcx().def_kind(parent);
- let res_sig = match (item_def_kind, parent_def_kind) {
- (DefKind::AssocFn, DefKind::Impl { of_trait: true }) => {
- let self_ty = self.tcx().type_of(parent).instantiate_identity();
- let generic_self_ty = ty::GenericArg::from(self_ty);
- let substs = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty));
- res_sig.instantiate(self.tcx(), substs).skip_binder()
- }
- (DefKind::Fn, _) | (DefKind::AssocFn, _) => {
- res_sig.instantiate_identity().skip_binder()
- }
- _ => span_bug!(span, "ty_from_delegation: couldn't calculate resolution signature"),
+ let res_sig = if let DefKind::Impl { of_trait: true } = parent_def_kind {
+ let self_ty = self.tcx().type_of(parent).instantiate_identity();
+ let generic_self_ty = ty::GenericArg::from(self_ty);
+ let substs = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty));
+ res_sig.instantiate(self.tcx(), substs).skip_binder()
+ } else {
+ res_sig.instantiate_identity().skip_binder()
};
- if let hir::InferDelegationVar::Input(id) = idx {
- res_sig.inputs()[id]
- } else {
- res_sig.output()
+ match idx {
+ hir::InferDelegationKind::Input(id) => res_sig.inputs()[id],
+ hir::InferDelegationKind::Output => res_sig.output(),
}
}
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 61110e85fce03..c3699b114c411 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -122,12 +122,6 @@ pub struct GenericParamCount {
pub consts: usize,
}
-impl GenericParamCount {
- pub fn count(&self) -> usize {
- self.lifetimes + self.types + self.consts
- }
-}
-
/// Information about the formal type/lifetime parameters associated
/// with an item or method. Analogous to `hir::Generics`.
///
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 41bf80c22ee95..1ef3ce301abc0 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -204,7 +204,7 @@ pub struct ResolverAstLowering {
/// Information about functions signatures for delegation items expansion
pub has_self: LocalDefIdSet,
- pub fns_arguments_count: FxHashMap,
+ pub fn_parameter_counts: LocalDefIdMap,
}
#[derive(Clone, Copy, Debug)]
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index d6d246e318876..65a4ba234602b 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -255,7 +255,7 @@ impl<'a> Parser<'a> {
{
// IMPL ITEM
self.parse_item_impl(attrs, def_())?
- } else if self.check_keyword(kw::Reuse) {
+ } else if self.is_reuse_path_item() {
self.parse_item_delegation()?
} else if self.check_keyword(kw::Mod)
|| self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Mod])
@@ -363,7 +363,7 @@ impl<'a> Parser<'a> {
fn is_reuse_path_item(&mut self) -> bool {
self.is_kw_followed_by_ident(kw::Reuse) // no: `reuse::b`, yes: `reuse U::`
// no: `reuse::b`, yes: reuse ::
- || (self.token.is_keyword(kw::Reuse) && self.look_ahead(1, |t| *t == token::Lt))
+ || (self.token.is_keyword(kw::Reuse) && self.look_ahead(1, |t| matches!(t.kind, token::Lt | token::BinOp(token::Shl))))
}
/// Are we sure this could not possibly be a macro invocation?
@@ -669,7 +669,6 @@ impl<'a> Parser<'a> {
fn parse_item_delegation(&mut self) -> PResult<'a, ItemInfo> {
self.expect_keyword(kw::Reuse)?;
- let span = self.prev_token.span;
let (qself, path) = if self.eat_lt() {
let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
@@ -678,25 +677,17 @@ impl<'a> Parser<'a> {
(None, self.parse_path(PathStyle::Expr)?)
};
- let expr = if self.eat(&token::OpenDelim(Delimiter::Brace)) {
- let expr = self.parse_expr()?;
- self.expect(&token::CloseDelim(Delimiter::Brace))?;
- Some(expr)
+ let body = if self.check(&token::OpenDelim(Delimiter::Brace)) {
+ Some(self.parse_block()?)
} else {
self.expect(&token::Semi)?;
None
};
- let ident =
- path.segments.last().and_then(|segment| Some(segment.ident)).unwrap_or(Ident::empty());
+ let ident = path.segments.last().map(|seg| seg.ident).unwrap_or(Ident::empty());
Ok((
ident,
- ItemKind::Delegation(Box::new(Delegation {
- id: DUMMY_NODE_ID,
- path: (qself, path),
- target_expr: expr,
- span: span.to(self.prev_token.span),
- })),
+ ItemKind::Delegation(Box::new(Delegation { id: DUMMY_NODE_ID, qself, path, body })),
))
}
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 453cada1bab73..0c46631b035df 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -16,7 +16,7 @@ use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError
use rustc_ast::visit::{self, AssocCtxt, Visitor};
use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind};
-use rustc_ast::{Block, Fn, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
+use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
use rustc_attr as attr;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{struct_span_err, Applicability};
@@ -681,10 +681,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
}
// These items live in the value namespace.
- ItemKind::Static(..) => {
- self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
- }
- ItemKind::Const(..) => {
+ ItemKind::Const(..) | ItemKind::Delegation(..) | ItemKind::Static(..) => {
self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
}
ItemKind::Fn(..) => {
@@ -790,11 +787,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
ItemKind::Impl(box Impl { of_trait: Some(..), .. }) => {
self.r.trait_impl_items.insert(local_def_id);
}
-
- ItemKind::Delegation(..) => {
- let res = Res::Def(DefKind::Fn, def_id);
- self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
- }
ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
ItemKind::MacroDef(..) | ItemKind::MacCall(_) => unreachable!(),
@@ -1366,15 +1358,10 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
if ctxt == AssocCtxt::Trait {
let ns = match item.kind {
- AssocItemKind::Const(..) => ValueNS,
- AssocItemKind::Fn(box Fn { ref sig, .. }) => {
- if sig.decl.has_self() {
- self.r.has_self.insert(local_def_id);
- }
- ValueNS
- }
+ AssocItemKind::Const(..)
+ | AssocItemKind::Delegation(..)
+ | AssocItemKind::Fn(..) => ValueNS,
AssocItemKind::Type(..) => TypeNS,
- AssocItemKind::Delegation(..) => ValueNS,
AssocItemKind::MacCall(_) => bug!(), // handled above
};
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index b7f90c93a5758..b77102c085c59 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -111,8 +111,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
ItemKind::TyAlias(..) => DefKind::TyAlias,
ItemKind::Static(s) => DefKind::Static(s.mutability),
ItemKind::Const(..) => DefKind::Const,
- ItemKind::Fn(..) => DefKind::Fn,
- ItemKind::Delegation(..) => DefKind::Fn,
+ ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
ItemKind::MacroDef(..) => {
let macro_data = self.resolver.compile_macro(i, self.resolver.tcx.sess.edition());
let macro_kind = macro_data.ext.macro_kind();
@@ -155,12 +154,8 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
});
}
- fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, fn_id: NodeId) {
+ fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind {
- self.resolver
- .fns_arguments_count
- .insert(self.resolver.node_id_to_def_id[&fn_id].to_def_id(), sig.decl.inputs.len());
-
match sig.header.coroutine_kind {
Some(coroutine_kind) => {
self.visit_generics(generics);
@@ -264,10 +259,9 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
let def_kind = match &i.kind {
- AssocItemKind::Fn(..) => DefKind::AssocFn,
+ AssocItemKind::Fn(..) | AssocItemKind::Delegation(..) => DefKind::AssocFn,
AssocItemKind::Const(..) => DefKind::AssocConst,
AssocItemKind::Type(..) => DefKind::AssocTy,
- AssocItemKind::Delegation(..) => DefKind::AssocFn,
AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
};
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index f803e17b0c7ba..8d1fcdb4dcf79 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -540,13 +540,12 @@ impl<'a> PathSource<'a> {
(PathSource::Type, false) => error_code!(E0412),
(PathSource::Struct, true) => error_code!(E0574),
(PathSource::Struct, false) => error_code!(E0422),
- (PathSource::Expr(..), true) => error_code!(E0423),
- (PathSource::Expr(..), false) => error_code!(E0425),
+ (PathSource::Expr(..), true) | (PathSource::Delegation, true) => error_code!(E0423),
+ (PathSource::Expr(..), false) | (PathSource::Delegation, false) => error_code!(E0425),
(PathSource::Pat | PathSource::TupleStruct(..), true) => error_code!(E0532),
(PathSource::Pat | PathSource::TupleStruct(..), false) => error_code!(E0531),
(PathSource::TraitItem(..), true) => error_code!(E0575),
(PathSource::TraitItem(..), false) => error_code!(E0576),
- (PathSource::Delegation, _) => error_code!(E0795),
}
}
}
@@ -681,8 +680,6 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
/// If it is `true`, then it will be updated when entering a nested function or trait body.
in_func_body: bool,
- in_delegation_item: bool,
-
/// Count the number of places a lifetime is used.
lifetime_uses: FxHashMap,
}
@@ -906,7 +903,6 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
}
fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) {
let previous_value = self.diagnostic_metadata.current_function;
-
match fn_kind {
// Bail if the function is foreign, and thus cannot validly have
// a body, or if there's no body for some other reason.
@@ -1300,7 +1296,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
diagnostic_metadata: Default::default(),
// errors at module scope should always be reported
in_func_body: false,
- in_delegation_item: false,
lifetime_uses: Default::default(),
}
}
@@ -1343,10 +1338,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
opt_ns: Option, // `None` indicates a module path in import
finalize: Option,
) -> PathResult<'a> {
- if self.in_delegation_item && path.len() == 1 && path[0].ident.name == kw::SelfLower {
- return PathResult::NonModule(def::PartialRes::new(def::Res::Err));
- }
-
self.r.resolve_path_with_ribs(
path,
opt_ns,
@@ -2536,14 +2527,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
}
ItemKind::Delegation(ref delegation) => {
- self.resolve_delegation(delegation, true);
+ self.resolve_delegation(item.id, delegation, false);
}
ItemKind::ExternCrate(..) => {}
- ItemKind::MacCall(_) => {
- panic!("unexpanded item in resolve!")
- }
+ ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"),
}
}
@@ -2818,13 +2807,15 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
}
AssocItemKind::Delegation(delegation) => {
- self.resolve_delegation(delegation, true);
+ self.resolve_delegation(item.id, delegation, false);
}
AssocItemKind::Type(box TyAlias { generics, .. }) => self
.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
walk_assoc_item(this, generics, LifetimeBinderKind::Item, item)
}),
- AssocItemKind::MacCall(_) => panic!("unexpanded assoc item in resolve!"),
+ AssocItemKind::MacCall(_) => {
+ panic!("unexpanded macro in resolve!")
+ }
};
}
@@ -3066,7 +3057,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
}
AssocItemKind::Delegation(box delegation) => {
debug!("resolve_implementation AssocItemKind::Delegation");
- let emitted = self.check_trait_item(
+ self.check_trait_item(
item.id,
item.ident,
&item.kind,
@@ -3075,9 +3066,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
seen_trait_items,
|i, s, c| MethodNotMemberOfTrait(i, s, c),
);
-
- // do not emit same errors twice during path resolution
- self.resolve_delegation(delegation, !emitted);
+ self.resolve_delegation(item.id, delegation, trait_id.is_some());
}
AssocItemKind::MacCall(_) => {
panic!("unexpanded macro in resolve!")
@@ -3094,13 +3083,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
span: Span,
seen_trait_items: &mut FxHashMap,
err: F,
- ) -> bool
- where
+ ) where
F: FnOnce(Ident, String, Option) -> ResolutionError<'a>,
{
// If there is a TraitRef in scope for an impl, then the method must be in the trait.
let Some((module, _)) = self.current_trait_ref else {
- return false;
+ return;
};
ident.span.normalize_to_macros_2_0_and_adjust(module.expansion);
let key = BindingKey::new(ident, ns);
@@ -3124,7 +3112,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
let path = &self.current_trait_ref.as_ref().unwrap().1.path;
let path_names = path_names_to_string(path);
self.report_error(span, err(ident, path_names, candidate));
- return true;
+ return;
};
let res = binding.res();
@@ -3140,7 +3128,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
trait_item_span: binding.span,
},
);
- return false;
+ return;
}
Entry::Vacant(entry) => {
entry.insert(span);
@@ -3155,7 +3143,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
self.r.record_partial_res(id, PartialRes::new(res));
let vis = self.r.tcx.visibility(id_in_trait).expect_local();
self.r.feed_visibility(self.r.local_def_id(id), vis);
- return false;
+ return;
}
_ => {}
}
@@ -3180,7 +3168,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
trait_item_span: binding.span,
},
);
- true
}
fn resolve_const_body(&mut self, expr: &'ast Expr, item: Option<(Ident, ConstantItemKind)>) {
@@ -3191,21 +3178,34 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
})
}
- fn resolve_delegation(&mut self, delegation: &'ast Delegation, with_path: bool) {
- self.in_delegation_item = true;
-
- let (qself, path) = &delegation.path;
- if let Some(qself) = &delegation.path.0 {
+ fn resolve_delegation(
+ &mut self,
+ item_id: NodeId,
+ delegation: &'ast Delegation,
+ is_trait_impl: bool,
+ ) {
+ let (qself, path) = (&delegation.qself, &delegation.path);
+ if let Some(qself) = &delegation.qself {
self.visit_ty(&qself.ty);
}
- if with_path {
- self.smart_resolve_path(delegation.id, qself, path, PathSource::Delegation);
+ self.visit_path(path, delegation.id);
+ self.smart_resolve_path(delegation.id, qself, path, PathSource::Delegation);
+ if !is_trait_impl {
+ let path_res = self.r.partial_res_map.get(&delegation.id).unwrap();
+ self.r.partial_res_map.insert(item_id, *path_res);
}
- if let Some(target_expr) = &delegation.target_expr {
- self.visit_expr(target_expr);
+ if let Some(body) = &delegation.body {
+ // `PatBoundCtx` is not necessary in this context
+ let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
+ self.fresh_binding(
+ Ident::with_dummy_span(kw::SelfLower),
+ delegation.id,
+ PatternSource::FnParam,
+ &mut bindings,
+ );
+ self.visit_block(body);
}
- self.in_delegation_item = false;
}
fn resolve_params(&mut self, params: &'ast [Param]) {
@@ -4600,13 +4600,24 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
}
}
-struct LifetimeCountVisitor<'a, 'b, 'tcx> {
+/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
+/// lifetime generic parameters and function parameters.
+struct ItemInfoCollector<'a, 'b, 'tcx> {
r: &'b mut Resolver<'a, 'tcx>,
}
-/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
-/// lifetime generic parameters.
-impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
+impl ItemInfoCollector<'_, '_, '_> {
+ fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId) {
+ let local_def_id = self.r.node_id_to_def_id[&id];
+ self.r.fn_parameter_counts.insert(local_def_id, sig.decl.inputs.len());
+
+ if sig.decl.has_self() {
+ self.r.has_self.insert(local_def_id);
+ }
+ }
+}
+
+impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
fn visit_item(&mut self, item: &'ast Item) {
match &item.kind {
ItemKind::TyAlias(box TyAlias { ref generics, .. })
@@ -4618,6 +4629,10 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
| ItemKind::Impl(box Impl { ref generics, .. })
| ItemKind::Trait(box Trait { ref generics, .. })
| ItemKind::TraitAlias(ref generics, _) => {
+ if let ItemKind::Fn(box Fn { ref sig, .. }) = &item.kind {
+ self.collect_fn_info(sig, item.id);
+ }
+
let def_id = self.r.local_def_id(item.id);
let count = generics
.params
@@ -4634,16 +4649,28 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
| ItemKind::ExternCrate(..)
| ItemKind::MacroDef(..)
| ItemKind::GlobalAsm(..)
- | ItemKind::MacCall(..)
- | ItemKind::Delegation(..) => {}
+ | ItemKind::MacCall(..) => {}
+ 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,
+ // it means there will be a panic when retrieving the count,
+ // but for delegation items we are never actually retrieving that count in practice.
+ }
}
visit::walk_item(self, item)
}
+
+ fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) {
+ if let AssocItemKind::Fn(box Fn { ref sig, .. }) = &item.kind {
+ self.collect_fn_info(sig, item.id);
+ }
+ visit::walk_assoc_item(self, item, ctxt);
+ }
}
impl<'a, 'tcx> Resolver<'a, 'tcx> {
pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
- visit::walk_crate(&mut LifetimeCountVisitor { r: self }, krate);
+ visit::walk_crate(&mut ItemInfoCollector { r: self }, krate);
let mut late_resolution_visitor = LateResolutionVisitor::new(self);
late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
visit::walk_crate(&mut late_resolution_visitor, krate);
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 13cd260cd0382..95c8bf572c5e7 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -221,18 +221,6 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
let mut span_label = None;
let item_ident = path.last().unwrap().ident;
let item_span = item_ident.span;
- if let PathSource::Delegation = source {
- return BaseError {
- msg: format!("couldn't resolve `{item_str}` in delegation item"),
- fallback_label: "delegation is only supported yet for trait methods with explicit paths and free functions".to_string(),
- span: item_span,
- span_label,
- could_be_expr: false,
- suggestion: None,
- module: None,
- };
- }
-
let (mod_prefix, mod_str, module, suggestion) = if path.len() == 1 {
debug!(?self.diagnostic_metadata.current_impl_items);
debug!(?self.diagnostic_metadata.current_function);
@@ -447,13 +435,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
code,
);
- // FIXME: suggestions do not supported yet for delegation item
- if let PathSource::Delegation = source {
- err.span_label(base_error.span, base_error.fallback_label);
- return (err, Vec::new());
- }
self.suggest_at_operator_in_slice_pat_with_range(&mut err, path);
-
self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span);
if let Some((span, label)) = base_error.span_label {
@@ -608,6 +590,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
res: Option,
base_error: &BaseError,
) -> (bool, Vec) {
+ if let PathSource::Delegation = source {
+ return (false, vec![]);
+ }
+
// Try to lookup name in more relaxed fashion for better error reporting.
let ident = path.last().unwrap().ident;
let is_expected = &|res| source.is_expected(res);
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index d367e45a18d6c..b3cb80b346b1f 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1101,6 +1101,8 @@ pub struct Resolver<'a, 'tcx> {
legacy_const_generic_args: FxHashMap>>,
/// Amount of lifetime parameters for each item in the crate.
item_generics_num_lifetimes: FxHashMap,
+ /// Amount of parameters for each function in the crate.
+ fn_parameter_counts: LocalDefIdMap,
main_def: Option,
trait_impls: FxIndexMap>,
@@ -1118,8 +1120,6 @@ pub struct Resolver<'a, 'tcx> {
doc_link_resolutions: FxHashMap,
doc_link_traits_in_scope: FxHashMap>,
all_macro_rules: FxHashMap,
-
- fns_arguments_count: FxHashMap,
}
/// Nothing really interesting here; it just provides memory for the rest of the crate.
@@ -1444,7 +1444,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
doc_link_resolutions: Default::default(),
doc_link_traits_in_scope: Default::default(),
all_macro_rules: Default::default(),
- fns_arguments_count: Default::default(),
+ fn_parameter_counts: Default::default(),
};
let root_parent_scope = ParentScope::module(graph_root, &resolver);
@@ -1549,7 +1549,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
lifetime_elision_allowed: self.lifetime_elision_allowed,
lint_buffer: Steal::new(self.lint_buffer),
has_self: self.has_self,
- fns_arguments_count: self.fns_arguments_count,
+ fn_parameter_counts: self.fn_parameter_counts,
};
ResolverOutputs { global_ctxt, ast_lowering }
}
diff --git a/tests/ui/delegation/bad-resolve.rs b/tests/ui/delegation/bad-resolve.rs
index a1bc9534b27f9..d7c5ef52813aa 100644
--- a/tests/ui/delegation/bad-resolve.rs
+++ b/tests/ui/delegation/bad-resolve.rs
@@ -17,28 +17,28 @@ impl F {
struct S(F);
impl Trait for S {
-//~^ not all trait items implemented, missing: `Type`
+//~^ ERROR not all trait items implemented, missing: `Type`
reuse ::C;
//~^ ERROR item `C` is an associated method, which doesn't match its trait `Trait`
+ //~| ERROR expected function, found associated constant `Trait::C`
reuse ::Type;
//~^ ERROR item `Type` is an associated method, which doesn't match its trait `Trait`
+ //~| ERROR expected method or associated constant, found associated type `Trait::Type`
reuse ::baz;
//~^ ERROR method `baz` is not a member of trait `Trait`
+ //~| ERROR cannot find method or associated constant `baz` in trait `Trait`
reuse ::bar;
reuse foo { &self.0 }
- //~^ ERROR couldn't resolve `foo` in delegation item
- //~| method `foo` has a `&self` declaration in the trait, but not in the impl
+ //~^ ERROR cannot find function `foo` in this scope
reuse F::foo { &self.0 }
- //~^ ERROR couldn't resolve `foo` in delegation item
+ //~^ ERROR cannot find function `foo` in `F`
//~| ERROR duplicate definitions with name `foo`
}
impl S {
reuse F::foo { &self.0 }
- //~^ ERROR couldn't resolve `foo` in delegation item
+ //~^ ERROR cannot find function `foo` in `F`
}
-fn main() {
-
-}
+fn main() {}
diff --git a/tests/ui/delegation/bad-resolve.stderr b/tests/ui/delegation/bad-resolve.stderr
index f6dd9f2282fe9..60ade9aa80657 100644
--- a/tests/ui/delegation/bad-resolve.stderr
+++ b/tests/ui/delegation/bad-resolve.stderr
@@ -8,7 +8,7 @@ LL | reuse ::C;
| ^^^^^^^^^^^^^^^^^^^^^^ does not match trait
error[E0324]: item `Type` is an associated method, which doesn't match its trait `Trait`
- --> $DIR/bad-resolve.rs:23:5
+ --> $DIR/bad-resolve.rs:24:5
|
LL | type Type;
| ---------- item in trait
@@ -17,7 +17,7 @@ LL | reuse ::Type;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ does not match trait
error[E0407]: method `baz` is not a member of trait `Trait`
- --> $DIR/bad-resolve.rs:25:5
+ --> $DIR/bad-resolve.rs:27:5
|
LL | reuse ::baz;
| ^^^^^^^^^^^^^^^^^^^^---^
@@ -26,43 +26,57 @@ LL | reuse ::baz;
| not a member of trait `Trait`
error[E0201]: duplicate definitions with name `foo`:
- --> $DIR/bad-resolve.rs:32:5
+ --> $DIR/bad-resolve.rs:34:5
|
LL | fn foo(&self, x: i32) -> i32 { x }
| ---------------------------------- item in trait
...
LL | reuse foo { &self.0 }
| --------------------- previous definition here
-...
+LL |
LL | reuse F::foo { &self.0 }
| ^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
-error[E0795]: couldn't resolve `foo` in delegation item
- --> $DIR/bad-resolve.rs:29:11
+error[E0423]: expected function, found associated constant `Trait::C`
+ --> $DIR/bad-resolve.rs:21:11
|
-LL | reuse foo { &self.0 }
- | ^^^ delegation is only supported yet for trait methods with explicit paths and free functions
+LL | reuse ::C;
+ | ^^^^^^^^^^^^^^^ not a function
-error[E0795]: couldn't resolve `foo` in delegation item
- --> $DIR/bad-resolve.rs:32:14
+error[E0575]: expected method or associated constant, found associated type `Trait::Type`
+ --> $DIR/bad-resolve.rs:24:11
|
-LL | reuse F::foo { &self.0 }
- | ^^^ delegation is only supported yet for trait methods with explicit paths and free functions
-
-error[E0795]: couldn't resolve `foo` in delegation item
- --> $DIR/bad-resolve.rs:38:14
+LL | reuse ::Type;
+ | ^^^^^^^^^^^^^^^^^^
|
-LL | reuse F::foo { &self.0 }
- | ^^^ delegation is only supported yet for trait methods with explicit paths and free functions
+ = note: can't use a type alias as a constructor
-error[E0186]: method `foo` has a `&self` declaration in the trait, but not in the impl
- --> $DIR/bad-resolve.rs:29:5
+error[E0576]: cannot find method or associated constant `baz` in trait `Trait`
+ --> $DIR/bad-resolve.rs:27:25
|
-LL | fn foo(&self, x: i32) -> i32 { x }
- | ---------------------------- `&self` used in trait
+LL | fn bar() {}
+ | -------- similarly named associated function `bar` defined here
...
+LL | reuse ::baz;
+ | ^^^ help: an associated function with a similar name exists: `bar`
+
+error[E0425]: cannot find function `foo` in this scope
+ --> $DIR/bad-resolve.rs:32:11
+ |
LL | reuse foo { &self.0 }
- | ^^^^^^^^^^^^^^^^^^^^^ expected `&self` in impl
+ | ^^^ not found in this scope
+
+error[E0425]: cannot find function `foo` in `F`
+ --> $DIR/bad-resolve.rs:34:14
+ |
+LL | reuse F::foo { &self.0 }
+ | ^^^ not found in `F`
+
+error[E0425]: cannot find function `foo` in `F`
+ --> $DIR/bad-resolve.rs:40:14
+ |
+LL | reuse F::foo { &self.0 }
+ | ^^^ not found in `F`
error[E0046]: not all trait items implemented, missing: `Type`
--> $DIR/bad-resolve.rs:19:1
@@ -73,7 +87,7 @@ LL | type Type;
LL | impl Trait for S {
| ^^^^^^^^^^^^^^^^ missing `Type` in implementation
-error: aborting due to 9 previous errors
+error: aborting due to 11 previous errors
-Some errors have detailed explanations: E0046, E0186, E0201, E0324, E0407, E0795.
+Some errors have detailed explanations: E0046, E0201, E0324, E0407, E0423, E0425, E0575, E0576.
For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/delegation/explicit-paths-pass.rs b/tests/ui/delegation/explicit-paths-pass.rs
index 85f24c5106433..73c8841619ef7 100644
--- a/tests/ui/delegation/explicit-paths-pass.rs
+++ b/tests/ui/delegation/explicit-paths-pass.rs
@@ -16,12 +16,12 @@ trait Trait {
struct F;
impl Trait for F {}
-mod reuse {
+mod to_reuse {
pub fn foo(x: i32) -> i32 { x + 1 }
pub fn zero_args() -> i32 { 15 }
}
-reuse reuse::zero_args { self }
+reuse to_reuse::zero_args { self }
struct S(F);
impl Trait for S {
@@ -33,7 +33,7 @@ impl Trait for S {
}
impl S {
- reuse ::static_method { reuse::foo(self) }
+ reuse ::static_method { to_reuse::foo(self) }
}
impl std::fmt::Display for S {
@@ -54,7 +54,7 @@ fn main() {
reuse ::static_method;
reuse ::static_method2 { static_method(self) }
#[inline]
- reuse reuse::foo;
+ reuse to_reuse::foo;
assert_eq!(42, static_method(42));
assert_eq!(21, static_method2(10, 10));
assert_eq!(43, foo(42));
diff --git a/tests/ui/delegation/explicit-paths-signature-pass.rs b/tests/ui/delegation/explicit-paths-signature-pass.rs
new file mode 100644
index 0000000000000..4910f458f680f
--- /dev/null
+++ b/tests/ui/delegation/explicit-paths-signature-pass.rs
@@ -0,0 +1,30 @@
+// run-pass
+
+mod to_reuse {
+ use crate::S;
+
+ pub fn foo<'a>(#[cfg(FALSE)] a: u8, _b: &'a S) -> u32 {
+ 1
+ }
+}
+
+reuse to_reuse::foo;
+
+trait Trait {
+ fn foo(&self) -> u32 { 0 }
+}
+
+struct F;
+impl Trait for F {}
+
+struct S(F);
+
+impl Trait for S {
+ reuse to_reuse::foo { self }
+}
+
+fn main() {
+ let s = S(F);
+ assert_eq!(1, foo(&s));
+ assert_eq!(1, s.foo());
+}
diff --git a/tests/ui/delegation/explicit-paths.stderr b/tests/ui/delegation/explicit-paths.stderr
index 4032f5954cd60..8288a9851f254 100644
--- a/tests/ui/delegation/explicit-paths.stderr
+++ b/tests/ui/delegation/explicit-paths.stderr
@@ -19,17 +19,10 @@ error[E0308]: mismatched types
--> $DIR/explicit-paths.rs:18:32
|
LL | reuse ::bar { &self.0 }
- | ------------------ ^^^^^^^ expected `&S2`, found `&F`
- | |
- | arguments to this function are incorrect
+ | ^^^^^^^ expected `&S2`, found `&F`
|
= note: expected reference `&S2`
found reference `&F`
-note: method defined here
- --> $DIR/explicit-paths.rs:2:8
- |
-LL | fn bar(&self) -> i32 { 42 }
- | ^^^ -----
error: aborting due to 2 previous errors
diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/not-supported.rs
index 577d0c784cc13..d77996c7fef90 100644
--- a/tests/ui/delegation/not-supported.rs
+++ b/tests/ui/delegation/not-supported.rs
@@ -41,12 +41,21 @@ mod generics {
reuse ::foo { &self.0 }
//~^ ERROR delegation with early bound generics is not supported yet
}
+}
+
+mod opaque {
+ trait Trait {}
mod to_reuse {
- pub fn opaque(_: impl super::Trait) -> i32 { 0 }
+ use super::Trait;
+
+ pub fn opaque_arg(_: impl Trait) -> i32 { 0 }
+ pub fn opaque_ret() -> impl Trait { unimplemented!() }
}
- reuse to_reuse::opaque;
+ reuse to_reuse::opaque_arg;
//~^ ERROR delegation with early bound generics is not supported yet
+ reuse to_reuse::opaque_ret;
+ //~^ ERROR delegation to a function with opaque type is not supported yet
}
mod fn_header {
@@ -58,13 +67,26 @@ mod fn_header {
}
reuse to_reuse::unsafe_fn;
- //~^ ERROR delegation with unsafe functions is not supported yet
+ //~^ ERROR delegation to unsafe functions is not supported yet
reuse to_reuse::extern_fn;
- //~^ ERROR delegation with non Rust ABI functions is not supported yet
+ //~^ ERROR delegation to non Rust ABI functions is not supported yet
reuse to_reuse::variadic_fn;
- //~^ ERROR delegation with variadic functions is not supported yet
+ //~^ ERROR delegation to variadic functions is not supported yet
reuse to_reuse::const_fn;
- //~^ ERROR delegation with const functions is not supported yet
+ //~^ ERROR delegation to const functions is not supported yet
+}
+
+mod recursive {
+ mod to_reuse1 {
+ pub mod to_reuse2 {
+ pub fn foo() {}
+ }
+
+ pub reuse to_reuse2::foo;
+ }
+
+ reuse to_reuse1::foo;
+ //~^ ERROR recursive delegation is not supported yet
}
fn main() {}
diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr
index 59eee4381ff6e..3c5bf533b389f 100644
--- a/tests/ui/delegation/not-supported.stderr
+++ b/tests/ui/delegation/not-supported.stderr
@@ -1,12 +1,3 @@
-error: delegation with early bound generics is not supported yet
- --> $DIR/not-supported.rs:48:5
- |
-LL | pub fn opaque(_: impl super::Trait) -> i32 { 0 }
- | ------------------------------------------ callee defined here
-LL | }
-LL | reuse to_reuse::opaque;
- | ^^^^^^^^^^^^^^^^^^^^^^^
-
error: delegation with early bound generics is not supported yet
--> $DIR/not-supported.rs:22:9
|
@@ -52,8 +43,26 @@ LL | fn foo(&self, x: i32) -> i32 { x }
LL | reuse ::foo { &self.0 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: delegation with unsafe functions is not supported yet
- --> $DIR/not-supported.rs:60:5
+error: delegation with early bound generics is not supported yet
+ --> $DIR/not-supported.rs:55:5
+ |
+LL | pub fn opaque_arg(_: impl Trait) -> i32 { 0 }
+ | --------------------------------------- callee defined here
+...
+LL | reuse to_reuse::opaque_arg;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: delegation to a function with opaque type is not supported yet
+ --> $DIR/not-supported.rs:57:5
+ |
+LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
+ | --------------------------------- callee defined here
+...
+LL | reuse to_reuse::opaque_ret;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: delegation to unsafe functions is not supported yet
+ --> $DIR/not-supported.rs:69:5
|
LL | pub unsafe fn unsafe_fn() {}
| ------------------------- callee defined here
@@ -61,8 +70,8 @@ LL | pub unsafe fn unsafe_fn() {}
LL | reuse to_reuse::unsafe_fn;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: delegation with non Rust ABI functions is not supported yet
- --> $DIR/not-supported.rs:62:5
+error: delegation to non Rust ABI functions is not supported yet
+ --> $DIR/not-supported.rs:71:5
|
LL | pub extern "C" fn extern_fn() {}
| ----------------------------- callee defined here
@@ -70,8 +79,8 @@ LL | pub extern "C" fn extern_fn() {}
LL | reuse to_reuse::extern_fn;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: delegation with variadic functions is not supported yet
- --> $DIR/not-supported.rs:64:5
+error: delegation to variadic functions is not supported yet
+ --> $DIR/not-supported.rs:73:5
|
LL | pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
| ------------------------------------------------------------- callee defined here
@@ -79,8 +88,8 @@ LL | pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
LL | reuse to_reuse::variadic_fn;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: delegation with const functions is not supported yet
- --> $DIR/not-supported.rs:66:5
+error: delegation to const functions is not supported yet
+ --> $DIR/not-supported.rs:75:5
|
LL | pub const fn const_fn() {}
| ----------------------- callee defined here
@@ -88,5 +97,14 @@ LL | pub const fn const_fn() {}
LL | reuse to_reuse::const_fn;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 10 previous errors
+error: recursive delegation is not supported yet
+ --> $DIR/not-supported.rs:88:5
+ |
+LL | pub reuse to_reuse2::foo;
+ | ------------------------- callee defined here
+...
+LL | reuse to_reuse1::foo;
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
diff --git a/tests/ui/delegation/parse.rs b/tests/ui/delegation/parse.rs
index 5732d21804f5d..e92c85304c2d9 100644
--- a/tests/ui/delegation/parse.rs
+++ b/tests/ui/delegation/parse.rs
@@ -1,4 +1,8 @@
+macro_rules! reuse { {} => {} }
+
mod reuse {
+ use crate::reuse;
+
pub fn to_unsafe(x: i32) -> i32 { x + 1 }
pub fn to_pub() {}
@@ -9,13 +13,19 @@ mod reuse {
c: i32,
}
+ impl reuse {
+ reuse!();
+ }
+
#[allow(unused)]
fn baz() {
let (a, b, c) = (0, 0, 0);
- let _ = reuse {a, b, c};
+ reuse {a, b, c};
}
}
+reuse!();
+
unsafe reuse reuse::to_unsafe;
//~^ ERROR expected item, found keyword `unsafe`
#[inline]
diff --git a/tests/ui/delegation/parse.stderr b/tests/ui/delegation/parse.stderr
index d4b289accb8ae..e6d2c7ce2f09e 100644
--- a/tests/ui/delegation/parse.stderr
+++ b/tests/ui/delegation/parse.stderr
@@ -1,5 +1,5 @@
error: expected item, found keyword `unsafe`
- --> $DIR/parse.rs:19:1
+ --> $DIR/parse.rs:29:1
|
LL | unsafe reuse reuse::to_unsafe;
| ^^^^^^ expected item