Rollup merge of #126497 - petrochenkov:delehyg, r=compiler-errors
delegation: Fix hygiene for `self` And fix diagnostics for `self` from a macro. The missing rib caused `self` to be treated as a generic parameter and ignore `macro_rules` hygiene. Addresses this comment https://github.com/rust-lang/rust/pull/124135#discussion_r1637492234.
This commit is contained in:
commit
4265043aae
@ -3281,17 +3281,19 @@ fn resolve_delegation(&mut self, delegation: &'ast Delegation) {
|
|||||||
}
|
}
|
||||||
self.visit_path(&delegation.path, delegation.id);
|
self.visit_path(&delegation.path, delegation.id);
|
||||||
if let Some(body) = &delegation.body {
|
if let Some(body) = &delegation.body {
|
||||||
// `PatBoundCtx` is not necessary in this context
|
self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
|
||||||
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
|
// `PatBoundCtx` is not necessary in this context
|
||||||
|
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
|
||||||
|
|
||||||
let span = delegation.path.segments.last().unwrap().ident.span;
|
let span = delegation.path.segments.last().unwrap().ident.span;
|
||||||
self.fresh_binding(
|
this.fresh_binding(
|
||||||
Ident::new(kw::SelfLower, span),
|
Ident::new(kw::SelfLower, span),
|
||||||
delegation.id,
|
delegation.id,
|
||||||
PatternSource::FnParam,
|
PatternSource::FnParam,
|
||||||
&mut bindings,
|
&mut bindings,
|
||||||
);
|
);
|
||||||
self.visit_block(body);
|
this.visit_block(body);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1021,12 +1021,14 @@ fn suggest_self_value(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
let is_assoc_fn = self.self_type_is_available();
|
let is_assoc_fn = self.self_type_is_available();
|
||||||
|
let self_from_macro = "a `self` parameter, but a macro invocation can only \
|
||||||
|
access identifiers it receives from parameters";
|
||||||
if let Some((fn_kind, span)) = &self.diag_metadata.current_function {
|
if let Some((fn_kind, span)) = &self.diag_metadata.current_function {
|
||||||
// The current function has a `self` parameter, but we were unable to resolve
|
// The current function has a `self` parameter, but we were unable to resolve
|
||||||
// a reference to `self`. This can only happen if the `self` identifier we
|
// a reference to `self`. This can only happen if the `self` identifier we
|
||||||
// are resolving came from a different hygiene context.
|
// are resolving came from a different hygiene context.
|
||||||
if fn_kind.decl().inputs.get(0).is_some_and(|p| p.is_self()) {
|
if fn_kind.decl().inputs.get(0).is_some_and(|p| p.is_self()) {
|
||||||
err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters");
|
err.span_label(*span, format!("this function has {self_from_macro}"));
|
||||||
} else {
|
} else {
|
||||||
let doesnt = if is_assoc_fn {
|
let doesnt = if is_assoc_fn {
|
||||||
let (span, sugg) = fn_kind
|
let (span, sugg) = fn_kind
|
||||||
@ -1068,14 +1070,18 @@ fn suggest_self_value(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(item_kind) = self.diag_metadata.current_item {
|
} else if let Some(item_kind) = self.diag_metadata.current_item {
|
||||||
err.span_label(
|
if matches!(item_kind.kind, ItemKind::Delegation(..)) {
|
||||||
item_kind.ident.span,
|
err.span_label(item_kind.span, format!("delegation supports {self_from_macro}"));
|
||||||
format!(
|
} else {
|
||||||
"`self` not allowed in {} {}",
|
err.span_label(
|
||||||
item_kind.kind.article(),
|
item_kind.ident.span,
|
||||||
item_kind.kind.descr()
|
format!(
|
||||||
),
|
"`self` not allowed in {} {}",
|
||||||
);
|
item_kind.kind.article(),
|
||||||
|
item_kind.kind.descr()
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,9 @@ impl Trait for u8 {}
|
|||||||
|
|
||||||
// Macro expansion works inside delegation items.
|
// Macro expansion works inside delegation items.
|
||||||
macro_rules! u8 { () => { u8 } }
|
macro_rules! u8 { () => { u8 } }
|
||||||
macro_rules! self_0 { () => { &self.0 } }
|
macro_rules! self_0 { ($self:ident) => { &$self.0 } }
|
||||||
impl Trait for S {
|
impl Trait for S {
|
||||||
reuse <u8!() as Trait>::{foo, bar} { self_0!() }
|
reuse <u8!() as Trait>::{foo, bar} { self_0!(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
20
tests/ui/delegation/self-hygiene.rs
Normal file
20
tests/ui/delegation/self-hygiene.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#![feature(fn_delegation)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
macro_rules! emit_self { () => { self } }
|
||||||
|
//~^ ERROR expected value, found module `self`
|
||||||
|
//~| ERROR expected value, found module `self`
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
impl S {
|
||||||
|
fn method(self) {
|
||||||
|
emit_self!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(arg: u8) {}
|
||||||
|
reuse foo as bar {
|
||||||
|
emit_self!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
31
tests/ui/delegation/self-hygiene.stderr
Normal file
31
tests/ui/delegation/self-hygiene.stderr
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
error[E0424]: expected value, found module `self`
|
||||||
|
--> $DIR/self-hygiene.rs:4:34
|
||||||
|
|
|
||||||
|
LL | macro_rules! emit_self { () => { self } }
|
||||||
|
| ^^^^ `self` value is a keyword only available in methods with a `self` parameter
|
||||||
|
...
|
||||||
|
LL | / fn method(self) {
|
||||||
|
LL | | emit_self!();
|
||||||
|
| | ------------ in this macro invocation
|
||||||
|
LL | | }
|
||||||
|
| |_____- this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters
|
||||||
|
|
|
||||||
|
= note: this error originates in the macro `emit_self` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error[E0424]: expected value, found module `self`
|
||||||
|
--> $DIR/self-hygiene.rs:4:34
|
||||||
|
|
|
||||||
|
LL | macro_rules! emit_self { () => { self } }
|
||||||
|
| ^^^^ `self` value is a keyword only available in methods with a `self` parameter
|
||||||
|
...
|
||||||
|
LL | / reuse foo as bar {
|
||||||
|
LL | | emit_self!()
|
||||||
|
| | ------------ in this macro invocation
|
||||||
|
LL | | }
|
||||||
|
| |_- delegation supports a `self` parameter, but a macro invocation can only access identifiers it receives from parameters
|
||||||
|
|
|
||||||
|
= note: this error originates in the macro `emit_self` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0424`.
|
Loading…
Reference in New Issue
Block a user