Skip to content

Commit 16a733b

Browse files
authored
Rollup merge of rust-lang#63083 - matthewjasper:parameter-hygiene, r=petrochenkov
Make generic parameters always use modern hygiene * E0263 (lifetime parameter declared twice in the same scope) now compares modernized identifiers. * Const parameters are now resolved with modern hygiene. Closes rust-lang#58307 Closes rust-lang#60746 Closes rust-lang#61574 Closes rust-lang#62433
2 parents 81510c9 + 0fb9295 commit 16a733b

9 files changed

+213
-23
lines changed

src/librustc/middle/resolve_lifetime.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2568,7 +2568,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
25682568
let lifetimes: Vec<_> = params
25692569
.iter()
25702570
.filter_map(|param| match param.kind {
2571-
GenericParamKind::Lifetime { .. } => Some((param, param.name)),
2571+
GenericParamKind::Lifetime { .. } => Some((param, param.name.modern())),
25722572
_ => None,
25732573
})
25742574
.collect();

src/librustc_resolve/lib.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -869,8 +869,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
869869
debug!("(resolving function) entering function");
870870
let rib_kind = match function_kind {
871871
FnKind::ItemFn(..) => FnItemRibKind,
872-
FnKind::Method(..) => AssocItemRibKind,
873-
FnKind::Closure(_) => NormalRibKind,
872+
FnKind::Method(..) | FnKind::Closure(_) => NormalRibKind,
874873
};
875874

876875
// Create a value rib for the function.
@@ -2307,21 +2306,32 @@ impl<'a> Resolver<'a> {
23072306
if ident.name == kw::Invalid {
23082307
return Some(LexicalScopeBinding::Res(Res::Err));
23092308
}
2310-
ident.span = if ident.name == kw::SelfUpper {
2309+
let (general_span, modern_span) = if ident.name == kw::SelfUpper {
23112310
// FIXME(jseyfried) improve `Self` hygiene
2312-
ident.span.with_ctxt(SyntaxContext::empty())
2311+
let empty_span = ident.span.with_ctxt(SyntaxContext::empty());
2312+
(empty_span, empty_span)
23132313
} else if ns == TypeNS {
2314-
ident.span.modern()
2314+
let modern_span = ident.span.modern();
2315+
(modern_span, modern_span)
23152316
} else {
2316-
ident.span.modern_and_legacy()
2317+
(ident.span.modern_and_legacy(), ident.span.modern())
23172318
};
2319+
ident.span = general_span;
2320+
let modern_ident = Ident { span: modern_span, ..ident };
23182321

23192322
// Walk backwards up the ribs in scope.
23202323
let record_used = record_used_id.is_some();
23212324
let mut module = self.graph_root;
23222325
for i in (0 .. self.ribs[ns].len()).rev() {
23232326
debug!("walk rib\n{:?}", self.ribs[ns][i].bindings);
2324-
if let Some(res) = self.ribs[ns][i].bindings.get(&ident).cloned() {
2327+
// Use the rib kind to determine whether we are resolving parameters
2328+
// (modern hygiene) or local variables (legacy hygiene).
2329+
let rib_ident = if let AssocItemRibKind | ItemRibKind = self.ribs[ns][i].kind {
2330+
modern_ident
2331+
} else {
2332+
ident
2333+
};
2334+
if let Some(res) = self.ribs[ns][i].bindings.get(&rib_ident).cloned() {
23252335
// The ident resolves to a type parameter or local variable.
23262336
return Some(LexicalScopeBinding::Res(
23272337
self.validate_res_from_ribs(ns, i, res, record_used, path_span),
@@ -2357,7 +2367,7 @@ impl<'a> Resolver<'a> {
23572367
}
23582368
}
23592369

2360-
ident.span = ident.span.modern();
2370+
ident = modern_ident;
23612371
let mut poisoned = None;
23622372
loop {
23632373
let opt_module = if let Some(node_id) = record_used_id {
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Ensure that lifetime parameter names are modernized before we check for
2+
// duplicates.
3+
4+
#![feature(decl_macro, rustc_attrs)]
5+
6+
#[rustc_macro_transparency = "semitransparent"]
7+
macro m($a:lifetime) {
8+
fn g<$a, 'a>() {} //~ ERROR lifetime name `'a` declared twice
9+
}
10+
11+
#[rustc_macro_transparency = "transparent"]
12+
macro n($a:lifetime) {
13+
fn h<$a, 'a>() {} //~ ERROR lifetime name `'a` declared twice
14+
}
15+
16+
m!('a);
17+
n!('a);
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0263]: lifetime name `'a` declared twice in the same scope
2+
--> $DIR/duplicate_lifetimes.rs:8:14
3+
|
4+
LL | fn g<$a, 'a>() {}
5+
| ^^ declared twice
6+
...
7+
LL | m!('a);
8+
| -------
9+
| | |
10+
| | previous declaration here
11+
| in this macro invocation
12+
13+
error[E0263]: lifetime name `'a` declared twice in the same scope
14+
--> $DIR/duplicate_lifetimes.rs:13:14
15+
|
16+
LL | fn h<$a, 'a>() {}
17+
| ^^ declared twice
18+
...
19+
LL | n!('a);
20+
| -------
21+
| | |
22+
| | previous declaration here
23+
| in this macro invocation
24+
25+
error: aborting due to 2 previous errors
26+
27+
For more information about this error, try `rustc --explain E0263`.

src/test/ui/hygiene/generic_params.rs

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Ensure that generic parameters always have modern hygiene.
2+
3+
// check-pass
4+
// ignore-pretty pretty-printing is unhygienic
5+
6+
#![feature(decl_macro, rustc_attrs, const_generics)]
7+
8+
mod type_params {
9+
macro m($T:ident) {
10+
fn f<$T: Clone, T: PartialEq>(t1: $T, t2: T) -> ($T, bool) {
11+
(t1.clone(), t2 == t2)
12+
}
13+
}
14+
15+
#[rustc_macro_transparency = "semitransparent"]
16+
macro n($T:ident) {
17+
fn g<$T: Clone>(t1: $T, t2: T) -> (T, $T) {
18+
(t1.clone(), t2.clone())
19+
}
20+
fn h<T: Clone>(t1: $T, t2: T) -> (T, $T) {
21+
(t1.clone(), t2.clone())
22+
}
23+
}
24+
25+
#[rustc_macro_transparency = "transparent"]
26+
macro p($T:ident) {
27+
fn j<$T: Clone>(t1: $T, t2: T) -> (T, $T) {
28+
(t1.clone(), t2.clone())
29+
}
30+
fn k<T: Clone>(t1: $T, t2: T) -> (T, $T) {
31+
(t1.clone(), t2.clone())
32+
}
33+
}
34+
35+
m!(T);
36+
n!(T);
37+
p!(T);
38+
}
39+
40+
mod lifetime_params {
41+
macro m($a:lifetime) {
42+
fn f<'b, 'c, $a: 'b, 'a: 'c>(t1: &$a(), t2: &'a ()) -> (&'b (), &'c ()) {
43+
(t1, t2)
44+
}
45+
}
46+
47+
#[rustc_macro_transparency = "semitransparent"]
48+
macro n($a:lifetime) {
49+
fn g<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
50+
(t1, t2)
51+
}
52+
fn h<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
53+
(t1, t2)
54+
}
55+
}
56+
57+
#[rustc_macro_transparency = "transparent"]
58+
macro p($a:lifetime) {
59+
fn j<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
60+
(t1, t2)
61+
}
62+
fn k<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
63+
(t1, t2)
64+
}
65+
}
66+
67+
m!('a);
68+
n!('a);
69+
p!('a);
70+
}
71+
72+
mod const_params {
73+
macro m($C:ident) {
74+
fn f<const $C: usize, const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); $C], [(); C]) {
75+
(t1, t2)
76+
}
77+
}
78+
79+
#[rustc_macro_transparency = "semitransparent"]
80+
macro n($C:ident) {
81+
fn g<const $C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
82+
(t1, t2)
83+
}
84+
fn h<const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
85+
(t1, t2)
86+
}
87+
}
88+
89+
#[rustc_macro_transparency = "transparent"]
90+
macro p($C:ident) {
91+
fn j<const $C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
92+
(t1, t2)
93+
}
94+
fn k<const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
95+
(t1, t2)
96+
}
97+
}
98+
99+
m!(C);
100+
n!(C);
101+
p!(C);
102+
}
103+
104+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
2+
--> $DIR/generic_params.rs:6:37
3+
|
4+
LL | #![feature(decl_macro, rustc_attrs, const_generics)]
5+
| ^^^^^^^^^^^^^^
6+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// A more comprehensive test that const parameters have correctly implemented
2+
// hygiene
3+
4+
// check-pass
5+
6+
#![feature(const_generics)]
7+
8+
use std::ops::Add;
9+
10+
struct VectorLike<T, const SIZE: usize>([T; {SIZE}]);
11+
12+
macro_rules! impl_operator_overload {
13+
($trait_ident:ident, $method_ident:ident) => {
14+
15+
impl<T, const SIZE: usize> $trait_ident for VectorLike<T, {SIZE}>
16+
where
17+
T: $trait_ident,
18+
{
19+
type Output = VectorLike<T, {SIZE}>;
20+
21+
fn $method_ident(self, _: VectorLike<T, {SIZE}>) -> VectorLike<T, {SIZE}> {
22+
let _ = SIZE;
23+
unimplemented!()
24+
}
25+
}
26+
27+
}
28+
}
29+
30+
impl_operator_overload!(Add, add);
31+
32+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
2+
--> $DIR/issue-61574-const-parameters.rs:6:12
3+
|
4+
LL | #![feature(const_generics)]
5+
| ^^^^^^^^^^^^^^
6+

src/test/ui/hygiene/ty_params.rs

-14
This file was deleted.

0 commit comments

Comments
 (0)