Skip to content

Commit ecd2b10

Browse files
Rollup merge of rust-lang#154049 - petrochenkov:deleglobspan, r=jackh726
delegation: Track more precise spans for glob delegations The last commit also fixes a macro hygiene issue with `self` in delegations found in rust-lang#154002.
2 parents dab8d9d + 66cf18e commit ecd2b10

15 files changed

Lines changed: 184 additions & 82 deletions

File tree

compiler/rustc_ast/src/ast.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3901,12 +3901,17 @@ pub struct Delegation {
39013901
pub from_glob: bool,
39023902
}
39033903

3904+
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
3905+
pub enum DelegationSuffixes {
3906+
List(ThinVec<(Ident, Option<Ident>)>),
3907+
Glob(Span),
3908+
}
3909+
39043910
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
39053911
pub struct DelegationMac {
39063912
pub qself: Option<Box<QSelf>>,
39073913
pub prefix: Path,
3908-
// Some for list delegation, and None for glob delegation.
3909-
pub suffixes: Option<ThinVec<(Ident, Option<Ident>)>>,
3914+
pub suffixes: DelegationSuffixes,
39103915
pub body: Option<Box<Block>>,
39113916
}
39123917

compiler/rustc_ast/src/visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ macro_rules! common_visitor_and_walkers {
430430
Defaultness,
431431
Delegation,
432432
DelegationMac,
433+
DelegationSuffixes,
433434
DelimArgs,
434435
DelimSpan,
435436
EnumDef,

compiler/rustc_ast_pretty/src/pprust/state/item.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,10 @@ impl<'a> State<'a> {
435435
&item.vis,
436436
&deleg.qself,
437437
&deleg.prefix,
438-
deleg.suffixes.as_ref().map_or(DelegationKind::Glob, |s| DelegationKind::List(s)),
438+
match &deleg.suffixes {
439+
ast::DelegationSuffixes::List(s) => DelegationKind::List(s),
440+
ast::DelegationSuffixes::Glob(_) => DelegationKind::Glob,
441+
},
439442
&deleg.body,
440443
),
441444
}
@@ -641,7 +644,10 @@ impl<'a> State<'a> {
641644
vis,
642645
&deleg.qself,
643646
&deleg.prefix,
644-
deleg.suffixes.as_ref().map_or(DelegationKind::Glob, |s| DelegationKind::List(s)),
647+
match &deleg.suffixes {
648+
ast::DelegationSuffixes::List(s) => DelegationKind::List(s),
649+
ast::DelegationSuffixes::Glob(_) => DelegationKind::Glob,
650+
},
645651
&deleg.body,
646652
),
647653
}

compiler/rustc_expand/src/base.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,26 +1019,32 @@ impl SyntaxExtension {
10191019
pub fn glob_delegation(
10201020
trait_def_id: DefId,
10211021
impl_def_id: LocalDefId,
1022+
star_span: Span,
10221023
edition: Edition,
10231024
) -> SyntaxExtension {
10241025
struct GlobDelegationExpanderImpl {
10251026
trait_def_id: DefId,
10261027
impl_def_id: LocalDefId,
1028+
star_span: Span,
10271029
}
10281030
impl GlobDelegationExpander for GlobDelegationExpanderImpl {
10291031
fn expand(
10301032
&self,
10311033
ecx: &mut ExtCtxt<'_>,
10321034
) -> ExpandResult<Vec<(Ident, Option<Ident>)>, ()> {
1033-
match ecx.resolver.glob_delegation_suffixes(self.trait_def_id, self.impl_def_id) {
1035+
match ecx.resolver.glob_delegation_suffixes(
1036+
self.trait_def_id,
1037+
self.impl_def_id,
1038+
self.star_span,
1039+
) {
10341040
Ok(suffixes) => ExpandResult::Ready(suffixes),
10351041
Err(Indeterminate) if ecx.force_mode => ExpandResult::Ready(Vec::new()),
10361042
Err(Indeterminate) => ExpandResult::Retry(()),
10371043
}
10381044
}
10391045
}
10401046

1041-
let expander = GlobDelegationExpanderImpl { trait_def_id, impl_def_id };
1047+
let expander = GlobDelegationExpanderImpl { trait_def_id, impl_def_id, star_span };
10421048
SyntaxExtension::default(SyntaxExtensionKind::GlobDelegation(Arc::new(expander)), edition)
10431049
}
10441050

@@ -1170,6 +1176,7 @@ pub trait ResolverExpand {
11701176
&self,
11711177
trait_def_id: DefId,
11721178
impl_def_id: LocalDefId,
1179+
star_span: Span,
11731180
) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate>;
11741181

11751182
/// Record the name of an opaque `Ty::ImplTrait` pre-expansion so that it can be used

compiler/rustc_expand/src/expand.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ use rustc_ast::tokenstream::TokenStream;
88
use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list};
99
use rustc_ast::{
1010
self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrItemKind, AttrStyle, AttrVec,
11-
DUMMY_NODE_ID, EarlyParsedAttribute, ExprKind, ForeignItemKind, HasAttrs, HasNodeId, Inline,
12-
ItemKind, MacStmtStyle, MetaItemInner, MetaItemKind, ModKind, NodeId, PatKind, StmtKind,
13-
TyKind, token,
11+
DUMMY_NODE_ID, DelegationSuffixes, EarlyParsedAttribute, ExprKind, ForeignItemKind, HasAttrs,
12+
HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner, MetaItemKind, ModKind, NodeId,
13+
PatKind, StmtKind, TyKind, token,
1414
};
1515
use rustc_ast_pretty::pprust;
1616
use rustc_attr_parsing::parser::AllowExprMetavar;
@@ -2401,7 +2401,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
24012401
res
24022402
}
24032403
None if let Some((deleg, item)) = node.delegation() => {
2404-
let Some(suffixes) = &deleg.suffixes else {
2404+
let DelegationSuffixes::List(suffixes) = &deleg.suffixes else {
24052405
let traitless_qself =
24062406
matches!(&deleg.qself, Some(qself) if qself.position == 0);
24072407
let (item, of_trait) = match node.to_annotatable() {

compiler/rustc_parse/src/parser/item.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,7 @@ impl<'a> Parser<'a> {
857857
kind: AssocItemKind::DelegationMac(Box::new(DelegationMac {
858858
qself: None,
859859
prefix: of_trait.trait_ref.path.clone(),
860-
suffixes: None,
860+
suffixes: DelegationSuffixes::Glob(whole_reuse_span),
861861
body,
862862
})),
863863
}));
@@ -879,10 +879,12 @@ impl<'a> Parser<'a> {
879879

880880
Ok(if self.eat_path_sep() {
881881
let suffixes = if self.eat(exp!(Star)) {
882-
None
882+
DelegationSuffixes::Glob(self.prev_token.span)
883883
} else {
884884
let parse_suffix = |p: &mut Self| Ok((p.parse_path_segment_ident()?, rename(p)?));
885-
Some(self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), parse_suffix)?.0)
885+
DelegationSuffixes::List(
886+
self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), parse_suffix)?.0,
887+
)
886888
};
887889

888890
ItemKind::DelegationMac(Box::new(DelegationMac {
@@ -1517,7 +1519,10 @@ impl<'a> Parser<'a> {
15171519
let span = self.psess.source_map().guess_head_span(span);
15181520
let descr = kind.descr();
15191521
let help = match kind {
1520-
ItemKind::DelegationMac(deleg) if deleg.suffixes.is_none() => false,
1522+
ItemKind::DelegationMac(box DelegationMac {
1523+
suffixes: DelegationSuffixes::Glob(_),
1524+
..
1525+
}) => false,
15211526
_ => true,
15221527
};
15231528
self.dcx().emit_err(errors::BadItemKind { span, descr, ctx, help });

compiler/rustc_resolve/src/late.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3873,8 +3873,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
38733873

38743874
let Some(body) = &delegation.body else { return };
38753875
self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
3876-
let span = delegation.path.segments.last().unwrap().ident.span;
3877-
let ident = Ident::new(kw::SelfLower, span.normalize_to_macro_rules());
3876+
let ident = Ident::new(kw::SelfLower, body.span.normalize_to_macro_rules());
38783877
let res = Res::Local(delegation.id);
38793878
this.innermost_rib_bindings(ValueNS).insert(ident, res);
38803879

compiler/rustc_resolve/src/macros.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use std::mem;
55
use std::sync::Arc;
66

7-
use rustc_ast::{self as ast, Crate, DUMMY_NODE_ID, NodeId};
7+
use rustc_ast::{self as ast, Crate, DUMMY_NODE_ID, DelegationSuffixes, NodeId};
88
use rustc_ast_pretty::pprust;
99
use rustc_attr_parsing::AttributeParser;
1010
use rustc_errors::{Applicability, DiagCtxtHandle, StashKey};
@@ -286,7 +286,8 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
286286
InvocationKind::Derive { ref path, .. } => (path, MacroKind::Derive),
287287
InvocationKind::GlobDelegation { ref item, .. } => {
288288
let ast::AssocItemKind::DelegationMac(deleg) = &item.kind else { unreachable!() };
289-
deleg_impl = Some(self.invocation_parent(invoc_id));
289+
let DelegationSuffixes::Glob(star_span) = deleg.suffixes else { unreachable!() };
290+
deleg_impl = Some((self.invocation_parent(invoc_id), star_span));
290291
// It is sufficient to consider glob delegation a bang macro for now.
291292
(&deleg.prefix, MacroKind::Bang)
292293
}
@@ -530,6 +531,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
530531
&self,
531532
trait_def_id: DefId,
532533
impl_def_id: LocalDefId,
534+
star_span: Span,
533535
) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate> {
534536
let target_trait = self.expect_module(trait_def_id);
535537
if !target_trait.unexpanded_invocations.borrow().is_empty() {
@@ -549,13 +551,13 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
549551

550552
let mut idents = Vec::new();
551553
target_trait.for_each_child(self, |this, ident, orig_ident_span, ns, _binding| {
552-
// FIXME: Adjust hygiene for idents from globs, like for glob imports.
553554
if let Some(overriding_keys) = this.impl_binding_keys.get(&impl_def_id)
554555
&& overriding_keys.contains(&BindingKey::new(ident, ns))
555556
{
556557
// The name is overridden, do not produce it from the glob delegation.
557558
} else {
558-
idents.push((ident.orig(orig_ident_span), None));
559+
// FIXME: Adjust hygiene for idents from globs, like for glob imports.
560+
idents.push((ident.orig(star_span.with_ctxt(orig_ident_span.ctxt())), None));
559561
}
560562
});
561563
Ok(idents)
@@ -579,7 +581,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
579581
parent_scope: &ParentScope<'ra>,
580582
node_id: NodeId,
581583
force: bool,
582-
deleg_impl: Option<LocalDefId>,
584+
deleg_impl: Option<(LocalDefId, Span)>,
583585
invoc_in_mod_inert_attr: Option<LocalDefId>,
584586
suggestion_span: Option<Span>,
585587
) -> Result<(Arc<SyntaxExtension>, Res), Indeterminate> {
@@ -771,7 +773,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
771773
kind: MacroKind,
772774
parent_scope: &ParentScope<'ra>,
773775
force: bool,
774-
deleg_impl: Option<LocalDefId>,
776+
deleg_impl: Option<(LocalDefId, Span)>,
775777
invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
776778
ignore_import: Option<Import<'ra>>,
777779
suggestion_span: Option<Span>,
@@ -856,10 +858,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
856858

857859
let res = res?;
858860
let ext = match deleg_impl {
859-
Some(impl_def_id) => match res {
861+
Some((impl_def_id, star_span)) => match res {
860862
def::Res::Def(DefKind::Trait, def_id) => {
861863
let edition = self.tcx.sess.edition();
862-
Some(Arc::new(SyntaxExtension::glob_delegation(def_id, impl_def_id, edition)))
864+
Some(Arc::new(SyntaxExtension::glob_delegation(
865+
def_id,
866+
impl_def_id,
867+
star_span,
868+
edition,
869+
)))
863870
}
864871
_ => None,
865872
},

tests/ui/delegation/glob-glob-conflict.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,10 @@
33

44
trait Trait1 {
55
fn method(&self) -> u8;
6-
//~^ ERROR: this function takes 1 argument but 0 arguments were supplied
7-
//~| ERROR: mismatched types
86
}
97
trait Trait2 {
108
fn method(&self) -> u8;
11-
//~^ ERROR: this function takes 1 argument but 0 arguments were supplied
12-
//~| ERROR: mismatched types
9+
1310
}
1411
trait Trait {
1512
fn method(&self) -> u8;
@@ -28,10 +25,14 @@ impl Trait2 for u8 {
2825
impl Trait for u8 {
2926
reuse Trait1::*;
3027
reuse Trait2::*; //~ ERROR duplicate definitions with name `method`
28+
//~^ ERROR: this function takes 1 argument but 0 arguments were supplied
29+
//~| ERROR: mismatched types
3130
}
3231
impl Trait for u16 {
3332
reuse Trait1::*;
3433
reuse Trait1::*; //~ ERROR duplicate definitions with name `method`
34+
//~^ ERROR: this function takes 1 argument but 0 arguments were supplied
35+
//~| ERROR: mismatched types
3536
}
3637

3738
fn main() {}

tests/ui/delegation/glob-glob-conflict.stderr

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0201]: duplicate definitions with name `method`:
2-
--> $DIR/glob-glob-conflict.rs:30:5
2+
--> $DIR/glob-glob-conflict.rs:27:5
33
|
44
LL | fn method(&self) -> u8;
55
| ----------------------- item in trait
@@ -10,7 +10,7 @@ LL | reuse Trait2::*;
1010
| ^^^^^^^^^^^^^^^^ duplicate definition
1111

1212
error[E0201]: duplicate definitions with name `method`:
13-
--> $DIR/glob-glob-conflict.rs:34:5
13+
--> $DIR/glob-glob-conflict.rs:33:5
1414
|
1515
LL | fn method(&self) -> u8;
1616
| ----------------------- item in trait
@@ -21,35 +21,35 @@ LL | reuse Trait1::*;
2121
| ^^^^^^^^^^^^^^^^ duplicate definition
2222

2323
error[E0061]: this function takes 1 argument but 0 arguments were supplied
24-
--> $DIR/glob-glob-conflict.rs:10:8
24+
--> $DIR/glob-glob-conflict.rs:27:19
2525
|
26-
LL | fn method(&self) -> u8;
27-
| ^^^^^^ argument #1 of type `&_` is missing
26+
LL | reuse Trait2::*;
27+
| ^ argument #1 of type `&_` is missing
2828
|
2929
note: method defined here
30-
--> $DIR/glob-glob-conflict.rs:10:8
30+
--> $DIR/glob-glob-conflict.rs:8:8
3131
|
3232
LL | fn method(&self) -> u8;
3333
| ^^^^^^ ----
3434
help: provide the argument
3535
|
36-
LL | fn method(/* value */)(&self) -> u8;
37-
| +++++++++++++
36+
LL | reuse Trait2::*(/* value */);
37+
| +++++++++++++
3838

3939
error[E0308]: mismatched types
40-
--> $DIR/glob-glob-conflict.rs:10:8
40+
--> $DIR/glob-glob-conflict.rs:27:19
4141
|
42-
LL | fn method(&self) -> u8;
43-
| ^^^^^^- help: consider using a semicolon here: `;`
44-
| |
45-
| expected `()`, found `u8`
46-
| expected `()` because of default return type
42+
LL | reuse Trait2::*;
43+
| ^- help: consider using a semicolon here: `;`
44+
| |
45+
| expected `()`, found `u8`
46+
| expected `()` because of default return type
4747

4848
error[E0061]: this function takes 1 argument but 0 arguments were supplied
49-
--> $DIR/glob-glob-conflict.rs:5:8
49+
--> $DIR/glob-glob-conflict.rs:33:19
5050
|
51-
LL | fn method(&self) -> u8;
52-
| ^^^^^^ argument #1 of type `&_` is missing
51+
LL | reuse Trait1::*;
52+
| ^ argument #1 of type `&_` is missing
5353
|
5454
note: method defined here
5555
--> $DIR/glob-glob-conflict.rs:5:8
@@ -58,17 +58,17 @@ LL | fn method(&self) -> u8;
5858
| ^^^^^^ ----
5959
help: provide the argument
6060
|
61-
LL | fn method(/* value */)(&self) -> u8;
62-
| +++++++++++++
61+
LL | reuse Trait1::*(/* value */);
62+
| +++++++++++++
6363

6464
error[E0308]: mismatched types
65-
--> $DIR/glob-glob-conflict.rs:5:8
65+
--> $DIR/glob-glob-conflict.rs:33:19
6666
|
67-
LL | fn method(&self) -> u8;
68-
| ^^^^^^- help: consider using a semicolon here: `;`
69-
| |
70-
| expected `()`, found `u8`
71-
| expected `()` because of default return type
67+
LL | reuse Trait1::*;
68+
| ^- help: consider using a semicolon here: `;`
69+
| |
70+
| expected `()`, found `u8`
71+
| expected `()` because of default return type
7272

7373
error: aborting due to 6 previous errors
7474

0 commit comments

Comments
 (0)