diff --git a/crates/edition/src/lib.rs b/crates/edition/src/lib.rs index c25d5b9557..7e9c94af40 100644 --- a/crates/edition/src/lib.rs +++ b/crates/edition/src/lib.rs @@ -5,7 +5,8 @@ use std::fmt; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(u8)] pub enum Edition { - Edition2015, + // The syntax context stuff needs the discriminants to start from 0 and be consecutive. + Edition2015 = 0, Edition2018, Edition2021, Edition2024, diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index 433a956ff9..de43924930 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -15,7 +15,7 @@ use hir_expand::{name::Name, ExpandError, InFile}; use la_arena::{Arena, ArenaMap, Idx, RawIdx}; use rustc_hash::FxHashMap; use smallvec::SmallVec; -use span::{Edition, MacroFileId}; +use span::{Edition, MacroFileId, SyntaxContextData}; use syntax::{ast, AstPtr, SyntaxNodePtr}; use triomphe::Arc; use tt::TextRange; @@ -37,15 +37,22 @@ use crate::{ /// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct HygieneId(pub(crate) span::SyntaxContextId); +pub struct HygieneId(span::SyntaxContextId); impl HygieneId { - pub const ROOT: Self = Self(span::SyntaxContextId::ROOT); + // The edition doesn't matter here, we only use this for comparisons and to lookup the macro. + pub const ROOT: Self = Self(span::SyntaxContextId::root(Edition::Edition2015)); - pub fn new(ctx: span::SyntaxContextId) -> Self { + pub fn new(mut ctx: span::SyntaxContextId) -> Self { + // See `Name` for why we're doing that. + ctx.remove_root_edition(); Self(ctx) } + pub(crate) fn lookup(self, db: &dyn DefDatabase) -> SyntaxContextData { + db.lookup_intern_syntax_context(self.0) + } + pub(crate) fn is_root(self) -> bool { self.0.is_root() } diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index eed9f9468f..71d8b81236 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -2460,7 +2460,7 @@ impl ExprCollector<'_> { None => HygieneId::ROOT, Some(span_map) => { let ctx = span_map.span_at(span_start).ctx; - HygieneId(self.db.lookup_intern_syntax_context(ctx).opaque_and_semitransparent) + HygieneId::new(self.db.lookup_intern_syntax_context(ctx).opaque_and_semitransparent) } } } diff --git a/crates/hir-def/src/expander.rs b/crates/hir-def/src/expander.rs index 5315c1c6fb..108258d5a1 100644 --- a/crates/hir-def/src/expander.rs +++ b/crates/hir-def/src/expander.rs @@ -10,7 +10,7 @@ use hir_expand::{ ExpandResult, HirFileId, InFile, Lookup, MacroCallId, }; use limit::Limit; -use span::SyntaxContextId; +use span::{Edition, SyntaxContextId}; use syntax::{ast, Parse}; use triomphe::Arc; @@ -60,7 +60,7 @@ impl Expander { pub fn syntax_context(&self) -> SyntaxContextId { // FIXME: - SyntaxContextId::ROOT + SyntaxContextId::root(Edition::CURRENT) } pub fn enter_expand( diff --git a/crates/hir-def/src/item_tree/tests.rs b/crates/hir-def/src/item_tree/tests.rs index 0f53969d6c..735586c049 100644 --- a/crates/hir-def/src/item_tree/tests.rs +++ b/crates/hir-def/src/item_tree/tests.rs @@ -270,7 +270,7 @@ m!(); // AstId: 2 pub macro m2 { ... } - // AstId: 3, SyntaxContext: 0, ExpandTo: Items + // AstId: 3, SyntaxContext: 2, ExpandTo: Items m!(...); "#]], ); diff --git a/crates/hir-def/src/macro_expansion_tests/mbe.rs b/crates/hir-def/src/macro_expansion_tests/mbe.rs index 511626b5ed..8c5bd3b6d3 100644 --- a/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -35,9 +35,9 @@ macro_rules! f { }; } -struct#0:1@58..64#1# MyTraitMap2#0:2@31..42#0# {#0:1@72..73#1# - map#0:1@86..89#1#:#0:1@89..90#1# #0:1@89..90#1#::#0:1@91..93#1#std#0:1@93..96#1#::#0:1@96..98#1#collections#0:1@98..109#1#::#0:1@109..111#1#HashSet#0:1@111..118#1#<#0:1@118..119#1#(#0:1@119..120#1#)#0:1@120..121#1#>#0:1@121..122#1#,#0:1@122..123#1# -}#0:1@132..133#1# +struct#0:1@58..64#4# MyTraitMap2#0:2@31..42#2# {#0:1@72..73#4# + map#0:1@86..89#4#:#0:1@89..90#4# #0:1@89..90#4#::#0:1@91..93#4#std#0:1@93..96#4#::#0:1@96..98#4#collections#0:1@98..109#4#::#0:1@109..111#4#HashSet#0:1@111..118#4#<#0:1@118..119#4#(#0:1@119..120#4#)#0:1@120..121#4#>#0:1@121..122#4#,#0:1@122..123#4# +}#0:1@132..133#4# "#]], ); } @@ -75,12 +75,12 @@ macro_rules! f { }; } -fn#0:2@30..32#0# main#0:2@33..37#0#(#0:2@37..38#0#)#0:2@38..39#0# {#0:2@40..41#0# - 1#0:2@50..51#0#;#0:2@51..52#0# - 1.0#0:2@61..64#0#;#0:2@64..65#0# - (#0:2@74..75#0#(#0:2@75..76#0#1#0:2@76..77#0#,#0:2@77..78#0# )#0:2@78..79#0#,#0:2@79..80#0# )#0:2@80..81#0#.#0:2@81..82#0#0#0:2@82..85#0#.#0:2@82..85#0#0#0:2@82..85#0#;#0:2@85..86#0# - let#0:2@95..98#0# x#0:2@99..100#0# =#0:2@101..102#0# 1#0:2@103..104#0#;#0:2@104..105#0# -}#0:2@110..111#0# +fn#0:2@30..32#2# main#0:2@33..37#2#(#0:2@37..38#2#)#0:2@38..39#2# {#0:2@40..41#2# + 1#0:2@50..51#2#;#0:2@51..52#2# + 1.0#0:2@61..64#2#;#0:2@64..65#2# + (#0:2@74..75#2#(#0:2@75..76#2#1#0:2@76..77#2#,#0:2@77..78#2# )#0:2@78..79#2#,#0:2@79..80#2# )#0:2@80..81#2#.#0:2@81..82#2#0#0:2@82..85#2#.#0:2@82..85#2#0#0:2@82..85#2#;#0:2@85..86#2# + let#0:2@95..98#2# x#0:2@99..100#2# =#0:2@101..102#2# 1#0:2@103..104#2#;#0:2@104..105#2# +}#0:2@110..111#2# "#]], @@ -171,7 +171,7 @@ fn main(foo: ()) { } fn main(foo: ()) { - /* error: unresolved macro unresolved */"helloworld!"#0:3@236..321#0#; + /* error: unresolved macro unresolved */"helloworld!"#0:3@236..321#2#; } } @@ -197,7 +197,7 @@ macro_rules! mk_struct { #[macro_use] mod foo; -struct#1:1@59..65#1# Foo#0:2@32..35#0#(#1:1@70..71#1#u32#0:2@41..44#0#)#1:1@74..75#1#;#1:1@75..76#1# +struct#1:1@59..65#4# Foo#0:2@32..35#2#(#1:1@70..71#4#u32#0:2@41..44#2#)#1:1@74..75#4#;#1:1@75..76#4# "#]], ); } @@ -423,10 +423,10 @@ m! { foo, bar } macro_rules! m { ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } ); } -impl#\1# Bar#\1# {#\1# - fn#\1# foo#\0#(#\1#)#\1# {#\1#}#\1# - fn#\1# bar#\0#(#\1#)#\1# {#\1#}#\1# -}#\1# +impl#\4# Bar#\4# {#\4# + fn#\4# foo#\2#(#\4#)#\4# {#\4#}#\4# + fn#\4# bar#\2#(#\4#)#\4# {#\4#}#\4# +}#\4# "#]], ); } diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs index 5b9ffdf37b..adcf278472 100644 --- a/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -358,6 +358,7 @@ impl ProcMacroExpander for IdentityWhenValidProcMacroExpander { let (parse, _) = syntax_bridge::token_tree_to_syntax_node( subtree, syntax_bridge::TopEntryPoint::MacroItems, + &mut |_| span::Edition::CURRENT, span::Edition::CURRENT, ); if parse.errors().is_empty() { diff --git a/crates/hir-def/src/macro_expansion_tests/proc_macros.rs b/crates/hir-def/src/macro_expansion_tests/proc_macros.rs index c0178adc9a..70e3e1ed4e 100644 --- a/crates/hir-def/src/macro_expansion_tests/proc_macros.rs +++ b/crates/hir-def/src/macro_expansion_tests/proc_macros.rs @@ -181,9 +181,9 @@ fn foo(&self) { self.0. 1; } -fn#0:1@45..47#0# foo#0:1@48..51#0#(#0:1@51..52#0#�:1@52..53#0#self#0:1@53..57#0# )#0:1@57..58#0# {#0:1@59..60#0# - self#0:1@65..69#0# .#0:1@69..70#0#0#0:1@70..71#0#.#0:1@71..72#0#1#0:1@73..74#0#;#0:1@74..75#0# -}#0:1@76..77#0#"#]], +fn#0:1@45..47#2# foo#0:1@48..51#2#(#0:1@51..52#2#�:1@52..53#2#self#0:1@53..57#2# )#0:1@57..58#2# {#0:1@59..60#2# + self#0:1@65..69#2# .#0:1@69..70#2#0#0:1@70..71#2#.#0:1@71..72#2#1#0:1@73..74#2#;#0:1@74..75#2# +}#0:1@76..77#2#"#]], ); } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index de76257587..988e5e83c8 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -74,7 +74,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI let proc_macros = if krate.is_proc_macro { db.proc_macros() - .for_crate(def_map.krate, db.syntax_context(tree_id.file_id())) + .for_crate(def_map.krate, db.syntax_context(tree_id.file_id(), krate.edition)) .unwrap_or_default() } else { Default::default() diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 82da57a9bb..df48ce6737 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -324,7 +324,7 @@ impl Resolver { if n_segments <= 1 { let mut hygiene_info = if !hygiene_id.is_root() { - let ctx = db.lookup_intern_syntax_context(hygiene_id.0); + let ctx = hygiene_id.lookup(db); ctx.outer_expn.map(|expansion| { let expansion = db.lookup_intern_macro_call(expansion); (ctx.parent, expansion.def) diff --git a/crates/hir-expand/src/builtin/derive_macro.rs b/crates/hir-expand/src/builtin/derive_macro.rs index 4510a593af..28b6812139 100644 --- a/crates/hir-expand/src/builtin/derive_macro.rs +++ b/crates/hir-expand/src/builtin/derive_macro.rs @@ -4,7 +4,7 @@ use intern::sym; use itertools::{izip, Itertools}; use parser::SyntaxKind; use rustc_hash::FxHashSet; -use span::{MacroCallId, Span, SyntaxContextId}; +use span::{Edition, MacroCallId, Span, SyntaxContextId}; use stdx::never; use syntax_bridge::DocCommentDesugarMode; use tracing::debug; @@ -33,7 +33,7 @@ macro_rules! register_builtin { } impl BuiltinDeriveExpander { - pub fn expander(&self) -> fn(Span, &tt::TopSubtree) -> ExpandResult { + pub fn expander(&self) -> fn(&dyn ExpandDatabase, Span, &tt::TopSubtree) -> ExpandResult { match *self { $( BuiltinDeriveExpander::$trait => $expand, )* } @@ -58,8 +58,8 @@ impl BuiltinDeriveExpander { tt: &tt::TopSubtree, span: Span, ) -> ExpandResult { - let span = span_with_def_site_ctxt(db, span, id); - self.expander()(span, tt) + let span = span_with_def_site_ctxt(db, span, id, Edition::CURRENT); + self.expander()(db, span, tt) } } @@ -226,8 +226,12 @@ struct AdtParam { } // FIXME: This whole thing needs a refactor. Each derive requires its special values, and the result is a mess. -fn parse_adt(tt: &tt::TopSubtree, call_site: Span) -> Result { - let (adt, tm) = to_adt_syntax(tt, call_site)?; +fn parse_adt( + db: &dyn ExpandDatabase, + tt: &tt::TopSubtree, + call_site: Span, +) -> Result { + let (adt, tm) = to_adt_syntax(db, tt, call_site)?; parse_adt_from_syntax(&adt, &tm, call_site) } @@ -382,12 +386,14 @@ fn parse_adt_from_syntax( } fn to_adt_syntax( + db: &dyn ExpandDatabase, tt: &tt::TopSubtree, call_site: Span, ) -> Result<(ast::Adt, span::SpanMap), ExpandError> { - let (parsed, tm) = syntax_bridge::token_tree_to_syntax_node( + let (parsed, tm) = crate::db::token_tree_to_syntax_node( + db, tt, - syntax_bridge::TopEntryPoint::MacroItems, + crate::ExpandTo::Items, parser::Edition::CURRENT_FIXME, ); let macro_items = ast::MacroItems::cast(parsed.syntax_node()) @@ -446,12 +452,13 @@ fn name_to_token( /// where B1, ..., BN are the bounds given by `bounds_paths`. Z is a phantom type, and /// therefore does not get bound by the derived trait. fn expand_simple_derive( + db: &dyn ExpandDatabase, invoc_span: Span, tt: &tt::TopSubtree, trait_path: tt::TopSubtree, make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::TopSubtree, ) -> ExpandResult { - let info = match parse_adt(tt, invoc_span) { + let info = match parse_adt(db, tt, invoc_span) { Ok(info) => info, Err(e) => { return ExpandResult::new( @@ -520,14 +527,22 @@ fn expand_simple_derive_with_parsed( } } -fn copy_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult { +fn copy_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult { let krate = dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::marker::Copy }, |_| quote! {span =>}) + expand_simple_derive(db, span, tt, quote! {span => #krate::marker::Copy }, |_| quote! {span =>}) } -fn clone_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult { +fn clone_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult { let krate = dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::clone::Clone }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::clone::Clone }, |adt| { if matches!(adt.shape, AdtShape::Union) { let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span }; return quote! {span => @@ -576,9 +591,13 @@ fn and_and(span: Span) -> tt::TopSubtree { quote! {span => #and& } } -fn default_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult { +fn default_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult { let krate = &dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::default::Default }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::default::Default }, |adt| { let body = match &adt.shape { AdtShape::Struct(fields) => { let name = &adt.name; @@ -615,9 +634,13 @@ fn default_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult ExpandResult { +fn debug_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult { let krate = &dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::fmt::Debug }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::fmt::Debug }, |adt| { let for_variant = |name: String, v: &VariantShape| match v { VariantShape::Struct(fields) => { let for_fields = fields.iter().map(|it| { @@ -687,9 +710,13 @@ fn debug_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult }) } -fn hash_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult { +fn hash_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult { let krate = &dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::hash::Hash }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::hash::Hash }, |adt| { if matches!(adt.shape, AdtShape::Union) { // FIXME: Return expand error here return quote! {span =>}; @@ -734,14 +761,22 @@ fn hash_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult }) } -fn eq_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult { +fn eq_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult { let krate = dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>}) + expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>}) } -fn partial_eq_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult { +fn partial_eq_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult { let krate = dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::cmp::PartialEq }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::PartialEq }, |adt| { if matches!(adt.shape, AdtShape::Union) { // FIXME: Return expand error here return quote! {span =>}; @@ -811,9 +846,13 @@ fn self_and_other_patterns( (self_patterns, other_patterns) } -fn ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult { +fn ord_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult { let krate = &dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::cmp::Ord }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::Ord }, |adt| { fn compare( krate: &tt::Ident, left: tt::TopSubtree, @@ -869,9 +908,13 @@ fn ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult { }) } -fn partial_ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult { +fn partial_ord_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult { let krate = &dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::cmp::PartialOrd }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::PartialOrd }, |adt| { fn compare( krate: &tt::Ident, left: tt::TopSubtree, @@ -932,8 +975,12 @@ fn partial_ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult ExpandResult { - let (adt, _span_map) = match to_adt_syntax(tt, span) { +fn coerce_pointee_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult { + let (adt, _span_map) = match to_adt_syntax(db, tt, span) { Ok(it) => it, Err(err) => { return ExpandResult::new(tt::TopSubtree::empty(tt::DelimSpan::from_single(span)), err); diff --git a/crates/hir-expand/src/builtin/fn_macro.rs b/crates/hir-expand/src/builtin/fn_macro.rs index 5b06de9875..310ddaaf9e 100644 --- a/crates/hir-expand/src/builtin/fn_macro.rs +++ b/crates/hir-expand/src/builtin/fn_macro.rs @@ -69,7 +69,7 @@ impl BuiltinFnLikeExpander { tt: &tt::TopSubtree, span: Span, ) -> ExpandResult { - let span = span_with_def_site_ctxt(db, span, id); + let span = span_with_def_site_ctxt(db, span, id, Edition::CURRENT); self.expander()(db, id, tt, span) } @@ -86,7 +86,7 @@ impl EagerExpander { tt: &tt::TopSubtree, span: Span, ) -> ExpandResult { - let span = span_with_def_site_ctxt(db, span, id); + let span = span_with_def_site_ctxt(db, span, id, Edition::CURRENT); self.expander()(db, id, tt, span) } @@ -221,7 +221,7 @@ fn assert_expand( tt: &tt::TopSubtree, span: Span, ) -> ExpandResult { - let call_site_span = span_with_call_site_ctxt(db, span, id); + let call_site_span = span_with_call_site_ctxt(db, span, id, Edition::CURRENT); let mut iter = tt.iter(); @@ -342,7 +342,7 @@ fn panic_expand( span: Span, ) -> ExpandResult { let dollar_crate = dollar_crate(span); - let call_site_span = span_with_call_site_ctxt(db, span, id); + let call_site_span = span_with_call_site_ctxt(db, span, id, Edition::CURRENT); let mac = if use_panic_2021(db, call_site_span) { sym::panic_2021.clone() @@ -373,7 +373,7 @@ fn unreachable_expand( span: Span, ) -> ExpandResult { let dollar_crate = dollar_crate(span); - let call_site_span = span_with_call_site_ctxt(db, span, id); + let call_site_span = span_with_call_site_ctxt(db, span, id, Edition::CURRENT); let mac = if use_panic_2021(db, call_site_span) { sym::unreachable_2021.clone() diff --git a/crates/hir-expand/src/builtin/quote.rs b/crates/hir-expand/src/builtin/quote.rs index 6c1abc2620..fcd242bb49 100644 --- a/crates/hir-expand/src/builtin/quote.rs +++ b/crates/hir-expand/src/builtin/quote.rs @@ -225,7 +225,7 @@ mod tests { use ::tt::IdentIsRaw; use expect_test::expect; use intern::Symbol; - use span::{SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; + use span::{Edition, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; use syntax::{TextRange, TextSize}; use super::quote; @@ -239,7 +239,7 @@ mod tests { ), ast_id: ROOT_ERASED_FILE_AST_ID, }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }; #[test] @@ -276,8 +276,8 @@ mod tests { assert_eq!(quoted.to_string(), "hello"); let t = format!("{quoted:#?}"); expect![[r#" - SUBTREE $$ 937550:0@0..0#0 937550:0@0..0#0 - IDENT hello 937550:0@0..0#0"#]] + SUBTREE $$ 937550:0@0..0#2 937550:0@0..0#2 + IDENT hello 937550:0@0..0#2"#]] .assert_eq(&t); } diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index f4e80ef9e2..b7804f888a 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -5,7 +5,7 @@ use either::Either; use limit::Limit; use mbe::MatchedArmIndex; use rustc_hash::FxHashSet; -use span::{AstIdMap, EditionedFileId, Span, SyntaxContextData, SyntaxContextId}; +use span::{AstIdMap, Edition, EditionedFileId, Span, SyntaxContextData, SyntaxContextId}; use syntax::{ast, AstNode, Parse, SyntaxElement, SyntaxError, SyntaxNode, SyntaxToken, T}; use syntax_bridge::{syntax_node_to_token_tree, DocCommentDesugarMode}; use triomphe::Arc; @@ -136,12 +136,12 @@ pub trait ExpandDatabase: SourceDatabase { macro_call: MacroCallId, ) -> Option>>>; #[ra_salsa::transparent] - fn syntax_context(&self, file: HirFileId) -> SyntaxContextId; + fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContextId; } -fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId) -> SyntaxContextId { +fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId, edition: Edition) -> SyntaxContextId { match file.repr() { - HirFileIdRepr::FileId(_) => SyntaxContextId::ROOT, + HirFileIdRepr::FileId(_) => SyntaxContextId::root(edition), HirFileIdRepr::MacroFile(m) => { db.macro_arg_considering_derives(m.macro_call_id, &m.macro_call_id.lookup(db).kind) .2 @@ -273,9 +273,9 @@ pub fn expand_speculative( loc.krate, &tt, attr_arg.as_ref(), - span_with_def_site_ctxt(db, span, actual_macro_call), - span_with_call_site_ctxt(db, span, actual_macro_call), - span_with_mixed_site_ctxt(db, span, actual_macro_call), + span_with_def_site_ctxt(db, span, actual_macro_call, loc.def.edition), + span_with_call_site_ctxt(db, span, actual_macro_call, loc.def.edition), + span_with_mixed_site_ctxt(db, span, actual_macro_call, loc.def.edition), ) } MacroDefKind::BuiltInAttr(_, it) if it.is_derive() => { @@ -300,7 +300,7 @@ pub fn expand_speculative( fixup::reverse_fixups(&mut speculative_expansion.value, &undo_info); let (node, rev_tmap) = - token_tree_to_syntax_node(&speculative_expansion.value, expand_to, loc.def.edition); + token_tree_to_syntax_node(db, &speculative_expansion.value, expand_to, loc.def.edition); let syntax_node = node.syntax_node(); let token = rev_tmap @@ -346,6 +346,7 @@ fn parse_macro_expansion( macro_expand(db, macro_file.macro_call_id, loc); let (parse, mut rev_token_map) = token_tree_to_syntax_node( + db, match &tt { CowArc::Arc(it) => it, CowArc::Owned(it) => it, @@ -699,9 +700,9 @@ fn expand_proc_macro( loc.krate, ¯o_arg, attr_arg, - span_with_def_site_ctxt(db, span, id), - span_with_call_site_ctxt(db, span, id), - span_with_mixed_site_ctxt(db, span, id), + span_with_def_site_ctxt(db, span, id, loc.def.edition), + span_with_call_site_ctxt(db, span, id, loc.def.edition), + span_with_mixed_site_ctxt(db, span, id, loc.def.edition), ) }; @@ -715,7 +716,8 @@ fn expand_proc_macro( ExpandResult { value: Arc::new(tt), err } } -fn token_tree_to_syntax_node( +pub(crate) fn token_tree_to_syntax_node( + db: &dyn ExpandDatabase, tt: &tt::TopSubtree, expand_to: ExpandTo, edition: parser::Edition, @@ -727,7 +729,12 @@ fn token_tree_to_syntax_node( ExpandTo::Type => syntax_bridge::TopEntryPoint::Type, ExpandTo::Expr => syntax_bridge::TopEntryPoint::Expr, }; - syntax_bridge::token_tree_to_syntax_node(tt, entry_point, edition) + syntax_bridge::token_tree_to_syntax_node( + tt, + entry_point, + &mut |ctx| ctx.lookup(db).edition, + edition, + ) } fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> { @@ -751,5 +758,7 @@ fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> { } fn setup_syntax_context_root(db: &dyn ExpandDatabase) { - db.intern_syntax_context(SyntaxContextData::root()); + for edition in Edition::iter() { + db.intern_syntax_context(SyntaxContextData::root(edition)); + } } diff --git a/crates/hir-expand/src/declarative.rs b/crates/hir-expand/src/declarative.rs index d1c39f32ca..fef77acb7b 100644 --- a/crates/hir-expand/src/declarative.rs +++ b/crates/hir-expand/src/declarative.rs @@ -2,7 +2,7 @@ use base_db::CrateId; use intern::sym; -use span::{Edition, MacroCallId, Span, SyntaxContextId}; +use span::{Edition, HirFileIdRepr, MacroCallId, Span, SyntaxContextId}; use stdx::TupleExt; use syntax::{ast, AstNode}; use syntax_bridge::DocCommentDesugarMode; @@ -20,6 +20,7 @@ use crate::{ pub struct DeclarativeMacroExpander { pub mac: mbe::DeclarativeMacro, pub transparency: Transparency, + edition: Edition, } impl DeclarativeMacroExpander { @@ -40,7 +41,7 @@ impl DeclarativeMacroExpander { .mac .expand( &tt, - |s| s.ctx = apply_mark(db, s.ctx, call_id, self.transparency), + |s| s.ctx = apply_mark(db, s.ctx, call_id, self.transparency, self.edition), span, loc.def.edition, ) @@ -159,6 +160,10 @@ impl DeclarativeMacroExpander { transparency(¯o_def).unwrap_or(Transparency::Opaque), ), }; - Arc::new(DeclarativeMacroExpander { mac, transparency }) + let edition = ctx_edition(match id.file_id.repr() { + HirFileIdRepr::MacroFile(macro_file) => macro_file.macro_call_id.lookup(db).ctxt, + HirFileIdRepr::FileId(file) => SyntaxContextId::root(file.edition()), + }); + Arc::new(DeclarativeMacroExpander { mac, transparency, edition }) } } diff --git a/crates/hir-expand/src/files.rs b/crates/hir-expand/src/files.rs index 8c04d05402..13ddb0d4ac 100644 --- a/crates/hir-expand/src/files.rs +++ b/crates/hir-expand/src/files.rs @@ -380,14 +380,14 @@ impl InFile { ) -> (FileRange, SyntaxContextId) { match self.file_id.repr() { HirFileIdRepr::FileId(file_id) => { - (FileRange { file_id, range: self.value }, SyntaxContextId::ROOT) + (FileRange { file_id, range: self.value }, SyntaxContextId::root(file_id.edition())) } HirFileIdRepr::MacroFile(mac_file) => { match map_node_range_up(db, &db.expansion_span_map(mac_file), self.value) { Some(it) => it, None => { let loc = db.lookup_intern_macro_call(mac_file.macro_call_id); - (loc.kind.original_call_range(db), SyntaxContextId::ROOT) + (loc.kind.original_call_range(db), SyntaxContextId::root(loc.def.edition)) } } } @@ -432,9 +432,10 @@ impl InFile { db: &dyn db::ExpandDatabase, ) -> Option<(FileRange, SyntaxContextId)> { match self.file_id.repr() { - HirFileIdRepr::FileId(file_id) => { - Some((FileRange { file_id, range: self.value }, SyntaxContextId::ROOT)) - } + HirFileIdRepr::FileId(file_id) => Some(( + FileRange { file_id, range: self.value }, + SyntaxContextId::root(file_id.edition()), + )), HirFileIdRepr::MacroFile(mac_file) => { map_node_range_up(db, &db.expansion_span_map(mac_file), self.value) } diff --git a/crates/hir-expand/src/fixup.rs b/crates/hir-expand/src/fixup.rs index 90012dd1f7..00fad67578 100644 --- a/crates/hir-expand/src/fixup.rs +++ b/crates/hir-expand/src/fixup.rs @@ -380,7 +380,7 @@ pub(crate) fn reverse_fixups(tt: &mut TopSubtree, undo_info: &SyntaxFixupUndoInf let span = |file_id| Span { range: TextRange::empty(TextSize::new(0)), anchor: SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(span::Edition::Edition2015), }; delimiter.open = span(delimiter.open.anchor.file_id); delimiter.close = span(delimiter.close.anchor.file_id); @@ -554,6 +554,7 @@ mod tests { let (parse, _) = syntax_bridge::token_tree_to_syntax_node( &tt, syntax_bridge::TopEntryPoint::MacroItems, + &mut |_| parser::Edition::CURRENT, parser::Edition::CURRENT, ); assert!( diff --git a/crates/hir-expand/src/hygiene.rs b/crates/hir-expand/src/hygiene.rs index f48de807c2..fe05af0ac9 100644 --- a/crates/hir-expand/src/hygiene.rs +++ b/crates/hir-expand/src/hygiene.rs @@ -24,26 +24,37 @@ use std::iter; -use span::{MacroCallId, Span, SyntaxContextData, SyntaxContextId}; +use span::{Edition, MacroCallId, Span, SyntaxContextData, SyntaxContextId}; use crate::db::{ExpandDatabase, InternSyntaxContextQuery}; pub use span::Transparency; -pub fn span_with_def_site_ctxt(db: &dyn ExpandDatabase, span: Span, expn_id: MacroCallId) -> Span { - span_with_ctxt_from_mark(db, span, expn_id, Transparency::Opaque) +pub fn span_with_def_site_ctxt( + db: &dyn ExpandDatabase, + span: Span, + expn_id: MacroCallId, + edition: Edition, +) -> Span { + span_with_ctxt_from_mark(db, span, expn_id, Transparency::Opaque, edition) } -pub fn span_with_call_site_ctxt(db: &dyn ExpandDatabase, span: Span, expn_id: MacroCallId) -> Span { - span_with_ctxt_from_mark(db, span, expn_id, Transparency::Transparent) +pub fn span_with_call_site_ctxt( + db: &dyn ExpandDatabase, + span: Span, + expn_id: MacroCallId, + edition: Edition, +) -> Span { + span_with_ctxt_from_mark(db, span, expn_id, Transparency::Transparent, edition) } pub fn span_with_mixed_site_ctxt( db: &dyn ExpandDatabase, span: Span, expn_id: MacroCallId, + edition: Edition, ) -> Span { - span_with_ctxt_from_mark(db, span, expn_id, Transparency::SemiTransparent) + span_with_ctxt_from_mark(db, span, expn_id, Transparency::SemiTransparent, edition) } fn span_with_ctxt_from_mark( @@ -51,8 +62,12 @@ fn span_with_ctxt_from_mark( span: Span, expn_id: MacroCallId, transparency: Transparency, + edition: Edition, ) -> Span { - Span { ctx: apply_mark(db, SyntaxContextId::ROOT, expn_id, transparency), ..span } + Span { + ctx: apply_mark(db, SyntaxContextId::root(edition), expn_id, transparency, edition), + ..span + } } pub(super) fn apply_mark( @@ -60,9 +75,10 @@ pub(super) fn apply_mark( ctxt: SyntaxContextId, call_id: MacroCallId, transparency: Transparency, + edition: Edition, ) -> SyntaxContextId { if transparency == Transparency::Opaque { - return apply_mark_internal(db, ctxt, call_id, transparency); + return apply_mark_internal(db, ctxt, call_id, transparency, edition); } let call_site_ctxt = db.lookup_intern_macro_call(call_id).ctxt; @@ -73,7 +89,7 @@ pub(super) fn apply_mark( }; if call_site_ctxt.is_root() { - return apply_mark_internal(db, ctxt, call_id, transparency); + return apply_mark_internal(db, ctxt, call_id, transparency, edition); } // Otherwise, `expn_id` is a macros 1.0 definition and the call site is in a @@ -86,9 +102,9 @@ pub(super) fn apply_mark( // // See the example at `test/ui/hygiene/legacy_interaction.rs`. for (call_id, transparency) in ctxt.marks(db) { - call_site_ctxt = apply_mark_internal(db, call_site_ctxt, call_id, transparency); + call_site_ctxt = apply_mark_internal(db, call_site_ctxt, call_id, transparency, edition); } - apply_mark_internal(db, call_site_ctxt, call_id, transparency) + apply_mark_internal(db, call_site_ctxt, call_id, transparency, edition) } fn apply_mark_internal( @@ -96,6 +112,7 @@ fn apply_mark_internal( ctxt: SyntaxContextId, call_id: MacroCallId, transparency: Transparency, + edition: Edition, ) -> SyntaxContextId { use base_db::ra_salsa; @@ -108,13 +125,14 @@ fn apply_mark_internal( if transparency >= Transparency::Opaque { let parent = opaque; opaque = ra_salsa::plumbing::get_query_table::(db).get_or_insert( - (parent, call_id, transparency), + (parent, call_id, transparency, edition), |new_opaque| SyntaxContextData { outer_expn: call_id, outer_transparency: transparency, parent, opaque: new_opaque, opaque_and_semitransparent: new_opaque, + edition, }, ); } @@ -123,13 +141,14 @@ fn apply_mark_internal( let parent = opaque_and_semitransparent; opaque_and_semitransparent = ra_salsa::plumbing::get_query_table::(db).get_or_insert( - (parent, call_id, transparency), + (parent, call_id, transparency, edition), |new_opaque_and_semitransparent| SyntaxContextData { outer_expn: call_id, outer_transparency: transparency, parent, opaque, opaque_and_semitransparent: new_opaque_and_semitransparent, + edition, }, ); } @@ -141,6 +160,7 @@ fn apply_mark_internal( parent, opaque, opaque_and_semitransparent, + edition, }) } diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index 7ecf521987..876919f3ed 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -273,10 +273,9 @@ fn convert_path( res } } - ast::PathSegmentKind::SelfTypeKw => ModPath::from_segments( - PathKind::Plain, - Some(Name::new_symbol(sym::Self_.clone(), SyntaxContextId::ROOT)), - ), + ast::PathSegmentKind::SelfTypeKw => { + ModPath::from_segments(PathKind::Plain, Some(Name::new_symbol_root(sym::Self_.clone()))) + } ast::PathSegmentKind::CrateKw => ModPath::from_segments(PathKind::Crate, iter::empty()), ast::PathSegmentKind::SelfKw => handle_super_kw(0)?, ast::PathSegmentKind::SuperKw => handle_super_kw(1)?, diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs index 267d545833..54a61a096d 100644 --- a/crates/hir-expand/src/name.rs +++ b/crates/hir-expand/src/name.rs @@ -80,11 +80,20 @@ impl Name { Name { symbol: Symbol::intern(text), ctx: () } } - pub fn new(text: &str, ctx: SyntaxContextId) -> Name { + pub fn new(text: &str, mut ctx: SyntaxContextId) -> Name { + // For comparisons etc. we remove the edition, because sometimes we search for some `Name` + // and we don't know which edition it came from. + // Can't do that for all `SyntaxContextId`s because it breaks Salsa. + ctx.remove_root_edition(); _ = ctx; Self::new_text(text) } + pub fn new_root(text: &str) -> Name { + // The edition doesn't matter for hygiene. + Self::new(text, SyntaxContextId::root(Edition::Edition2015)) + } + pub fn new_tuple_field(idx: usize) -> Name { Name { symbol: Symbol::intern(&idx.to_string()), ctx: () } } diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index a23fdf1b39..01cb040bdf 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -12,7 +12,6 @@ use hir_def::{ }; use hir_expand::{mod_path::PathKind, name::Name}; use hir_ty::{db::HirDatabase, method_resolution}; -use span::SyntaxContextId; use crate::{ Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl, @@ -328,9 +327,7 @@ fn doc_modpath_from_str(link: &str) -> Option { }; let parts = first_segment.into_iter().chain(parts).map(|segment| match segment.parse() { Ok(idx) => Name::new_tuple_field(idx), - Err(_) => { - Name::new(segment.split_once('<').map_or(segment, |it| it.0), SyntaxContextId::ROOT) - } + Err(_) => Name::new_root(segment.split_once('<').map_or(segment, |it| it.0)), }); Some(ModPath::from_segments(kind, parts)) }; diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index fe4b255d3c..ac109be5ef 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -83,7 +83,7 @@ use itertools::Itertools; use nameres::diagnostics::DefDiagnosticKind; use rustc_hash::FxHashSet; use smallvec::SmallVec; -use span::{Edition, EditionedFileId, FileId, MacroCallId, SyntaxContextId}; +use span::{Edition, EditionedFileId, FileId, MacroCallId}; use stdx::{format_to, impl_from, never}; use syntax::{ ast::{self, HasAttrs as _, HasGenericParams, HasName}, @@ -4824,7 +4824,7 @@ impl Type { let iterator_trait = db.lang_item(self.env.krate, LangItem::Iterator)?.as_trait()?; let iterator_item = db .trait_data(iterator_trait) - .associated_type_by_name(&Name::new_symbol(sym::Item.clone(), SyntaxContextId::ROOT))?; + .associated_type_by_name(&Name::new_symbol_root(sym::Item.clone()))?; self.normalize_trait_assoc_type(db, &[], iterator_item.into()) } diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 7f44f396bf..7414735016 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -959,7 +959,10 @@ impl<'db> SemanticsImpl<'db> { process_expansion_for_token(&mut stack, include)?; } None => { - stack.push((file_id.into(), smallvec![(token, SyntaxContextId::ROOT)])); + stack.push(( + file_id.into(), + smallvec![(token, SyntaxContextId::root(file_id.edition()))], + )); } } @@ -1571,7 +1574,7 @@ impl<'db> SemanticsImpl<'db> { self.db.upcast(), &ModPath::from_segments( hir_def::path::PathKind::Plain, - segments.into_iter().map(|it| Name::new(&it, SyntaxContextId::ROOT)), + segments.into_iter().map(|it| Name::new_root(&it)), ), ); Some(items.iter_items().map(|(item, _)| item.into())) diff --git a/crates/ide-diagnostics/src/handlers/no_such_field.rs b/crates/ide-diagnostics/src/handlers/no_such_field.rs index e5d871975b..0f126a1a65 100644 --- a/crates/ide-diagnostics/src/handlers/no_such_field.rs +++ b/crates/ide-diagnostics/src/handlers/no_such_field.rs @@ -399,4 +399,38 @@ fn f(s@m::Struct { "#, ) } + + #[test] + fn editions_between_macros() { + check_diagnostics( + r#" +//- /edition2015.rs crate:edition2015 edition:2015 +#[macro_export] +macro_rules! pass_expr_thorough { + ($e:expr) => { $e }; +} + +//- /edition2018.rs crate:edition2018 deps:edition2015 edition:2018 +async fn bar() {} +async fn foo() { + edition2015::pass_expr_thorough!(bar().await); +} + "#, + ); + check_diagnostics( + r#" +//- /edition2018.rs crate:edition2018 edition:2018 +pub async fn bar() {} +#[macro_export] +macro_rules! make_await { + () => { async { $crate::bar().await }; }; +} + +//- /edition2015.rs crate:edition2015 deps:edition2018 edition:2015 +fn foo() { + edition2018::make_await!(); +} + "#, + ); + } } diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs index 6abf56d4b3..bebd29ef74 100644 --- a/crates/mbe/src/lib.rs +++ b/crates/mbe/src/lib.rs @@ -369,7 +369,8 @@ pub fn expect_fragment<'t>( ) -> ExpandResult> { use ::parser; let buffer = tt_iter.remaining(); - let parser_input = to_parser_input(edition, buffer); + // FIXME: Pass the correct edition per token. Due to the split between mbe and hir-expand it's complicated. + let parser_input = to_parser_input(buffer, &mut |_ctx| edition); let tree_traversal = entry_point.parse(&parser_input, edition); let mut cursor = buffer.cursor(); let mut error = false; diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs index e63ad113ff..fb68d35a4c 100644 --- a/crates/mbe/src/tests.rs +++ b/crates/mbe/src/tests.rs @@ -26,7 +26,7 @@ fn check_( file_id: EditionedFileId::new(FileId::from_raw(0), def_edition), ast_id: ErasedFileAstId::from_raw(0), }, - SyntaxContextId::ROOT, + SyntaxContextId::root(Edition::CURRENT), decl, ) .unwrap(); @@ -39,16 +39,20 @@ fn check_( file_id: EditionedFileId::new(FileId::from_raw(1), call_edition), ast_id: ErasedFileAstId::from_raw(0), }; - let arg_tt = - syntax_bridge::parse_to_token_tree(call_edition, call_anchor, SyntaxContextId::ROOT, arg) - .unwrap(); + let arg_tt = syntax_bridge::parse_to_token_tree( + call_edition, + call_anchor, + SyntaxContextId::root(Edition::CURRENT), + arg, + ) + .unwrap(); let res = mac.expand( &arg_tt, |_| (), Span { range: TextRange::up_to(TextSize::of(arg)), anchor: call_anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, def_edition, ); @@ -59,7 +63,12 @@ fn check_( if render_debug { format_to!(expect_res, "{:#?}\n\n", res.value.0); } - let (node, _) = syntax_bridge::token_tree_to_syntax_node(&res.value.0, parse, def_edition); + let (node, _) = syntax_bridge::token_tree_to_syntax_node( + &res.value.0, + parse, + &mut |_| def_edition, + def_edition, + ); format_to!( expect_res, "{}", @@ -106,25 +115,25 @@ fn token_mapping_smoke_test() { struct MyTraitMap2 "#, expect![[r#" - SUBTREE $$ 1:0@0..20#0 1:0@0..20#0 - IDENT struct 0:0@34..40#0 - IDENT MyTraitMap2 1:0@8..19#0 - SUBTREE {} 0:0@48..49#0 0:0@100..101#0 - IDENT map 0:0@58..61#0 - PUNCH : [alone] 0:0@61..62#0 - PUNCH : [joint] 0:0@63..64#0 - PUNCH : [alone] 0:0@64..65#0 - IDENT std 0:0@65..68#0 - PUNCH : [joint] 0:0@68..69#0 - PUNCH : [alone] 0:0@69..70#0 - IDENT collections 0:0@70..81#0 - PUNCH : [joint] 0:0@81..82#0 - PUNCH : [alone] 0:0@82..83#0 - IDENT HashSet 0:0@83..90#0 - PUNCH < [alone] 0:0@90..91#0 - SUBTREE () 0:0@91..92#0 0:0@92..93#0 - PUNCH > [joint] 0:0@93..94#0 - PUNCH , [alone] 0:0@94..95#0 + SUBTREE $$ 1:0@0..20#2 1:0@0..20#2 + IDENT struct 0:0@34..40#2 + IDENT MyTraitMap2 1:0@8..19#2 + SUBTREE {} 0:0@48..49#2 0:0@100..101#2 + IDENT map 0:0@58..61#2 + PUNCH : [alone] 0:0@61..62#2 + PUNCH : [joint] 0:0@63..64#2 + PUNCH : [alone] 0:0@64..65#2 + IDENT std 0:0@65..68#2 + PUNCH : [joint] 0:0@68..69#2 + PUNCH : [alone] 0:0@69..70#2 + IDENT collections 0:0@70..81#2 + PUNCH : [joint] 0:0@81..82#2 + PUNCH : [alone] 0:0@82..83#2 + IDENT HashSet 0:0@83..90#2 + PUNCH < [alone] 0:0@90..91#2 + SUBTREE () 0:0@91..92#2 0:0@92..93#2 + PUNCH > [joint] 0:0@93..94#2 + PUNCH , [alone] 0:0@94..95#2 struct MyTraitMap2 { map: ::std::collections::HashSet<()>, @@ -153,28 +162,28 @@ fn main() { } "#, expect![[r#" - SUBTREE $$ 1:0@0..63#0 1:0@0..63#0 - IDENT fn 1:0@1..3#0 - IDENT main 1:0@4..8#0 - SUBTREE () 1:0@8..9#0 1:0@9..10#0 - SUBTREE {} 1:0@11..12#0 1:0@61..62#0 - LITERAL Integer 1 1:0@17..18#0 - PUNCH ; [alone] 1:0@18..19#0 - LITERAL Float 1.0 1:0@24..27#0 - PUNCH ; [alone] 1:0@27..28#0 - SUBTREE () 1:0@33..34#0 1:0@39..40#0 - SUBTREE () 1:0@34..35#0 1:0@37..38#0 - LITERAL Integer 1 1:0@35..36#0 - PUNCH , [alone] 1:0@36..37#0 - PUNCH , [alone] 1:0@38..39#0 - PUNCH . [alone] 1:0@40..41#0 - LITERAL Float 0.0 1:0@41..44#0 - PUNCH ; [alone] 1:0@44..45#0 - IDENT let 1:0@50..53#0 - IDENT x 1:0@54..55#0 - PUNCH = [alone] 1:0@56..57#0 - LITERAL Integer 1 1:0@58..59#0 - PUNCH ; [alone] 1:0@59..60#0 + SUBTREE $$ 1:0@0..63#2 1:0@0..63#2 + IDENT fn 1:0@1..3#2 + IDENT main 1:0@4..8#2 + SUBTREE () 1:0@8..9#2 1:0@9..10#2 + SUBTREE {} 1:0@11..12#2 1:0@61..62#2 + LITERAL Integer 1 1:0@17..18#2 + PUNCH ; [alone] 1:0@18..19#2 + LITERAL Float 1.0 1:0@24..27#2 + PUNCH ; [alone] 1:0@27..28#2 + SUBTREE () 1:0@33..34#2 1:0@39..40#2 + SUBTREE () 1:0@34..35#2 1:0@37..38#2 + LITERAL Integer 1 1:0@35..36#2 + PUNCH , [alone] 1:0@36..37#2 + PUNCH , [alone] 1:0@38..39#2 + PUNCH . [alone] 1:0@40..41#2 + LITERAL Float 0.0 1:0@41..44#2 + PUNCH ; [alone] 1:0@44..45#2 + IDENT let 1:0@50..53#2 + IDENT x 1:0@54..55#2 + PUNCH = [alone] 1:0@56..57#2 + LITERAL Integer 1 1:0@58..59#2 + PUNCH ; [alone] 1:0@59..60#2 fn main(){ 1; @@ -200,14 +209,14 @@ fn expr_2021() { const { 1 }, "#, expect![[r#" - SUBTREE $$ 1:0@0..25#0 1:0@0..25#0 - IDENT _ 1:0@5..6#0 - PUNCH ; [joint] 0:0@36..37#0 - SUBTREE () 0:0@34..35#0 0:0@34..35#0 - IDENT const 1:0@12..17#0 - SUBTREE {} 1:0@18..19#0 1:0@22..23#0 - LITERAL Integer 1 1:0@20..21#0 - PUNCH ; [alone] 0:0@39..40#0 + SUBTREE $$ 1:0@0..25#2 1:0@0..25#2 + IDENT _ 1:0@5..6#2 + PUNCH ; [joint] 0:0@36..37#2 + SUBTREE () 0:0@34..35#2 0:0@34..35#2 + IDENT const 1:0@12..17#2 + SUBTREE {} 1:0@18..19#2 1:0@22..23#2 + LITERAL Integer 1 1:0@20..21#2 + PUNCH ; [alone] 0:0@39..40#2 _; (const { @@ -228,13 +237,13 @@ fn expr_2021() { expect![[r#" ExpandError { inner: ( - 1:0@5..6#0, + 1:0@5..6#2, NoMatchingRule, ), } - SUBTREE $$ 1:0@0..8#0 1:0@0..8#0 - PUNCH ; [alone] 0:0@39..40#0 + SUBTREE $$ 1:0@0..8#2 1:0@0..8#2 + PUNCH ; [alone] 0:0@39..40#2 ;"#]], ); @@ -252,13 +261,13 @@ fn expr_2021() { expect![[r#" ExpandError { inner: ( - 1:0@5..10#0, + 1:0@5..10#2, NoMatchingRule, ), } - SUBTREE $$ 1:0@0..18#0 1:0@0..18#0 - PUNCH ; [alone] 0:0@39..40#0 + SUBTREE $$ 1:0@0..18#2 1:0@0..18#2 + PUNCH ; [alone] 0:0@39..40#2 ;"#]], ); @@ -278,26 +287,26 @@ fn expr_2021() { break 'foo bar, "#, expect![[r#" - SUBTREE $$ 1:0@0..76#0 1:0@0..76#0 - LITERAL Integer 4 1:0@5..6#0 - PUNCH ; [joint] 0:0@41..42#0 - LITERAL Str literal 1:0@12..21#0 - PUNCH ; [joint] 0:0@41..42#0 - SUBTREE () 0:0@39..40#0 0:0@39..40#0 - IDENT funcall 1:0@27..34#0 - SUBTREE () 1:0@34..35#0 1:0@35..36#0 - PUNCH ; [joint] 0:0@41..42#0 - SUBTREE () 0:0@39..40#0 0:0@39..40#0 - IDENT future 1:0@42..48#0 - PUNCH . [alone] 1:0@48..49#0 - IDENT await 1:0@49..54#0 - PUNCH ; [joint] 0:0@41..42#0 - SUBTREE () 0:0@39..40#0 0:0@39..40#0 - IDENT break 1:0@60..65#0 - PUNCH ' [joint] 1:0@66..67#0 - IDENT foo 1:0@67..70#0 - IDENT bar 1:0@71..74#0 - PUNCH ; [alone] 0:0@44..45#0 + SUBTREE $$ 1:0@0..76#2 1:0@0..76#2 + LITERAL Integer 4 1:0@5..6#2 + PUNCH ; [joint] 0:0@41..42#2 + LITERAL Str literal 1:0@12..21#2 + PUNCH ; [joint] 0:0@41..42#2 + SUBTREE () 0:0@39..40#2 0:0@39..40#2 + IDENT funcall 1:0@27..34#2 + SUBTREE () 1:0@34..35#2 1:0@35..36#2 + PUNCH ; [joint] 0:0@41..42#2 + SUBTREE () 0:0@39..40#2 0:0@39..40#2 + IDENT future 1:0@42..48#2 + PUNCH . [alone] 1:0@48..49#2 + IDENT await 1:0@49..54#2 + PUNCH ; [joint] 0:0@41..42#2 + SUBTREE () 0:0@39..40#2 0:0@39..40#2 + IDENT break 1:0@60..65#2 + PUNCH ' [joint] 1:0@66..67#2 + IDENT foo 1:0@67..70#2 + IDENT bar 1:0@71..74#2 + PUNCH ; [alone] 0:0@44..45#2 4; "literal"; @@ -319,13 +328,13 @@ fn expr_2021() { expect![[r#" ExpandError { inner: ( - 1:0@5..6#0, + 1:0@5..6#2, NoMatchingRule, ), } - SUBTREE $$ 1:0@0..8#0 1:0@0..8#0 - PUNCH ; [alone] 0:0@44..45#0 + SUBTREE $$ 1:0@0..8#2 1:0@0..8#2 + PUNCH ; [alone] 0:0@44..45#2 ;"#]], ); diff --git a/crates/proc-macro-api/src/legacy_protocol/msg.rs b/crates/proc-macro-api/src/legacy_protocol/msg.rs index 6ea8db9a90..4b831e4ace 100644 --- a/crates/proc-macro-api/src/legacy_protocol/msg.rs +++ b/crates/proc-macro-api/src/legacy_protocol/msg.rs @@ -159,7 +159,7 @@ type ProtocolWrite = for<'o, 'msg> fn(out: &'o mut W, msg: &'msg str) #[cfg(test)] mod tests { use intern::{sym, Symbol}; - use span::{ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, TextRange, TextSize}; + use span::{Edition, ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, TextRange, TextSize}; use tt::{ Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, Spacing, TopSubtree, TopSubtreeBuilder, @@ -180,12 +180,12 @@ mod tests { open: Span { range: TextRange::empty(TextSize::new(0)), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, close: Span { range: TextRange::empty(TextSize::new(19)), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, kind: DelimiterKind::Invisible, }); @@ -196,7 +196,7 @@ mod tests { span: Span { range: TextRange::at(TextSize::new(0), TextSize::of("struct")), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, is_raw: tt::IdentIsRaw::No, } @@ -208,7 +208,7 @@ mod tests { span: Span { range: TextRange::at(TextSize::new(5), TextSize::of("r#Foo")), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, is_raw: tt::IdentIsRaw::Yes, } @@ -219,7 +219,7 @@ mod tests { span: Span { range: TextRange::at(TextSize::new(10), TextSize::of("\"Foo\"")), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, kind: tt::LitKind::Str, suffix: None, @@ -229,7 +229,7 @@ mod tests { span: Span { range: TextRange::at(TextSize::new(13), TextSize::of('@')), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, spacing: Spacing::Joint, })); @@ -238,7 +238,7 @@ mod tests { Span { range: TextRange::at(TextSize::new(14), TextSize::of('{')), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, ); builder.push(Leaf::Literal(Literal { @@ -246,7 +246,7 @@ mod tests { span: Span { range: TextRange::at(TextSize::new(15), TextSize::of("0u32")), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, kind: tt::LitKind::Integer, suffix: Some(sym::u32.clone()), @@ -254,7 +254,7 @@ mod tests { builder.close(Span { range: TextRange::at(TextSize::new(19), TextSize::of('}')), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }); builder.build() diff --git a/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs index beaebf3330..c7614849e0 100644 --- a/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs +++ b/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs @@ -440,7 +440,7 @@ mod tests { file_id: EditionedFileId::current_edition(FileId::from_raw(0)), ast_id: span::ErasedFileAstId::from_raw(0), }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(span::Edition::CURRENT), }; let s = TokenStream { token_trees: vec![ @@ -482,7 +482,7 @@ mod tests { file_id: EditionedFileId::current_edition(FileId::from_raw(0)), ast_id: span::ErasedFileAstId::from_raw(0), }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(span::Edition::CURRENT), }; let subtree_paren_a = vec![ tt::TokenTree::Subtree(tt::Subtree { diff --git a/crates/proc-macro-srv/src/tests/mod.rs b/crates/proc-macro-srv/src/tests/mod.rs index dc6e71163b..15de88ea65 100644 --- a/crates/proc-macro-srv/src/tests/mod.rs +++ b/crates/proc-macro-srv/src/tests/mod.rs @@ -12,7 +12,7 @@ fn test_derive_empty() { "DeriveEmpty", r#"struct S;"#, expect!["SUBTREE $$ 1 1"], - expect!["SUBTREE $$ 42:2@0..100#0 42:2@0..100#0"], + expect!["SUBTREE $$ 42:2@0..100#2 42:2@0..100#2"], ); } @@ -29,12 +29,12 @@ fn test_derive_error() { LITERAL Str #[derive(DeriveError)] struct S ; 1 PUNCH ; [alone] 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT compile_error 42:2@0..100#0 - PUNCH ! [alone] 42:2@0..100#0 - SUBTREE () 42:2@0..100#0 42:2@0..100#0 - LITERAL Str #[derive(DeriveError)] struct S ; 42:2@0..100#0 - PUNCH ; [alone] 42:2@0..100#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT compile_error 42:2@0..100#2 + PUNCH ! [alone] 42:2@0..100#2 + SUBTREE () 42:2@0..100#2 42:2@0..100#2 + LITERAL Str #[derive(DeriveError)] struct S ; 42:2@0..100#2 + PUNCH ; [alone] 42:2@0..100#2"#]], ); } @@ -53,14 +53,14 @@ fn test_fn_like_macro_noop() { PUNCH , [alone] 1 SUBTREE [] 1 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT ident 42:2@0..5#0 - PUNCH , [alone] 42:2@5..6#0 - LITERAL Integer 0 42:2@7..8#0 - PUNCH , [alone] 42:2@8..9#0 - LITERAL Integer 1 42:2@10..11#0 - PUNCH , [alone] 42:2@11..12#0 - SUBTREE [] 42:2@13..14#0 42:2@14..15#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT ident 42:2@0..5#2 + PUNCH , [alone] 42:2@5..6#2 + LITERAL Integer 0 42:2@7..8#2 + PUNCH , [alone] 42:2@8..9#2 + LITERAL Integer 1 42:2@10..11#2 + PUNCH , [alone] 42:2@11..12#2 + SUBTREE [] 42:2@13..14#2 42:2@14..15#2"#]], ); } @@ -75,10 +75,10 @@ fn test_fn_like_macro_clone_ident_subtree() { PUNCH , [alone] 1 SUBTREE [] 1 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT ident 42:2@0..5#0 - PUNCH , [alone] 42:2@5..6#0 - SUBTREE [] 42:2@7..8#0 42:2@7..8#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT ident 42:2@0..5#2 + PUNCH , [alone] 42:2@5..6#2 + SUBTREE [] 42:2@7..8#2 42:2@7..8#2"#]], ); } @@ -91,8 +91,8 @@ fn test_fn_like_macro_clone_raw_ident() { SUBTREE $$ 1 1 IDENT r#async 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT r#async 42:2@0..7#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT r#async 42:2@0..7#2"#]], ); } @@ -105,8 +105,8 @@ fn test_fn_like_fn_like_span_join() { SUBTREE $$ 1 1 IDENT r#joined 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT r#joined 42:2@0..11#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT r#joined 42:2@0..11#2"#]], ); } @@ -121,10 +121,10 @@ fn test_fn_like_fn_like_span_ops() { IDENT resolved_at_def_site 1 IDENT start_span 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT set_def_site 41:1@0..150#0 - IDENT resolved_at_def_site 42:2@13..33#0 - IDENT start_span 42:2@34..34#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT set_def_site 41:1@0..150#2 + IDENT resolved_at_def_site 42:2@13..33#2 + IDENT start_span 42:2@34..34#2"#]], ); } @@ -143,14 +143,14 @@ fn test_fn_like_mk_literals() { LITERAL Integer 123i64 1 LITERAL Integer 123 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - LITERAL ByteStr byte_string 42:2@0..100#0 - LITERAL Char c 42:2@0..100#0 - LITERAL Str string 42:2@0..100#0 - LITERAL Float 3.14f64 42:2@0..100#0 - LITERAL Float 3.14 42:2@0..100#0 - LITERAL Integer 123i64 42:2@0..100#0 - LITERAL Integer 123 42:2@0..100#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + LITERAL ByteStr byte_string 42:2@0..100#2 + LITERAL Char c 42:2@0..100#2 + LITERAL Str string 42:2@0..100#2 + LITERAL Float 3.14f64 42:2@0..100#2 + LITERAL Float 3.14 42:2@0..100#2 + LITERAL Integer 123i64 42:2@0..100#2 + LITERAL Integer 123 42:2@0..100#2"#]], ); } @@ -164,9 +164,9 @@ fn test_fn_like_mk_idents() { IDENT standard 1 IDENT r#raw 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT standard 42:2@0..100#0 - IDENT r#raw 42:2@0..100#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT standard 42:2@0..100#2 + IDENT r#raw 42:2@0..100#2"#]], ); } @@ -198,27 +198,27 @@ fn test_fn_like_macro_clone_literals() { PUNCH , [alone] 1 LITERAL CStr null 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - LITERAL Integer 1u16 42:2@0..4#0 - PUNCH , [alone] 42:2@4..5#0 - LITERAL Integer 2_u32 42:2@6..11#0 - PUNCH , [alone] 42:2@11..12#0 - PUNCH - [alone] 42:2@13..14#0 - LITERAL Integer 4i64 42:2@14..18#0 - PUNCH , [alone] 42:2@18..19#0 - LITERAL Float 3.14f32 42:2@20..27#0 - PUNCH , [alone] 42:2@27..28#0 - LITERAL Str hello bridge 42:2@29..43#0 - PUNCH , [alone] 42:2@43..44#0 - LITERAL Str suffixedsuffix 42:2@45..61#0 - PUNCH , [alone] 42:2@61..62#0 - LITERAL StrRaw(2) raw 42:2@63..73#0 - PUNCH , [alone] 42:2@73..74#0 - LITERAL Char a 42:2@75..78#0 - PUNCH , [alone] 42:2@78..79#0 - LITERAL Byte b 42:2@80..84#0 - PUNCH , [alone] 42:2@84..85#0 - LITERAL CStr null 42:2@86..93#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + LITERAL Integer 1u16 42:2@0..4#2 + PUNCH , [alone] 42:2@4..5#2 + LITERAL Integer 2_u32 42:2@6..11#2 + PUNCH , [alone] 42:2@11..12#2 + PUNCH - [alone] 42:2@13..14#2 + LITERAL Integer 4i64 42:2@14..18#2 + PUNCH , [alone] 42:2@18..19#2 + LITERAL Float 3.14f32 42:2@20..27#2 + PUNCH , [alone] 42:2@27..28#2 + LITERAL Str hello bridge 42:2@29..43#2 + PUNCH , [alone] 42:2@43..44#2 + LITERAL Str suffixedsuffix 42:2@45..61#2 + PUNCH , [alone] 42:2@61..62#2 + LITERAL StrRaw(2) raw 42:2@63..73#2 + PUNCH , [alone] 42:2@73..74#2 + LITERAL Char a 42:2@75..78#2 + PUNCH , [alone] 42:2@78..79#2 + LITERAL Byte b 42:2@80..84#2 + PUNCH , [alone] 42:2@84..85#2 + LITERAL CStr null 42:2@86..93#2"#]], ); } @@ -239,12 +239,12 @@ fn test_attr_macro() { LITERAL Str #[attr_error(some arguments)] mod m {} 1 PUNCH ; [alone] 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT compile_error 42:2@0..100#0 - PUNCH ! [alone] 42:2@0..100#0 - SUBTREE () 42:2@0..100#0 42:2@0..100#0 - LITERAL Str #[attr_error(some arguments)] mod m {} 42:2@0..100#0 - PUNCH ; [alone] 42:2@0..100#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT compile_error 42:2@0..100#2 + PUNCH ! [alone] 42:2@0..100#2 + SUBTREE () 42:2@0..100#2 42:2@0..100#2 + LITERAL Str #[attr_error(some arguments)] mod m {} 42:2@0..100#2 + PUNCH ; [alone] 42:2@0..100#2"#]], ); } diff --git a/crates/proc-macro-srv/src/tests/utils.rs b/crates/proc-macro-srv/src/tests/utils.rs index 37d51050f3..42f0a7f59b 100644 --- a/crates/proc-macro-srv/src/tests/utils.rs +++ b/crates/proc-macro-srv/src/tests/utils.rs @@ -76,7 +76,7 @@ fn assert_expand_impl( file_id: EditionedFileId::current_edition(FileId::from_raw(41)), ast_id: ErasedFileAstId::from_raw(1), }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(span::Edition::CURRENT), }; let call_site = Span { range: TextRange::new(0.into(), 100.into()), @@ -84,7 +84,7 @@ fn assert_expand_impl( file_id: EditionedFileId::current_edition(FileId::from_raw(42)), ast_id: ErasedFileAstId::from_raw(2), }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(span::Edition::CURRENT), }; let mixed_site = call_site; diff --git a/crates/span/src/hygiene.rs b/crates/span/src/hygiene.rs index 87a948df55..6becc8e41e 100644 --- a/crates/span/src/hygiene.rs +++ b/crates/span/src/hygiene.rs @@ -26,7 +26,7 @@ use crate::InternId; #[cfg(feature = "ra-salsa")] use ra_salsa::{InternId, InternValue}; -use crate::MacroCallId; +use crate::{Edition, MacroCallId}; /// Interned [`SyntaxContextData`]. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -59,11 +59,20 @@ impl fmt::Display for SyntaxContextId { } impl SyntaxContextId { + #[inline] + pub fn remove_root_edition(&mut self) { + if self.is_root() { + *self = Self::root(Edition::Edition2015); + } + } + /// The root context, which is the parent of all other contexts. All [`FileId`]s have this context. - pub const ROOT: Self = SyntaxContextId(unsafe { InternId::new_unchecked(0) }); + pub const fn root(edition: Edition) -> Self { + SyntaxContextId(unsafe { InternId::new_unchecked(edition as u32) }) + } pub fn is_root(self) -> bool { - self == Self::ROOT + self.into_u32() <= Edition::LATEST as u32 } /// Deconstruct a `SyntaxContextId` into a raw `u32`. @@ -89,6 +98,7 @@ pub struct SyntaxContextData { // per crate. Though that is likely not a problem as `MacroCallId`s are already crate calling dependent. pub outer_expn: Option, pub outer_transparency: Transparency, + pub edition: Edition, pub parent: SyntaxContextId, /// This context, but with all transparent and semi-transparent expansions filtered away. pub opaque: SyntaxContextId, @@ -98,10 +108,10 @@ pub struct SyntaxContextData { #[cfg(feature = "ra-salsa")] impl InternValue for SyntaxContextData { - type Key = (SyntaxContextId, Option, Transparency); + type Key = (SyntaxContextId, Option, Transparency, Edition); fn into_key(&self) -> Self::Key { - (self.parent, self.outer_expn, self.outer_transparency) + (self.parent, self.outer_expn, self.outer_transparency, self.edition) } } @@ -118,13 +128,14 @@ impl std::fmt::Debug for SyntaxContextData { } impl SyntaxContextData { - pub fn root() -> Self { + pub fn root(edition: Edition) -> Self { SyntaxContextData { outer_expn: None, outer_transparency: Transparency::Opaque, - parent: SyntaxContextId::ROOT, - opaque: SyntaxContextId::ROOT, - opaque_and_semitransparent: SyntaxContextId::ROOT, + parent: SyntaxContextId::root(edition), + opaque: SyntaxContextId::root(edition), + opaque_and_semitransparent: SyntaxContextId::root(edition), + edition, } } } diff --git a/crates/span/src/map.rs b/crates/span/src/map.rs index 66bbce1859..dc35de67fd 100644 --- a/crates/span/src/map.rs +++ b/crates/span/src/map.rs @@ -208,7 +208,7 @@ impl RealSpanMap { Span { range: range - offset, anchor: SpanAnchor { file_id: self.file_id, ast_id }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(self.file_id.edition()), } } } diff --git a/crates/syntax-bridge/src/lib.rs b/crates/syntax-bridge/src/lib.rs index ed8b1908d6..19801c49e4 100644 --- a/crates/syntax-bridge/src/lib.rs +++ b/crates/syntax-bridge/src/lib.rs @@ -1,6 +1,6 @@ //! Conversions between [`SyntaxNode`] and [`tt::TokenTree`]. -use std::fmt; +use std::{fmt, hash::Hash}; use intern::Symbol; use rustc_hash::{FxHashMap, FxHashSet}; @@ -58,7 +58,7 @@ pub mod dummy_test_span_utils { ), ast_id: span::ROOT_ERASED_FILE_AST_ID, }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }; pub struct DummyTestSpanMap; @@ -74,7 +74,7 @@ pub mod dummy_test_span_utils { ), ast_id: span::ROOT_ERASED_FILE_AST_ID, }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), } } } @@ -141,15 +141,16 @@ where pub fn token_tree_to_syntax_node( tt: &tt::TopSubtree>, entry_point: parser::TopEntryPoint, - edition: parser::Edition, + span_to_edition: &mut dyn FnMut(Ctx) -> Edition, + top_edition: Edition, ) -> (Parse, SpanMap) where - SpanData: Copy + fmt::Debug, - Ctx: PartialEq, + Ctx: Copy + fmt::Debug + PartialEq + PartialEq + Eq + Hash, { let buffer = tt.view().strip_invisible(); - let parser_input = to_parser_input(edition, buffer); - let parser_output = entry_point.parse(&parser_input, edition); + let parser_input = to_parser_input(buffer, span_to_edition); + // It matters what edition we parse with even when we escape all identifiers correctly. + let parser_output = entry_point.parse(&parser_input, top_edition); let mut tree_sink = TtTreeSink::new(buffer.cursor()); for event in parser_output.iter() { match event { diff --git a/crates/syntax-bridge/src/to_parser_input.rs b/crates/syntax-bridge/src/to_parser_input.rs index 1bbb05f550..0dcb2be316 100644 --- a/crates/syntax-bridge/src/to_parser_input.rs +++ b/crates/syntax-bridge/src/to_parser_input.rs @@ -2,17 +2,20 @@ //! format that works for our parser. use std::fmt; +use std::hash::Hash; -use span::Edition; +use rustc_hash::FxHashMap; +use span::{Edition, SpanData}; use syntax::{SyntaxKind, SyntaxKind::*, T}; -pub fn to_parser_input( - edition: Edition, - buffer: tt::TokenTreesView<'_, S>, +pub fn to_parser_input( + buffer: tt::TokenTreesView<'_, SpanData>, + span_to_edition: &mut dyn FnMut(Ctx) -> Edition, ) -> parser::Input { let mut res = parser::Input::default(); let mut current = buffer.cursor(); + let mut syntax_context_to_edition_cache = FxHashMap::default(); while !current.eof() { let tt = current.token_tree(); @@ -57,20 +60,25 @@ pub fn to_parser_input( res.was_joint(); } } - tt::Leaf::Ident(ident) => match ident.sym.as_str() { - "_" => res.push(T![_]), - i if i.starts_with('\'') => res.push(LIFETIME_IDENT), - _ if ident.is_raw.yes() => res.push(IDENT), - text => match SyntaxKind::from_keyword(text, edition) { - Some(kind) => res.push(kind), - None => { - let contextual_keyword = - SyntaxKind::from_contextual_keyword(text, edition) - .unwrap_or(SyntaxKind::IDENT); - res.push_ident(contextual_keyword); - } - }, - }, + tt::Leaf::Ident(ident) => { + let edition = *syntax_context_to_edition_cache + .entry(ident.span.ctx) + .or_insert_with(|| span_to_edition(ident.span.ctx)); + match ident.sym.as_str() { + "_" => res.push(T![_]), + i if i.starts_with('\'') => res.push(LIFETIME_IDENT), + _ if ident.is_raw.yes() => res.push(IDENT), + text => match SyntaxKind::from_keyword(text, edition) { + Some(kind) => res.push(kind), + None => { + let contextual_keyword = + SyntaxKind::from_contextual_keyword(text, edition) + .unwrap_or(SyntaxKind::IDENT); + res.push_ident(contextual_keyword); + } + }, + } + } tt::Leaf::Punct(punct) => { let kind = SyntaxKind::from_char(punct.char) .unwrap_or_else(|| panic!("{punct:#?} is not a valid punct"));