From 8876b3b9b0bf652cddf68d9ddcb5b5fa31d829ab Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 28 Jul 2019 13:34:03 +0100 Subject: [PATCH] Resolve const parameters with modern hygiene Declarations were already modernized, resulting in cases where a macro couldn't resolve it's own identifier. --- src/librustc_resolve/lib.rs | 26 ++++-- src/test/ui/hygiene/generic_params.rs | 104 ++++++++++++++++++++++ src/test/ui/hygiene/generic_params.stderr | 6 ++ src/test/ui/hygiene/ty_params.rs | 14 --- 4 files changed, 128 insertions(+), 22 deletions(-) create mode 100644 src/test/ui/hygiene/generic_params.rs create mode 100644 src/test/ui/hygiene/generic_params.stderr delete mode 100644 src/test/ui/hygiene/ty_params.rs diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a5e498fa75643..8884d1cd27f79 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -872,8 +872,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { debug!("(resolving function) entering function"); let rib_kind = match function_kind { FnKind::ItemFn(..) => FnItemRibKind, - FnKind::Method(..) => AssocItemRibKind, - FnKind::Closure(_) => NormalRibKind, + FnKind::Method(..) | FnKind::Closure(_) => NormalRibKind, }; // Create a value rib for the function. @@ -2310,21 +2309,32 @@ impl<'a> Resolver<'a> { if ident.name == kw::Invalid { return Some(LexicalScopeBinding::Res(Res::Err)); } - ident.span = if ident.name == kw::SelfUpper { + let (general_span, modern_span) = if ident.name == kw::SelfUpper { // FIXME(jseyfried) improve `Self` hygiene - ident.span.with_ctxt(SyntaxContext::empty()) + let empty_span = ident.span.with_ctxt(SyntaxContext::empty()); + (empty_span, empty_span) } else if ns == TypeNS { - ident.span.modern() + let modern_span = ident.span.modern(); + (modern_span, modern_span) } else { - ident.span.modern_and_legacy() + (ident.span.modern_and_legacy(), ident.span.modern()) }; + ident.span = general_span; + let modern_ident = Ident { span: modern_span, ..ident }; // Walk backwards up the ribs in scope. let record_used = record_used_id.is_some(); let mut module = self.graph_root; for i in (0 .. self.ribs[ns].len()).rev() { debug!("walk rib\n{:?}", self.ribs[ns][i].bindings); - if let Some(res) = self.ribs[ns][i].bindings.get(&ident).cloned() { + // Use the rib kind to determine whether we are resolving parameters + // (modern hygiene) or local variables (legacy hygiene). + let rib_ident = if let AssocItemRibKind | ItemRibKind = self.ribs[ns][i].kind { + modern_ident + } else { + ident + }; + if let Some(res) = self.ribs[ns][i].bindings.get(&rib_ident).cloned() { // The ident resolves to a type parameter or local variable. return Some(LexicalScopeBinding::Res( self.validate_res_from_ribs(ns, i, res, record_used, path_span), @@ -2360,7 +2370,7 @@ impl<'a> Resolver<'a> { } } - ident.span = ident.span.modern(); + ident = modern_ident; let mut poisoned = None; loop { let opt_module = if let Some(node_id) = record_used_id { diff --git a/src/test/ui/hygiene/generic_params.rs b/src/test/ui/hygiene/generic_params.rs new file mode 100644 index 0000000000000..9dc5adfce478a --- /dev/null +++ b/src/test/ui/hygiene/generic_params.rs @@ -0,0 +1,104 @@ +// Ensure that generic parameters always have modern hygiene. + +// check-pass +// ignore-pretty pretty-printing is unhygienic + +#![feature(decl_macro, rustc_attrs, const_generics)] + +mod type_params { + macro m($T:ident) { + fn f<$T: Clone, T: PartialEq>(t1: $T, t2: T) -> ($T, bool) { + (t1.clone(), t2 == t2) + } + } + + #[rustc_macro_transparency = "semitransparent"] + macro n($T:ident) { + fn g<$T: Clone>(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + fn h(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + } + + #[rustc_macro_transparency = "transparent"] + macro p($T:ident) { + fn j<$T: Clone>(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + fn k(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + } + + m!(T); + n!(T); + p!(T); +} + +mod lifetime_params { + macro m($a:lifetime) { + fn f<'b, 'c, $a: 'b, 'a: 'c>(t1: &$a(), t2: &'a ()) -> (&'b (), &'c ()) { + (t1, t2) + } + } + + #[rustc_macro_transparency = "semitransparent"] + macro n($a:lifetime) { + fn g<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + fn h<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + } + + #[rustc_macro_transparency = "transparent"] + macro p($a:lifetime) { + fn j<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + fn k<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + } + + m!('a); + n!('a); + p!('a); +} + +mod const_params { + macro m($C:ident) { + fn f(t1: [(); $C], t2: [(); C]) -> ([(); $C], [(); C]) { + (t1, t2) + } + } + + #[rustc_macro_transparency = "semitransparent"] + macro n($C:ident) { + fn g(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + fn h(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + } + + #[rustc_macro_transparency = "transparent"] + macro p($C:ident) { + fn j(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + fn k(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + } + + m!(C); + n!(C); + p!(C); +} + +fn main() {} diff --git a/src/test/ui/hygiene/generic_params.stderr b/src/test/ui/hygiene/generic_params.stderr new file mode 100644 index 0000000000000..ecd228a5db5c8 --- /dev/null +++ b/src/test/ui/hygiene/generic_params.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/generic_params.rs:6:37 + | +LL | #![feature(decl_macro, rustc_attrs, const_generics)] + | ^^^^^^^^^^^^^^ + diff --git a/src/test/ui/hygiene/ty_params.rs b/src/test/ui/hygiene/ty_params.rs deleted file mode 100644 index b296bfe598887..0000000000000 --- a/src/test/ui/hygiene/ty_params.rs +++ /dev/null @@ -1,14 +0,0 @@ -// check-pass -// ignore-pretty pretty-printing is unhygienic - -#![feature(decl_macro)] - -macro m($T:ident) { - fn f(t: T, t2: $T) -> (T, $T) { - (t, t2) - } -} - -m!(T); - -fn main() {}