mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-31 12:04:43 +00:00 
			
		
		
		
	Merge pull request #18861 from ChayimFriedman2/await-edition
fix: Make edition per-token, not per-file
This commit is contained in:
		
						commit
						3fe50ef83c
					
				
					 34 changed files with 480 additions and 316 deletions
				
			
		|  | @ -5,7 +5,8 @@ use std::fmt; | ||||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||||||
| #[repr(u8)] | #[repr(u8)] | ||||||
| pub enum Edition { | pub enum Edition { | ||||||
|     Edition2015, |     // The syntax context stuff needs the discriminants to start from 0 and be consecutive.
 | ||||||
|  |     Edition2015 = 0, | ||||||
|     Edition2018, |     Edition2018, | ||||||
|     Edition2021, |     Edition2021, | ||||||
|     Edition2024, |     Edition2024, | ||||||
|  |  | ||||||
|  | @ -15,7 +15,7 @@ use hir_expand::{name::Name, ExpandError, InFile}; | ||||||
| use la_arena::{Arena, ArenaMap, Idx, RawIdx}; | use la_arena::{Arena, ArenaMap, Idx, RawIdx}; | ||||||
| use rustc_hash::FxHashMap; | use rustc_hash::FxHashMap; | ||||||
| use smallvec::SmallVec; | use smallvec::SmallVec; | ||||||
| use span::{Edition, MacroFileId}; | use span::{Edition, MacroFileId, SyntaxContextData}; | ||||||
| use syntax::{ast, AstPtr, SyntaxNodePtr}; | use syntax::{ast, AstPtr, SyntaxNodePtr}; | ||||||
| use triomphe::Arc; | use triomphe::Arc; | ||||||
| use tt::TextRange; | use tt::TextRange; | ||||||
|  | @ -37,15 +37,22 @@ use crate::{ | ||||||
| 
 | 
 | ||||||
| /// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons.
 | /// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons.
 | ||||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||||||
| pub struct HygieneId(pub(crate) span::SyntaxContextId); | pub struct HygieneId(span::SyntaxContextId); | ||||||
| 
 | 
 | ||||||
| impl HygieneId { | 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) |         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 { |     pub(crate) fn is_root(self) -> bool { | ||||||
|         self.0.is_root() |         self.0.is_root() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -2460,7 +2460,7 @@ impl ExprCollector<'_> { | ||||||
|             None => HygieneId::ROOT, |             None => HygieneId::ROOT, | ||||||
|             Some(span_map) => { |             Some(span_map) => { | ||||||
|                 let ctx = span_map.span_at(span_start).ctx; |                 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) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ use hir_expand::{ | ||||||
|     ExpandResult, HirFileId, InFile, Lookup, MacroCallId, |     ExpandResult, HirFileId, InFile, Lookup, MacroCallId, | ||||||
| }; | }; | ||||||
| use limit::Limit; | use limit::Limit; | ||||||
| use span::SyntaxContextId; | use span::{Edition, SyntaxContextId}; | ||||||
| use syntax::{ast, Parse}; | use syntax::{ast, Parse}; | ||||||
| use triomphe::Arc; | use triomphe::Arc; | ||||||
| 
 | 
 | ||||||
|  | @ -60,7 +60,7 @@ impl Expander { | ||||||
| 
 | 
 | ||||||
|     pub fn syntax_context(&self) -> SyntaxContextId { |     pub fn syntax_context(&self) -> SyntaxContextId { | ||||||
|         // FIXME:
 |         // FIXME:
 | ||||||
|         SyntaxContextId::ROOT |         SyntaxContextId::root(Edition::CURRENT) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn enter_expand<T: ast::AstNode>( |     pub fn enter_expand<T: ast::AstNode>( | ||||||
|  |  | ||||||
|  | @ -270,7 +270,7 @@ m!(); | ||||||
|             // AstId: 2
 |             // AstId: 2
 | ||||||
|             pub macro m2 { ... } |             pub macro m2 { ... } | ||||||
| 
 | 
 | ||||||
|             // AstId: 3, SyntaxContext: 0, ExpandTo: Items
 |             // AstId: 3, SyntaxContext: 2, ExpandTo: Items
 | ||||||
|             m!(...); |             m!(...); | ||||||
|         "#]],
 |         "#]],
 | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|  | @ -35,9 +35,9 @@ macro_rules! f { | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct#0:1@58..64#1# MyTraitMap2#0:2@31..42#0# {#0:1@72..73#1# | struct#0:1@58..64#4# MyTraitMap2#0:2@31..42#2# {#0:1@72..73#4# | ||||||
|     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# |     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#1# | }#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# | 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#0#;#0:2@51..52#0# |     1#0:2@50..51#2#;#0:2@51..52#2# | ||||||
|     1.0#0:2@61..64#0#;#0:2@64..65#0# |     1.0#0:2@61..64#2#;#0:2@64..65#2# | ||||||
|     (#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# |     (#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#0# x#0:2@99..100#0# =#0:2@101..102#0# 1#0:2@103..104#0#;#0:2@104..105#0# |     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#0# | }#0:2@110..111#2# | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| "#]],
 | "#]],
 | ||||||
|  | @ -171,7 +171,7 @@ fn main(foo: ()) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     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] | #[macro_use] | ||||||
| mod foo; | 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 { | macro_rules! m { | ||||||
|     ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } ); |     ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } ); | ||||||
| } | } | ||||||
| impl#\1# Bar#\1# {#\1# | impl#\4# Bar#\4# {#\4# | ||||||
|     fn#\1# foo#\0#(#\1#)#\1# {#\1#}#\1# |     fn#\4# foo#\2#(#\4#)#\4# {#\4#}#\4# | ||||||
|     fn#\1# bar#\0#(#\1#)#\1# {#\1#}#\1# |     fn#\4# bar#\2#(#\4#)#\4# {#\4#}#\4# | ||||||
| }#\1# | }#\4# | ||||||
| "#]],
 | "#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -358,6 +358,7 @@ impl ProcMacroExpander for IdentityWhenValidProcMacroExpander { | ||||||
|         let (parse, _) = syntax_bridge::token_tree_to_syntax_node( |         let (parse, _) = syntax_bridge::token_tree_to_syntax_node( | ||||||
|             subtree, |             subtree, | ||||||
|             syntax_bridge::TopEntryPoint::MacroItems, |             syntax_bridge::TopEntryPoint::MacroItems, | ||||||
|  |             &mut |_| span::Edition::CURRENT, | ||||||
|             span::Edition::CURRENT, |             span::Edition::CURRENT, | ||||||
|         ); |         ); | ||||||
|         if parse.errors().is_empty() { |         if parse.errors().is_empty() { | ||||||
|  |  | ||||||
|  | @ -181,9 +181,9 @@ fn foo(&self) { | ||||||
|     self.0. 1; |     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# | 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#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# |     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#0#"#]],
 | }#0:1@76..77#2#"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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 { |     let proc_macros = if krate.is_proc_macro { | ||||||
|         db.proc_macros() |         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() |             .unwrap_or_default() | ||||||
|     } else { |     } else { | ||||||
|         Default::default() |         Default::default() | ||||||
|  |  | ||||||
|  | @ -324,7 +324,7 @@ impl Resolver { | ||||||
| 
 | 
 | ||||||
|         if n_segments <= 1 { |         if n_segments <= 1 { | ||||||
|             let mut hygiene_info = if !hygiene_id.is_root() { |             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| { |                 ctx.outer_expn.map(|expansion| { | ||||||
|                     let expansion = db.lookup_intern_macro_call(expansion); |                     let expansion = db.lookup_intern_macro_call(expansion); | ||||||
|                     (ctx.parent, expansion.def) |                     (ctx.parent, expansion.def) | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ use intern::sym; | ||||||
| use itertools::{izip, Itertools}; | use itertools::{izip, Itertools}; | ||||||
| use parser::SyntaxKind; | use parser::SyntaxKind; | ||||||
| use rustc_hash::FxHashSet; | use rustc_hash::FxHashSet; | ||||||
| use span::{MacroCallId, Span, SyntaxContextId}; | use span::{Edition, MacroCallId, Span, SyntaxContextId}; | ||||||
| use stdx::never; | use stdx::never; | ||||||
| use syntax_bridge::DocCommentDesugarMode; | use syntax_bridge::DocCommentDesugarMode; | ||||||
| use tracing::debug; | use tracing::debug; | ||||||
|  | @ -33,7 +33,7 @@ macro_rules! register_builtin { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         impl BuiltinDeriveExpander { |         impl BuiltinDeriveExpander { | ||||||
|             pub fn expander(&self) -> fn(Span, &tt::TopSubtree) -> ExpandResult<tt::TopSubtree>  { |             pub fn expander(&self) -> fn(&dyn ExpandDatabase, Span, &tt::TopSubtree) -> ExpandResult<tt::TopSubtree>  { | ||||||
|                 match *self { |                 match *self { | ||||||
|                     $( BuiltinDeriveExpander::$trait => $expand, )* |                     $( BuiltinDeriveExpander::$trait => $expand, )* | ||||||
|                 } |                 } | ||||||
|  | @ -58,8 +58,8 @@ impl BuiltinDeriveExpander { | ||||||
|         tt: &tt::TopSubtree, |         tt: &tt::TopSubtree, | ||||||
|         span: Span, |         span: Span, | ||||||
|     ) -> ExpandResult<tt::TopSubtree> { |     ) -> ExpandResult<tt::TopSubtree> { | ||||||
|         let span = span_with_def_site_ctxt(db, span, id); |         let span = span_with_def_site_ctxt(db, span, id, Edition::CURRENT); | ||||||
|         self.expander()(span, tt) |         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.
 | // 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<BasicAdtInfo, ExpandError> { | fn parse_adt( | ||||||
|     let (adt, tm) = to_adt_syntax(tt, call_site)?; |     db: &dyn ExpandDatabase, | ||||||
|  |     tt: &tt::TopSubtree, | ||||||
|  |     call_site: Span, | ||||||
|  | ) -> Result<BasicAdtInfo, ExpandError> { | ||||||
|  |     let (adt, tm) = to_adt_syntax(db, tt, call_site)?; | ||||||
|     parse_adt_from_syntax(&adt, &tm, call_site) |     parse_adt_from_syntax(&adt, &tm, call_site) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -382,12 +386,14 @@ fn parse_adt_from_syntax( | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn to_adt_syntax( | fn to_adt_syntax( | ||||||
|  |     db: &dyn ExpandDatabase, | ||||||
|     tt: &tt::TopSubtree, |     tt: &tt::TopSubtree, | ||||||
|     call_site: Span, |     call_site: Span, | ||||||
| ) -> Result<(ast::Adt, span::SpanMap<SyntaxContextId>), ExpandError> { | ) -> Result<(ast::Adt, span::SpanMap<SyntaxContextId>), ExpandError> { | ||||||
|     let (parsed, tm) = syntax_bridge::token_tree_to_syntax_node( |     let (parsed, tm) = crate::db::token_tree_to_syntax_node( | ||||||
|  |         db, | ||||||
|         tt, |         tt, | ||||||
|         syntax_bridge::TopEntryPoint::MacroItems, |         crate::ExpandTo::Items, | ||||||
|         parser::Edition::CURRENT_FIXME, |         parser::Edition::CURRENT_FIXME, | ||||||
|     ); |     ); | ||||||
|     let macro_items = ast::MacroItems::cast(parsed.syntax_node()) |     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
 | /// 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.
 | /// therefore does not get bound by the derived trait.
 | ||||||
| fn expand_simple_derive( | fn expand_simple_derive( | ||||||
|  |     db: &dyn ExpandDatabase, | ||||||
|     invoc_span: Span, |     invoc_span: Span, | ||||||
|     tt: &tt::TopSubtree, |     tt: &tt::TopSubtree, | ||||||
|     trait_path: tt::TopSubtree, |     trait_path: tt::TopSubtree, | ||||||
|     make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::TopSubtree, |     make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::TopSubtree, | ||||||
| ) -> ExpandResult<tt::TopSubtree> { | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|     let info = match parse_adt(tt, invoc_span) { |     let info = match parse_adt(db, tt, invoc_span) { | ||||||
|         Ok(info) => info, |         Ok(info) => info, | ||||||
|         Err(e) => { |         Err(e) => { | ||||||
|             return ExpandResult::new( |             return ExpandResult::new( | ||||||
|  | @ -520,14 +527,22 @@ fn expand_simple_derive_with_parsed( | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn copy_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { | fn copy_expand( | ||||||
|  |     db: &dyn ExpandDatabase, | ||||||
|  |     span: Span, | ||||||
|  |     tt: &tt::TopSubtree, | ||||||
|  | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|     let krate = dollar_crate(span); |     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<tt::TopSubtree> { | fn clone_expand( | ||||||
|  |     db: &dyn ExpandDatabase, | ||||||
|  |     span: Span, | ||||||
|  |     tt: &tt::TopSubtree, | ||||||
|  | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|     let krate = dollar_crate(span); |     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) { |         if matches!(adt.shape, AdtShape::Union) { | ||||||
|             let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span }; |             let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span }; | ||||||
|             return quote! {span => |             return quote! {span => | ||||||
|  | @ -576,9 +591,13 @@ fn and_and(span: Span) -> tt::TopSubtree { | ||||||
|     quote! {span => #and& } |     quote! {span => #and& } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn default_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { | fn default_expand( | ||||||
|  |     db: &dyn ExpandDatabase, | ||||||
|  |     span: Span, | ||||||
|  |     tt: &tt::TopSubtree, | ||||||
|  | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|     let krate = &dollar_crate(span); |     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 { |         let body = match &adt.shape { | ||||||
|             AdtShape::Struct(fields) => { |             AdtShape::Struct(fields) => { | ||||||
|                 let name = &adt.name; |                 let name = &adt.name; | ||||||
|  | @ -615,9 +634,13 @@ fn default_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtre | ||||||
|     }) |     }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn debug_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { | fn debug_expand( | ||||||
|  |     db: &dyn ExpandDatabase, | ||||||
|  |     span: Span, | ||||||
|  |     tt: &tt::TopSubtree, | ||||||
|  | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|     let krate = &dollar_crate(span); |     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 { |         let for_variant = |name: String, v: &VariantShape| match v { | ||||||
|             VariantShape::Struct(fields) => { |             VariantShape::Struct(fields) => { | ||||||
|                 let for_fields = fields.iter().map(|it| { |                 let for_fields = fields.iter().map(|it| { | ||||||
|  | @ -687,9 +710,13 @@ fn debug_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> | ||||||
|     }) |     }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn hash_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { | fn hash_expand( | ||||||
|  |     db: &dyn ExpandDatabase, | ||||||
|  |     span: Span, | ||||||
|  |     tt: &tt::TopSubtree, | ||||||
|  | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|     let krate = &dollar_crate(span); |     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) { |         if matches!(adt.shape, AdtShape::Union) { | ||||||
|             // FIXME: Return expand error here
 |             // FIXME: Return expand error here
 | ||||||
|             return quote! {span =>}; |             return quote! {span =>}; | ||||||
|  | @ -734,14 +761,22 @@ fn hash_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> | ||||||
|     }) |     }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn eq_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { | fn eq_expand( | ||||||
|  |     db: &dyn ExpandDatabase, | ||||||
|  |     span: Span, | ||||||
|  |     tt: &tt::TopSubtree, | ||||||
|  | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|     let krate = dollar_crate(span); |     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<tt::TopSubtree> { | fn partial_eq_expand( | ||||||
|  |     db: &dyn ExpandDatabase, | ||||||
|  |     span: Span, | ||||||
|  |     tt: &tt::TopSubtree, | ||||||
|  | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|     let krate = dollar_crate(span); |     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) { |         if matches!(adt.shape, AdtShape::Union) { | ||||||
|             // FIXME: Return expand error here
 |             // FIXME: Return expand error here
 | ||||||
|             return quote! {span =>}; |             return quote! {span =>}; | ||||||
|  | @ -811,9 +846,13 @@ fn self_and_other_patterns( | ||||||
|     (self_patterns, other_patterns) |     (self_patterns, other_patterns) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { | fn ord_expand( | ||||||
|  |     db: &dyn ExpandDatabase, | ||||||
|  |     span: Span, | ||||||
|  |     tt: &tt::TopSubtree, | ||||||
|  | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|     let krate = &dollar_crate(span); |     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( |         fn compare( | ||||||
|             krate: &tt::Ident, |             krate: &tt::Ident, | ||||||
|             left: tt::TopSubtree, |             left: tt::TopSubtree, | ||||||
|  | @ -869,9 +908,13 @@ fn ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { | ||||||
|     }) |     }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn partial_ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { | fn partial_ord_expand( | ||||||
|  |     db: &dyn ExpandDatabase, | ||||||
|  |     span: Span, | ||||||
|  |     tt: &tt::TopSubtree, | ||||||
|  | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|     let krate = &dollar_crate(span); |     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( |         fn compare( | ||||||
|             krate: &tt::Ident, |             krate: &tt::Ident, | ||||||
|             left: tt::TopSubtree, |             left: tt::TopSubtree, | ||||||
|  | @ -932,8 +975,12 @@ fn partial_ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSu | ||||||
|     }) |     }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn coerce_pointee_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { | fn coerce_pointee_expand( | ||||||
|     let (adt, _span_map) = match to_adt_syntax(tt, span) { |     db: &dyn ExpandDatabase, | ||||||
|  |     span: Span, | ||||||
|  |     tt: &tt::TopSubtree, | ||||||
|  | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|  |     let (adt, _span_map) = match to_adt_syntax(db, tt, span) { | ||||||
|         Ok(it) => it, |         Ok(it) => it, | ||||||
|         Err(err) => { |         Err(err) => { | ||||||
|             return ExpandResult::new(tt::TopSubtree::empty(tt::DelimSpan::from_single(span)), err); |             return ExpandResult::new(tt::TopSubtree::empty(tt::DelimSpan::from_single(span)), err); | ||||||
|  |  | ||||||
|  | @ -69,7 +69,7 @@ impl BuiltinFnLikeExpander { | ||||||
|         tt: &tt::TopSubtree, |         tt: &tt::TopSubtree, | ||||||
|         span: Span, |         span: Span, | ||||||
|     ) -> ExpandResult<tt::TopSubtree> { |     ) -> ExpandResult<tt::TopSubtree> { | ||||||
|         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) |         self.expander()(db, id, tt, span) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -86,7 +86,7 @@ impl EagerExpander { | ||||||
|         tt: &tt::TopSubtree, |         tt: &tt::TopSubtree, | ||||||
|         span: Span, |         span: Span, | ||||||
|     ) -> ExpandResult<tt::TopSubtree> { |     ) -> ExpandResult<tt::TopSubtree> { | ||||||
|         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) |         self.expander()(db, id, tt, span) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -221,7 +221,7 @@ fn assert_expand( | ||||||
|     tt: &tt::TopSubtree, |     tt: &tt::TopSubtree, | ||||||
|     span: Span, |     span: Span, | ||||||
| ) -> ExpandResult<tt::TopSubtree> { | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|     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(); |     let mut iter = tt.iter(); | ||||||
| 
 | 
 | ||||||
|  | @ -342,7 +342,7 @@ fn panic_expand( | ||||||
|     span: Span, |     span: Span, | ||||||
| ) -> ExpandResult<tt::TopSubtree> { | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|     let dollar_crate = dollar_crate(span); |     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) { |     let mac = if use_panic_2021(db, call_site_span) { | ||||||
|         sym::panic_2021.clone() |         sym::panic_2021.clone() | ||||||
|  | @ -373,7 +373,7 @@ fn unreachable_expand( | ||||||
|     span: Span, |     span: Span, | ||||||
| ) -> ExpandResult<tt::TopSubtree> { | ) -> ExpandResult<tt::TopSubtree> { | ||||||
|     let dollar_crate = dollar_crate(span); |     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) { |     let mac = if use_panic_2021(db, call_site_span) { | ||||||
|         sym::unreachable_2021.clone() |         sym::unreachable_2021.clone() | ||||||
|  |  | ||||||
|  | @ -225,7 +225,7 @@ mod tests { | ||||||
|     use ::tt::IdentIsRaw; |     use ::tt::IdentIsRaw; | ||||||
|     use expect_test::expect; |     use expect_test::expect; | ||||||
|     use intern::Symbol; |     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 syntax::{TextRange, TextSize}; | ||||||
| 
 | 
 | ||||||
|     use super::quote; |     use super::quote; | ||||||
|  | @ -239,7 +239,7 @@ mod tests { | ||||||
|             ), |             ), | ||||||
|             ast_id: ROOT_ERASED_FILE_AST_ID, |             ast_id: ROOT_ERASED_FILE_AST_ID, | ||||||
|         }, |         }, | ||||||
|         ctx: SyntaxContextId::ROOT, |         ctx: SyntaxContextId::root(Edition::CURRENT), | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
|  | @ -276,8 +276,8 @@ mod tests { | ||||||
|         assert_eq!(quoted.to_string(), "hello"); |         assert_eq!(quoted.to_string(), "hello"); | ||||||
|         let t = format!("{quoted:#?}"); |         let t = format!("{quoted:#?}"); | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 937550:0@0..0#0 937550:0@0..0#0 |             SUBTREE $$ 937550:0@0..0#2 937550:0@0..0#2 | ||||||
|               IDENT   hello 937550:0@0..0#0"#]]
 |               IDENT   hello 937550:0@0..0#2"#]]
 | ||||||
|         .assert_eq(&t); |         .assert_eq(&t); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ use either::Either; | ||||||
| use limit::Limit; | use limit::Limit; | ||||||
| use mbe::MatchedArmIndex; | use mbe::MatchedArmIndex; | ||||||
| use rustc_hash::FxHashSet; | 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::{ast, AstNode, Parse, SyntaxElement, SyntaxError, SyntaxNode, SyntaxToken, T}; | ||||||
| use syntax_bridge::{syntax_node_to_token_tree, DocCommentDesugarMode}; | use syntax_bridge::{syntax_node_to_token_tree, DocCommentDesugarMode}; | ||||||
| use triomphe::Arc; | use triomphe::Arc; | ||||||
|  | @ -136,12 +136,12 @@ pub trait ExpandDatabase: SourceDatabase { | ||||||
|         macro_call: MacroCallId, |         macro_call: MacroCallId, | ||||||
|     ) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>>; |     ) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>>; | ||||||
|     #[ra_salsa::transparent] |     #[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() { |     match file.repr() { | ||||||
|         HirFileIdRepr::FileId(_) => SyntaxContextId::ROOT, |         HirFileIdRepr::FileId(_) => SyntaxContextId::root(edition), | ||||||
|         HirFileIdRepr::MacroFile(m) => { |         HirFileIdRepr::MacroFile(m) => { | ||||||
|             db.macro_arg_considering_derives(m.macro_call_id, &m.macro_call_id.lookup(db).kind) |             db.macro_arg_considering_derives(m.macro_call_id, &m.macro_call_id.lookup(db).kind) | ||||||
|                 .2 |                 .2 | ||||||
|  | @ -273,9 +273,9 @@ pub fn expand_speculative( | ||||||
|                 loc.krate, |                 loc.krate, | ||||||
|                 &tt, |                 &tt, | ||||||
|                 attr_arg.as_ref(), |                 attr_arg.as_ref(), | ||||||
|                 span_with_def_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), |                 span_with_call_site_ctxt(db, span, actual_macro_call, loc.def.edition), | ||||||
|                 span_with_mixed_site_ctxt(db, span, actual_macro_call), |                 span_with_mixed_site_ctxt(db, span, actual_macro_call, loc.def.edition), | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
|         MacroDefKind::BuiltInAttr(_, it) if it.is_derive() => { |         MacroDefKind::BuiltInAttr(_, it) if it.is_derive() => { | ||||||
|  | @ -300,7 +300,7 @@ pub fn expand_speculative( | ||||||
| 
 | 
 | ||||||
|     fixup::reverse_fixups(&mut speculative_expansion.value, &undo_info); |     fixup::reverse_fixups(&mut speculative_expansion.value, &undo_info); | ||||||
|     let (node, rev_tmap) = |     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 syntax_node = node.syntax_node(); | ||||||
|     let token = rev_tmap |     let token = rev_tmap | ||||||
|  | @ -346,6 +346,7 @@ fn parse_macro_expansion( | ||||||
|         macro_expand(db, macro_file.macro_call_id, loc); |         macro_expand(db, macro_file.macro_call_id, loc); | ||||||
| 
 | 
 | ||||||
|     let (parse, mut rev_token_map) = token_tree_to_syntax_node( |     let (parse, mut rev_token_map) = token_tree_to_syntax_node( | ||||||
|  |         db, | ||||||
|         match &tt { |         match &tt { | ||||||
|             CowArc::Arc(it) => it, |             CowArc::Arc(it) => it, | ||||||
|             CowArc::Owned(it) => it, |             CowArc::Owned(it) => it, | ||||||
|  | @ -699,9 +700,9 @@ fn expand_proc_macro( | ||||||
|             loc.krate, |             loc.krate, | ||||||
|             ¯o_arg, |             ¯o_arg, | ||||||
|             attr_arg, |             attr_arg, | ||||||
|             span_with_def_site_ctxt(db, span, id), |             span_with_def_site_ctxt(db, span, id, loc.def.edition), | ||||||
|             span_with_call_site_ctxt(db, span, id), |             span_with_call_site_ctxt(db, span, id, loc.def.edition), | ||||||
|             span_with_mixed_site_ctxt(db, span, id), |             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 } |     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, |     tt: &tt::TopSubtree, | ||||||
|     expand_to: ExpandTo, |     expand_to: ExpandTo, | ||||||
|     edition: parser::Edition, |     edition: parser::Edition, | ||||||
|  | @ -727,7 +729,12 @@ fn token_tree_to_syntax_node( | ||||||
|         ExpandTo::Type => syntax_bridge::TopEntryPoint::Type, |         ExpandTo::Type => syntax_bridge::TopEntryPoint::Type, | ||||||
|         ExpandTo::Expr => syntax_bridge::TopEntryPoint::Expr, |         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<()>> { | 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) { | 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)); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| 
 | 
 | ||||||
| use base_db::CrateId; | use base_db::CrateId; | ||||||
| use intern::sym; | use intern::sym; | ||||||
| use span::{Edition, MacroCallId, Span, SyntaxContextId}; | use span::{Edition, HirFileIdRepr, MacroCallId, Span, SyntaxContextId}; | ||||||
| use stdx::TupleExt; | use stdx::TupleExt; | ||||||
| use syntax::{ast, AstNode}; | use syntax::{ast, AstNode}; | ||||||
| use syntax_bridge::DocCommentDesugarMode; | use syntax_bridge::DocCommentDesugarMode; | ||||||
|  | @ -20,6 +20,7 @@ use crate::{ | ||||||
| pub struct DeclarativeMacroExpander { | pub struct DeclarativeMacroExpander { | ||||||
|     pub mac: mbe::DeclarativeMacro, |     pub mac: mbe::DeclarativeMacro, | ||||||
|     pub transparency: Transparency, |     pub transparency: Transparency, | ||||||
|  |     edition: Edition, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl DeclarativeMacroExpander { | impl DeclarativeMacroExpander { | ||||||
|  | @ -40,7 +41,7 @@ impl DeclarativeMacroExpander { | ||||||
|                 .mac |                 .mac | ||||||
|                 .expand( |                 .expand( | ||||||
|                     &tt, |                     &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, |                     span, | ||||||
|                     loc.def.edition, |                     loc.def.edition, | ||||||
|                 ) |                 ) | ||||||
|  | @ -159,6 +160,10 @@ impl DeclarativeMacroExpander { | ||||||
|                 transparency(¯o_def).unwrap_or(Transparency::Opaque), |                 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 }) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -380,14 +380,14 @@ impl InFile<TextRange> { | ||||||
|     ) -> (FileRange, SyntaxContextId) { |     ) -> (FileRange, SyntaxContextId) { | ||||||
|         match self.file_id.repr() { |         match self.file_id.repr() { | ||||||
|             HirFileIdRepr::FileId(file_id) => { |             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) => { |             HirFileIdRepr::MacroFile(mac_file) => { | ||||||
|                 match map_node_range_up(db, &db.expansion_span_map(mac_file), self.value) { |                 match map_node_range_up(db, &db.expansion_span_map(mac_file), self.value) { | ||||||
|                     Some(it) => it, |                     Some(it) => it, | ||||||
|                     None => { |                     None => { | ||||||
|                         let loc = db.lookup_intern_macro_call(mac_file.macro_call_id); |                         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<TextRange> { | ||||||
|         db: &dyn db::ExpandDatabase, |         db: &dyn db::ExpandDatabase, | ||||||
|     ) -> Option<(FileRange, SyntaxContextId)> { |     ) -> Option<(FileRange, SyntaxContextId)> { | ||||||
|         match self.file_id.repr() { |         match self.file_id.repr() { | ||||||
|             HirFileIdRepr::FileId(file_id) => { |             HirFileIdRepr::FileId(file_id) => Some(( | ||||||
|                 Some((FileRange { file_id, range: self.value }, SyntaxContextId::ROOT)) |                 FileRange { file_id, range: self.value }, | ||||||
|             } |                 SyntaxContextId::root(file_id.edition()), | ||||||
|  |             )), | ||||||
|             HirFileIdRepr::MacroFile(mac_file) => { |             HirFileIdRepr::MacroFile(mac_file) => { | ||||||
|                 map_node_range_up(db, &db.expansion_span_map(mac_file), self.value) |                 map_node_range_up(db, &db.expansion_span_map(mac_file), self.value) | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -380,7 +380,7 @@ pub(crate) fn reverse_fixups(tt: &mut TopSubtree, undo_info: &SyntaxFixupUndoInf | ||||||
|         let span = |file_id| Span { |         let span = |file_id| Span { | ||||||
|             range: TextRange::empty(TextSize::new(0)), |             range: TextRange::empty(TextSize::new(0)), | ||||||
|             anchor: SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID }, |             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.open = span(delimiter.open.anchor.file_id); | ||||||
|         delimiter.close = span(delimiter.close.anchor.file_id); |         delimiter.close = span(delimiter.close.anchor.file_id); | ||||||
|  | @ -562,6 +562,7 @@ mod tests { | ||||||
|         let (parse, _) = syntax_bridge::token_tree_to_syntax_node( |         let (parse, _) = syntax_bridge::token_tree_to_syntax_node( | ||||||
|             &tt, |             &tt, | ||||||
|             syntax_bridge::TopEntryPoint::MacroItems, |             syntax_bridge::TopEntryPoint::MacroItems, | ||||||
|  |             &mut |_| parser::Edition::CURRENT, | ||||||
|             parser::Edition::CURRENT, |             parser::Edition::CURRENT, | ||||||
|         ); |         ); | ||||||
|         assert!( |         assert!( | ||||||
|  |  | ||||||
|  | @ -24,26 +24,37 @@ | ||||||
| 
 | 
 | ||||||
| use std::iter; | use std::iter; | ||||||
| 
 | 
 | ||||||
| use span::{MacroCallId, Span, SyntaxContextData, SyntaxContextId}; | use span::{Edition, MacroCallId, Span, SyntaxContextData, SyntaxContextId}; | ||||||
| 
 | 
 | ||||||
| use crate::db::{ExpandDatabase, InternSyntaxContextQuery}; | use crate::db::{ExpandDatabase, InternSyntaxContextQuery}; | ||||||
| 
 | 
 | ||||||
| pub use span::Transparency; | pub use span::Transparency; | ||||||
| 
 | 
 | ||||||
| pub fn span_with_def_site_ctxt(db: &dyn ExpandDatabase, span: Span, expn_id: MacroCallId) -> Span { | pub fn span_with_def_site_ctxt( | ||||||
|     span_with_ctxt_from_mark(db, span, expn_id, Transparency::Opaque) |     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 { | pub fn span_with_call_site_ctxt( | ||||||
|     span_with_ctxt_from_mark(db, span, expn_id, Transparency::Transparent) |     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( | pub fn span_with_mixed_site_ctxt( | ||||||
|     db: &dyn ExpandDatabase, |     db: &dyn ExpandDatabase, | ||||||
|     span: Span, |     span: Span, | ||||||
|     expn_id: MacroCallId, |     expn_id: MacroCallId, | ||||||
|  |     edition: Edition, | ||||||
| ) -> Span { | ) -> 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( | fn span_with_ctxt_from_mark( | ||||||
|  | @ -51,8 +62,12 @@ fn span_with_ctxt_from_mark( | ||||||
|     span: Span, |     span: Span, | ||||||
|     expn_id: MacroCallId, |     expn_id: MacroCallId, | ||||||
|     transparency: Transparency, |     transparency: Transparency, | ||||||
|  |     edition: Edition, | ||||||
| ) -> Span { | ) -> 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( | pub(super) fn apply_mark( | ||||||
|  | @ -60,9 +75,10 @@ pub(super) fn apply_mark( | ||||||
|     ctxt: SyntaxContextId, |     ctxt: SyntaxContextId, | ||||||
|     call_id: MacroCallId, |     call_id: MacroCallId, | ||||||
|     transparency: Transparency, |     transparency: Transparency, | ||||||
|  |     edition: Edition, | ||||||
| ) -> SyntaxContextId { | ) -> SyntaxContextId { | ||||||
|     if transparency == Transparency::Opaque { |     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; |     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() { |     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
 |     // 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`.
 |     // See the example at `test/ui/hygiene/legacy_interaction.rs`.
 | ||||||
|     for (call_id, transparency) in ctxt.marks(db) { |     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( | fn apply_mark_internal( | ||||||
|  | @ -96,6 +112,7 @@ fn apply_mark_internal( | ||||||
|     ctxt: SyntaxContextId, |     ctxt: SyntaxContextId, | ||||||
|     call_id: MacroCallId, |     call_id: MacroCallId, | ||||||
|     transparency: Transparency, |     transparency: Transparency, | ||||||
|  |     edition: Edition, | ||||||
| ) -> SyntaxContextId { | ) -> SyntaxContextId { | ||||||
|     use base_db::ra_salsa; |     use base_db::ra_salsa; | ||||||
| 
 | 
 | ||||||
|  | @ -108,13 +125,14 @@ fn apply_mark_internal( | ||||||
|     if transparency >= Transparency::Opaque { |     if transparency >= Transparency::Opaque { | ||||||
|         let parent = opaque; |         let parent = opaque; | ||||||
|         opaque = ra_salsa::plumbing::get_query_table::<InternSyntaxContextQuery>(db).get_or_insert( |         opaque = ra_salsa::plumbing::get_query_table::<InternSyntaxContextQuery>(db).get_or_insert( | ||||||
|             (parent, call_id, transparency), |             (parent, call_id, transparency, edition), | ||||||
|             |new_opaque| SyntaxContextData { |             |new_opaque| SyntaxContextData { | ||||||
|                 outer_expn: call_id, |                 outer_expn: call_id, | ||||||
|                 outer_transparency: transparency, |                 outer_transparency: transparency, | ||||||
|                 parent, |                 parent, | ||||||
|                 opaque: new_opaque, |                 opaque: new_opaque, | ||||||
|                 opaque_and_semitransparent: new_opaque, |                 opaque_and_semitransparent: new_opaque, | ||||||
|  |                 edition, | ||||||
|             }, |             }, | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  | @ -123,13 +141,14 @@ fn apply_mark_internal( | ||||||
|         let parent = opaque_and_semitransparent; |         let parent = opaque_and_semitransparent; | ||||||
|         opaque_and_semitransparent = |         opaque_and_semitransparent = | ||||||
|             ra_salsa::plumbing::get_query_table::<InternSyntaxContextQuery>(db).get_or_insert( |             ra_salsa::plumbing::get_query_table::<InternSyntaxContextQuery>(db).get_or_insert( | ||||||
|                 (parent, call_id, transparency), |                 (parent, call_id, transparency, edition), | ||||||
|                 |new_opaque_and_semitransparent| SyntaxContextData { |                 |new_opaque_and_semitransparent| SyntaxContextData { | ||||||
|                     outer_expn: call_id, |                     outer_expn: call_id, | ||||||
|                     outer_transparency: transparency, |                     outer_transparency: transparency, | ||||||
|                     parent, |                     parent, | ||||||
|                     opaque, |                     opaque, | ||||||
|                     opaque_and_semitransparent: new_opaque_and_semitransparent, |                     opaque_and_semitransparent: new_opaque_and_semitransparent, | ||||||
|  |                     edition, | ||||||
|                 }, |                 }, | ||||||
|             ); |             ); | ||||||
|     } |     } | ||||||
|  | @ -141,6 +160,7 @@ fn apply_mark_internal( | ||||||
|         parent, |         parent, | ||||||
|         opaque, |         opaque, | ||||||
|         opaque_and_semitransparent, |         opaque_and_semitransparent, | ||||||
|  |         edition, | ||||||
|     }) |     }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -273,10 +273,9 @@ fn convert_path( | ||||||
|                 res |                 res | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         ast::PathSegmentKind::SelfTypeKw => ModPath::from_segments( |         ast::PathSegmentKind::SelfTypeKw => { | ||||||
|             PathKind::Plain, |             ModPath::from_segments(PathKind::Plain, Some(Name::new_symbol_root(sym::Self_.clone()))) | ||||||
|             Some(Name::new_symbol(sym::Self_.clone(), SyntaxContextId::ROOT)), |         } | ||||||
|         ), |  | ||||||
|         ast::PathSegmentKind::CrateKw => ModPath::from_segments(PathKind::Crate, iter::empty()), |         ast::PathSegmentKind::CrateKw => ModPath::from_segments(PathKind::Crate, iter::empty()), | ||||||
|         ast::PathSegmentKind::SelfKw => handle_super_kw(0)?, |         ast::PathSegmentKind::SelfKw => handle_super_kw(0)?, | ||||||
|         ast::PathSegmentKind::SuperKw => handle_super_kw(1)?, |         ast::PathSegmentKind::SuperKw => handle_super_kw(1)?, | ||||||
|  |  | ||||||
|  | @ -80,11 +80,20 @@ impl Name { | ||||||
|         Name { symbol: Symbol::intern(text), ctx: () } |         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; |         _ = ctx; | ||||||
|         Self::new_text(text) |         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 { |     pub fn new_tuple_field(idx: usize) -> Name { | ||||||
|         Name { symbol: Symbol::intern(&idx.to_string()), ctx: () } |         Name { symbol: Symbol::intern(&idx.to_string()), ctx: () } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -12,7 +12,6 @@ use hir_def::{ | ||||||
| }; | }; | ||||||
| use hir_expand::{mod_path::PathKind, name::Name}; | use hir_expand::{mod_path::PathKind, name::Name}; | ||||||
| use hir_ty::{db::HirDatabase, method_resolution}; | use hir_ty::{db::HirDatabase, method_resolution}; | ||||||
| use span::SyntaxContextId; |  | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl, |     Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl, | ||||||
|  | @ -328,9 +327,7 @@ fn doc_modpath_from_str(link: &str) -> Option<ModPath> { | ||||||
|         }; |         }; | ||||||
|         let parts = first_segment.into_iter().chain(parts).map(|segment| match segment.parse() { |         let parts = first_segment.into_iter().chain(parts).map(|segment| match segment.parse() { | ||||||
|             Ok(idx) => Name::new_tuple_field(idx), |             Ok(idx) => Name::new_tuple_field(idx), | ||||||
|             Err(_) => { |             Err(_) => Name::new_root(segment.split_once('<').map_or(segment, |it| it.0)), | ||||||
|                 Name::new(segment.split_once('<').map_or(segment, |it| it.0), SyntaxContextId::ROOT) |  | ||||||
|             } |  | ||||||
|         }); |         }); | ||||||
|         Some(ModPath::from_segments(kind, parts)) |         Some(ModPath::from_segments(kind, parts)) | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  | @ -83,7 +83,7 @@ use itertools::Itertools; | ||||||
| use nameres::diagnostics::DefDiagnosticKind; | use nameres::diagnostics::DefDiagnosticKind; | ||||||
| use rustc_hash::FxHashSet; | use rustc_hash::FxHashSet; | ||||||
| use smallvec::SmallVec; | use smallvec::SmallVec; | ||||||
| use span::{Edition, EditionedFileId, FileId, MacroCallId, SyntaxContextId}; | use span::{Edition, EditionedFileId, FileId, MacroCallId}; | ||||||
| use stdx::{format_to, impl_from, never}; | use stdx::{format_to, impl_from, never}; | ||||||
| use syntax::{ | use syntax::{ | ||||||
|     ast::{self, HasAttrs as _, HasGenericParams, HasName}, |     ast::{self, HasAttrs as _, HasGenericParams, HasName}, | ||||||
|  | @ -4833,7 +4833,7 @@ impl Type { | ||||||
|         let iterator_trait = db.lang_item(self.env.krate, LangItem::Iterator)?.as_trait()?; |         let iterator_trait = db.lang_item(self.env.krate, LangItem::Iterator)?.as_trait()?; | ||||||
|         let iterator_item = db |         let iterator_item = db | ||||||
|             .trait_data(iterator_trait) |             .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()) |         self.normalize_trait_assoc_type(db, &[], iterator_item.into()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -986,7 +986,10 @@ impl<'db> SemanticsImpl<'db> { | ||||||
|                 process_expansion_for_token(&mut stack, include)?; |                 process_expansion_for_token(&mut stack, include)?; | ||||||
|             } |             } | ||||||
|             None => { |             None => { | ||||||
|                 stack.push((file_id.into(), smallvec![(token, SyntaxContextId::ROOT)])); |                 stack.push(( | ||||||
|  |                     file_id.into(), | ||||||
|  |                     smallvec![(token, SyntaxContextId::root(file_id.edition()))], | ||||||
|  |                 )); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -1597,7 +1600,7 @@ impl<'db> SemanticsImpl<'db> { | ||||||
|             self.db.upcast(), |             self.db.upcast(), | ||||||
|             &ModPath::from_segments( |             &ModPath::from_segments( | ||||||
|                 hir_def::path::PathKind::Plain, |                 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())) |         Some(items.iter_items().map(|(item, _)| item.into())) | ||||||
|  |  | ||||||
|  | @ -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!(); | ||||||
|  | } | ||||||
|  |         "#,
 | ||||||
|  |         ); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -369,7 +369,8 @@ pub fn expect_fragment<'t>( | ||||||
| ) -> ExpandResult<tt::TokenTreesView<'t, Span>> { | ) -> ExpandResult<tt::TokenTreesView<'t, Span>> { | ||||||
|     use ::parser; |     use ::parser; | ||||||
|     let buffer = tt_iter.remaining(); |     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 tree_traversal = entry_point.parse(&parser_input, edition); | ||||||
|     let mut cursor = buffer.cursor(); |     let mut cursor = buffer.cursor(); | ||||||
|     let mut error = false; |     let mut error = false; | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ fn check_( | ||||||
|             file_id: EditionedFileId::new(FileId::from_raw(0), def_edition), |             file_id: EditionedFileId::new(FileId::from_raw(0), def_edition), | ||||||
|             ast_id: ErasedFileAstId::from_raw(0), |             ast_id: ErasedFileAstId::from_raw(0), | ||||||
|         }, |         }, | ||||||
|         SyntaxContextId::ROOT, |         SyntaxContextId::root(Edition::CURRENT), | ||||||
|         decl, |         decl, | ||||||
|     ) |     ) | ||||||
|     .unwrap(); |     .unwrap(); | ||||||
|  | @ -39,16 +39,20 @@ fn check_( | ||||||
|         file_id: EditionedFileId::new(FileId::from_raw(1), call_edition), |         file_id: EditionedFileId::new(FileId::from_raw(1), call_edition), | ||||||
|         ast_id: ErasedFileAstId::from_raw(0), |         ast_id: ErasedFileAstId::from_raw(0), | ||||||
|     }; |     }; | ||||||
|     let arg_tt = |     let arg_tt = syntax_bridge::parse_to_token_tree( | ||||||
|         syntax_bridge::parse_to_token_tree(call_edition, call_anchor, SyntaxContextId::ROOT, arg) |         call_edition, | ||||||
|             .unwrap(); |         call_anchor, | ||||||
|  |         SyntaxContextId::root(Edition::CURRENT), | ||||||
|  |         arg, | ||||||
|  |     ) | ||||||
|  |     .unwrap(); | ||||||
|     let res = mac.expand( |     let res = mac.expand( | ||||||
|         &arg_tt, |         &arg_tt, | ||||||
|         |_| (), |         |_| (), | ||||||
|         Span { |         Span { | ||||||
|             range: TextRange::up_to(TextSize::of(arg)), |             range: TextRange::up_to(TextSize::of(arg)), | ||||||
|             anchor: call_anchor, |             anchor: call_anchor, | ||||||
|             ctx: SyntaxContextId::ROOT, |             ctx: SyntaxContextId::root(Edition::CURRENT), | ||||||
|         }, |         }, | ||||||
|         def_edition, |         def_edition, | ||||||
|     ); |     ); | ||||||
|  | @ -59,7 +63,12 @@ fn check_( | ||||||
|     if render_debug { |     if render_debug { | ||||||
|         format_to!(expect_res, "{:#?}\n\n", res.value.0); |         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!( |     format_to!( | ||||||
|         expect_res, |         expect_res, | ||||||
|         "{}", |         "{}", | ||||||
|  | @ -106,25 +115,25 @@ fn token_mapping_smoke_test() { | ||||||
| struct MyTraitMap2 | struct MyTraitMap2 | ||||||
| "#,
 | "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..20#0 1:0@0..20#0 |             SUBTREE $$ 1:0@0..20#2 1:0@0..20#2 | ||||||
|               IDENT   struct 0:0@34..40#0 |               IDENT   struct 0:0@34..40#2 | ||||||
|               IDENT   MyTraitMap2 1:0@8..19#0 |               IDENT   MyTraitMap2 1:0@8..19#2 | ||||||
|               SUBTREE {} 0:0@48..49#0 0:0@100..101#0 |               SUBTREE {} 0:0@48..49#2 0:0@100..101#2 | ||||||
|                 IDENT   map 0:0@58..61#0 |                 IDENT   map 0:0@58..61#2 | ||||||
|                 PUNCH   : [alone] 0:0@61..62#0 |                 PUNCH   : [alone] 0:0@61..62#2 | ||||||
|                 PUNCH   : [joint] 0:0@63..64#0 |                 PUNCH   : [joint] 0:0@63..64#2 | ||||||
|                 PUNCH   : [alone] 0:0@64..65#0 |                 PUNCH   : [alone] 0:0@64..65#2 | ||||||
|                 IDENT   std 0:0@65..68#0 |                 IDENT   std 0:0@65..68#2 | ||||||
|                 PUNCH   : [joint] 0:0@68..69#0 |                 PUNCH   : [joint] 0:0@68..69#2 | ||||||
|                 PUNCH   : [alone] 0:0@69..70#0 |                 PUNCH   : [alone] 0:0@69..70#2 | ||||||
|                 IDENT   collections 0:0@70..81#0 |                 IDENT   collections 0:0@70..81#2 | ||||||
|                 PUNCH   : [joint] 0:0@81..82#0 |                 PUNCH   : [joint] 0:0@81..82#2 | ||||||
|                 PUNCH   : [alone] 0:0@82..83#0 |                 PUNCH   : [alone] 0:0@82..83#2 | ||||||
|                 IDENT   HashSet 0:0@83..90#0 |                 IDENT   HashSet 0:0@83..90#2 | ||||||
|                 PUNCH   < [alone] 0:0@90..91#0 |                 PUNCH   < [alone] 0:0@90..91#2 | ||||||
|                 SUBTREE () 0:0@91..92#0 0:0@92..93#0 |                 SUBTREE () 0:0@91..92#2 0:0@92..93#2 | ||||||
|                 PUNCH   > [joint] 0:0@93..94#0 |                 PUNCH   > [joint] 0:0@93..94#2 | ||||||
|                 PUNCH   , [alone] 0:0@94..95#0 |                 PUNCH   , [alone] 0:0@94..95#2 | ||||||
| 
 | 
 | ||||||
|             struct MyTraitMap2 { |             struct MyTraitMap2 { | ||||||
|                 map: ::std::collections::HashSet<()>, |                 map: ::std::collections::HashSet<()>, | ||||||
|  | @ -153,28 +162,28 @@ fn main() { | ||||||
| } | } | ||||||
| "#,
 | "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..63#0 1:0@0..63#0 |             SUBTREE $$ 1:0@0..63#2 1:0@0..63#2 | ||||||
|               IDENT   fn 1:0@1..3#0 |               IDENT   fn 1:0@1..3#2 | ||||||
|               IDENT   main 1:0@4..8#0 |               IDENT   main 1:0@4..8#2 | ||||||
|               SUBTREE () 1:0@8..9#0 1:0@9..10#0 |               SUBTREE () 1:0@8..9#2 1:0@9..10#2 | ||||||
|               SUBTREE {} 1:0@11..12#0 1:0@61..62#0 |               SUBTREE {} 1:0@11..12#2 1:0@61..62#2 | ||||||
|                 LITERAL Integer 1 1:0@17..18#0 |                 LITERAL Integer 1 1:0@17..18#2 | ||||||
|                 PUNCH   ; [alone] 1:0@18..19#0 |                 PUNCH   ; [alone] 1:0@18..19#2 | ||||||
|                 LITERAL Float 1.0 1:0@24..27#0 |                 LITERAL Float 1.0 1:0@24..27#2 | ||||||
|                 PUNCH   ; [alone] 1:0@27..28#0 |                 PUNCH   ; [alone] 1:0@27..28#2 | ||||||
|                 SUBTREE () 1:0@33..34#0 1:0@39..40#0 |                 SUBTREE () 1:0@33..34#2 1:0@39..40#2 | ||||||
|                   SUBTREE () 1:0@34..35#0 1:0@37..38#0 |                   SUBTREE () 1:0@34..35#2 1:0@37..38#2 | ||||||
|                     LITERAL Integer 1 1:0@35..36#0 |                     LITERAL Integer 1 1:0@35..36#2 | ||||||
|                     PUNCH   , [alone] 1:0@36..37#0 |                     PUNCH   , [alone] 1:0@36..37#2 | ||||||
|                   PUNCH   , [alone] 1:0@38..39#0 |                   PUNCH   , [alone] 1:0@38..39#2 | ||||||
|                 PUNCH   . [alone] 1:0@40..41#0 |                 PUNCH   . [alone] 1:0@40..41#2 | ||||||
|                 LITERAL Float 0.0 1:0@41..44#0 |                 LITERAL Float 0.0 1:0@41..44#2 | ||||||
|                 PUNCH   ; [alone] 1:0@44..45#0 |                 PUNCH   ; [alone] 1:0@44..45#2 | ||||||
|                 IDENT   let 1:0@50..53#0 |                 IDENT   let 1:0@50..53#2 | ||||||
|                 IDENT   x 1:0@54..55#0 |                 IDENT   x 1:0@54..55#2 | ||||||
|                 PUNCH   = [alone] 1:0@56..57#0 |                 PUNCH   = [alone] 1:0@56..57#2 | ||||||
|                 LITERAL Integer 1 1:0@58..59#0 |                 LITERAL Integer 1 1:0@58..59#2 | ||||||
|                 PUNCH   ; [alone] 1:0@59..60#0 |                 PUNCH   ; [alone] 1:0@59..60#2 | ||||||
| 
 | 
 | ||||||
|             fn main(){ |             fn main(){ | ||||||
|                 1; |                 1; | ||||||
|  | @ -200,14 +209,14 @@ fn expr_2021() { | ||||||
|     const { 1 }, |     const { 1 }, | ||||||
| "#,
 | "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..25#0 1:0@0..25#0 |             SUBTREE $$ 1:0@0..25#2 1:0@0..25#2 | ||||||
|               IDENT   _ 1:0@5..6#0 |               IDENT   _ 1:0@5..6#2 | ||||||
|               PUNCH   ; [joint] 0:0@36..37#0 |               PUNCH   ; [joint] 0:0@36..37#2 | ||||||
|               SUBTREE () 0:0@34..35#0 0:0@34..35#0 |               SUBTREE () 0:0@34..35#2 0:0@34..35#2 | ||||||
|                 IDENT   const 1:0@12..17#0 |                 IDENT   const 1:0@12..17#2 | ||||||
|                 SUBTREE {} 1:0@18..19#0 1:0@22..23#0 |                 SUBTREE {} 1:0@18..19#2 1:0@22..23#2 | ||||||
|                   LITERAL Integer 1 1:0@20..21#0 |                   LITERAL Integer 1 1:0@20..21#2 | ||||||
|               PUNCH   ; [alone] 0:0@39..40#0 |               PUNCH   ; [alone] 0:0@39..40#2 | ||||||
| 
 | 
 | ||||||
|             _; |             _; | ||||||
|             (const  { |             (const  { | ||||||
|  | @ -228,13 +237,13 @@ fn expr_2021() { | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             ExpandError { |             ExpandError { | ||||||
|                 inner: ( |                 inner: ( | ||||||
|                     1:0@5..6#0, |                     1:0@5..6#2, | ||||||
|                     NoMatchingRule, |                     NoMatchingRule, | ||||||
|                 ), |                 ), | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 1:0@0..8#0 1:0@0..8#0 |             SUBTREE $$ 1:0@0..8#2 1:0@0..8#2 | ||||||
|               PUNCH   ; [alone] 0:0@39..40#0 |               PUNCH   ; [alone] 0:0@39..40#2 | ||||||
| 
 | 
 | ||||||
|             ;"#]],
 |             ;"#]],
 | ||||||
|     ); |     ); | ||||||
|  | @ -252,13 +261,13 @@ fn expr_2021() { | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             ExpandError { |             ExpandError { | ||||||
|                 inner: ( |                 inner: ( | ||||||
|                     1:0@5..10#0, |                     1:0@5..10#2, | ||||||
|                     NoMatchingRule, |                     NoMatchingRule, | ||||||
|                 ), |                 ), | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 1:0@0..18#0 1:0@0..18#0 |             SUBTREE $$ 1:0@0..18#2 1:0@0..18#2 | ||||||
|               PUNCH   ; [alone] 0:0@39..40#0 |               PUNCH   ; [alone] 0:0@39..40#2 | ||||||
| 
 | 
 | ||||||
|             ;"#]],
 |             ;"#]],
 | ||||||
|     ); |     ); | ||||||
|  | @ -278,26 +287,26 @@ fn expr_2021() { | ||||||
|     break 'foo bar, |     break 'foo bar, | ||||||
| "#,
 | "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..76#0 1:0@0..76#0 |             SUBTREE $$ 1:0@0..76#2 1:0@0..76#2 | ||||||
|               LITERAL Integer 4 1:0@5..6#0 |               LITERAL Integer 4 1:0@5..6#2 | ||||||
|               PUNCH   ; [joint] 0:0@41..42#0 |               PUNCH   ; [joint] 0:0@41..42#2 | ||||||
|               LITERAL Str literal 1:0@12..21#0 |               LITERAL Str literal 1:0@12..21#2 | ||||||
|               PUNCH   ; [joint] 0:0@41..42#0 |               PUNCH   ; [joint] 0:0@41..42#2 | ||||||
|               SUBTREE () 0:0@39..40#0 0:0@39..40#0 |               SUBTREE () 0:0@39..40#2 0:0@39..40#2 | ||||||
|                 IDENT   funcall 1:0@27..34#0 |                 IDENT   funcall 1:0@27..34#2 | ||||||
|                 SUBTREE () 1:0@34..35#0 1:0@35..36#0 |                 SUBTREE () 1:0@34..35#2 1:0@35..36#2 | ||||||
|               PUNCH   ; [joint] 0:0@41..42#0 |               PUNCH   ; [joint] 0:0@41..42#2 | ||||||
|               SUBTREE () 0:0@39..40#0 0:0@39..40#0 |               SUBTREE () 0:0@39..40#2 0:0@39..40#2 | ||||||
|                 IDENT   future 1:0@42..48#0 |                 IDENT   future 1:0@42..48#2 | ||||||
|                 PUNCH   . [alone] 1:0@48..49#0 |                 PUNCH   . [alone] 1:0@48..49#2 | ||||||
|                 IDENT   await 1:0@49..54#0 |                 IDENT   await 1:0@49..54#2 | ||||||
|               PUNCH   ; [joint] 0:0@41..42#0 |               PUNCH   ; [joint] 0:0@41..42#2 | ||||||
|               SUBTREE () 0:0@39..40#0 0:0@39..40#0 |               SUBTREE () 0:0@39..40#2 0:0@39..40#2 | ||||||
|                 IDENT   break 1:0@60..65#0 |                 IDENT   break 1:0@60..65#2 | ||||||
|                 PUNCH   ' [joint] 1:0@66..67#0 |                 PUNCH   ' [joint] 1:0@66..67#2 | ||||||
|                 IDENT   foo 1:0@67..70#0 |                 IDENT   foo 1:0@67..70#2 | ||||||
|                 IDENT   bar 1:0@71..74#0 |                 IDENT   bar 1:0@71..74#2 | ||||||
|               PUNCH   ; [alone] 0:0@44..45#0 |               PUNCH   ; [alone] 0:0@44..45#2 | ||||||
| 
 | 
 | ||||||
|             4; |             4; | ||||||
|             "literal"; |             "literal"; | ||||||
|  | @ -319,13 +328,13 @@ fn expr_2021() { | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             ExpandError { |             ExpandError { | ||||||
|                 inner: ( |                 inner: ( | ||||||
|                     1:0@5..6#0, |                     1:0@5..6#2, | ||||||
|                     NoMatchingRule, |                     NoMatchingRule, | ||||||
|                 ), |                 ), | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 1:0@0..8#0 1:0@0..8#0 |             SUBTREE $$ 1:0@0..8#2 1:0@0..8#2 | ||||||
|               PUNCH   ; [alone] 0:0@44..45#0 |               PUNCH   ; [alone] 0:0@44..45#2 | ||||||
| 
 | 
 | ||||||
|             ;"#]],
 |             ;"#]],
 | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|  | @ -159,7 +159,7 @@ type ProtocolWrite<W: Write> = for<'o, 'msg> fn(out: &'o mut W, msg: &'msg str) | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod tests { | mod tests { | ||||||
|     use intern::{sym, Symbol}; |     use intern::{sym, Symbol}; | ||||||
|     use span::{ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, TextRange, TextSize}; |     use span::{Edition, ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, TextRange, TextSize}; | ||||||
|     use tt::{ |     use tt::{ | ||||||
|         Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, Spacing, TopSubtree, |         Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, Spacing, TopSubtree, | ||||||
|         TopSubtreeBuilder, |         TopSubtreeBuilder, | ||||||
|  | @ -180,12 +180,12 @@ mod tests { | ||||||
|             open: Span { |             open: Span { | ||||||
|                 range: TextRange::empty(TextSize::new(0)), |                 range: TextRange::empty(TextSize::new(0)), | ||||||
|                 anchor, |                 anchor, | ||||||
|                 ctx: SyntaxContextId::ROOT, |                 ctx: SyntaxContextId::root(Edition::CURRENT), | ||||||
|             }, |             }, | ||||||
|             close: Span { |             close: Span { | ||||||
|                 range: TextRange::empty(TextSize::new(19)), |                 range: TextRange::empty(TextSize::new(19)), | ||||||
|                 anchor, |                 anchor, | ||||||
|                 ctx: SyntaxContextId::ROOT, |                 ctx: SyntaxContextId::root(Edition::CURRENT), | ||||||
|             }, |             }, | ||||||
|             kind: DelimiterKind::Invisible, |             kind: DelimiterKind::Invisible, | ||||||
|         }); |         }); | ||||||
|  | @ -196,7 +196,7 @@ mod tests { | ||||||
|                 span: Span { |                 span: Span { | ||||||
|                     range: TextRange::at(TextSize::new(0), TextSize::of("struct")), |                     range: TextRange::at(TextSize::new(0), TextSize::of("struct")), | ||||||
|                     anchor, |                     anchor, | ||||||
|                     ctx: SyntaxContextId::ROOT, |                     ctx: SyntaxContextId::root(Edition::CURRENT), | ||||||
|                 }, |                 }, | ||||||
|                 is_raw: tt::IdentIsRaw::No, |                 is_raw: tt::IdentIsRaw::No, | ||||||
|             } |             } | ||||||
|  | @ -208,7 +208,7 @@ mod tests { | ||||||
|                 span: Span { |                 span: Span { | ||||||
|                     range: TextRange::at(TextSize::new(5), TextSize::of("r#Foo")), |                     range: TextRange::at(TextSize::new(5), TextSize::of("r#Foo")), | ||||||
|                     anchor, |                     anchor, | ||||||
|                     ctx: SyntaxContextId::ROOT, |                     ctx: SyntaxContextId::root(Edition::CURRENT), | ||||||
|                 }, |                 }, | ||||||
|                 is_raw: tt::IdentIsRaw::Yes, |                 is_raw: tt::IdentIsRaw::Yes, | ||||||
|             } |             } | ||||||
|  | @ -219,7 +219,7 @@ mod tests { | ||||||
|             span: Span { |             span: Span { | ||||||
|                 range: TextRange::at(TextSize::new(10), TextSize::of("\"Foo\"")), |                 range: TextRange::at(TextSize::new(10), TextSize::of("\"Foo\"")), | ||||||
|                 anchor, |                 anchor, | ||||||
|                 ctx: SyntaxContextId::ROOT, |                 ctx: SyntaxContextId::root(Edition::CURRENT), | ||||||
|             }, |             }, | ||||||
|             kind: tt::LitKind::Str, |             kind: tt::LitKind::Str, | ||||||
|             suffix: None, |             suffix: None, | ||||||
|  | @ -229,7 +229,7 @@ mod tests { | ||||||
|             span: Span { |             span: Span { | ||||||
|                 range: TextRange::at(TextSize::new(13), TextSize::of('@')), |                 range: TextRange::at(TextSize::new(13), TextSize::of('@')), | ||||||
|                 anchor, |                 anchor, | ||||||
|                 ctx: SyntaxContextId::ROOT, |                 ctx: SyntaxContextId::root(Edition::CURRENT), | ||||||
|             }, |             }, | ||||||
|             spacing: Spacing::Joint, |             spacing: Spacing::Joint, | ||||||
|         })); |         })); | ||||||
|  | @ -238,7 +238,7 @@ mod tests { | ||||||
|             Span { |             Span { | ||||||
|                 range: TextRange::at(TextSize::new(14), TextSize::of('{')), |                 range: TextRange::at(TextSize::new(14), TextSize::of('{')), | ||||||
|                 anchor, |                 anchor, | ||||||
|                 ctx: SyntaxContextId::ROOT, |                 ctx: SyntaxContextId::root(Edition::CURRENT), | ||||||
|             }, |             }, | ||||||
|         ); |         ); | ||||||
|         builder.push(Leaf::Literal(Literal { |         builder.push(Leaf::Literal(Literal { | ||||||
|  | @ -246,7 +246,7 @@ mod tests { | ||||||
|             span: Span { |             span: Span { | ||||||
|                 range: TextRange::at(TextSize::new(15), TextSize::of("0u32")), |                 range: TextRange::at(TextSize::new(15), TextSize::of("0u32")), | ||||||
|                 anchor, |                 anchor, | ||||||
|                 ctx: SyntaxContextId::ROOT, |                 ctx: SyntaxContextId::root(Edition::CURRENT), | ||||||
|             }, |             }, | ||||||
|             kind: tt::LitKind::Integer, |             kind: tt::LitKind::Integer, | ||||||
|             suffix: Some(sym::u32.clone()), |             suffix: Some(sym::u32.clone()), | ||||||
|  | @ -254,7 +254,7 @@ mod tests { | ||||||
|         builder.close(Span { |         builder.close(Span { | ||||||
|             range: TextRange::at(TextSize::new(19), TextSize::of('}')), |             range: TextRange::at(TextSize::new(19), TextSize::of('}')), | ||||||
|             anchor, |             anchor, | ||||||
|             ctx: SyntaxContextId::ROOT, |             ctx: SyntaxContextId::root(Edition::CURRENT), | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         builder.build() |         builder.build() | ||||||
|  |  | ||||||
|  | @ -440,7 +440,7 @@ mod tests { | ||||||
|                 file_id: EditionedFileId::current_edition(FileId::from_raw(0)), |                 file_id: EditionedFileId::current_edition(FileId::from_raw(0)), | ||||||
|                 ast_id: span::ErasedFileAstId::from_raw(0), |                 ast_id: span::ErasedFileAstId::from_raw(0), | ||||||
|             }, |             }, | ||||||
|             ctx: SyntaxContextId::ROOT, |             ctx: SyntaxContextId::root(span::Edition::CURRENT), | ||||||
|         }; |         }; | ||||||
|         let s = TokenStream { |         let s = TokenStream { | ||||||
|             token_trees: vec![ |             token_trees: vec![ | ||||||
|  | @ -482,7 +482,7 @@ mod tests { | ||||||
|                 file_id: EditionedFileId::current_edition(FileId::from_raw(0)), |                 file_id: EditionedFileId::current_edition(FileId::from_raw(0)), | ||||||
|                 ast_id: span::ErasedFileAstId::from_raw(0), |                 ast_id: span::ErasedFileAstId::from_raw(0), | ||||||
|             }, |             }, | ||||||
|             ctx: SyntaxContextId::ROOT, |             ctx: SyntaxContextId::root(span::Edition::CURRENT), | ||||||
|         }; |         }; | ||||||
|         let subtree_paren_a = vec![ |         let subtree_paren_a = vec![ | ||||||
|             tt::TokenTree::Subtree(tt::Subtree { |             tt::TokenTree::Subtree(tt::Subtree { | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ fn test_derive_empty() { | ||||||
|         "DeriveEmpty", |         "DeriveEmpty", | ||||||
|         r#"struct S;"#, |         r#"struct S;"#, | ||||||
|         expect!["SUBTREE $$ 1 1"], |         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 |                 LITERAL Str #[derive(DeriveError)] struct S ; 1 | ||||||
|               PUNCH   ; [alone] 1"#]],
 |               PUNCH   ; [alone] 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 |             SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 | ||||||
|               IDENT   compile_error 42:2@0..100#0 |               IDENT   compile_error 42:2@0..100#2 | ||||||
|               PUNCH   ! [alone] 42:2@0..100#0 |               PUNCH   ! [alone] 42:2@0..100#2 | ||||||
|               SUBTREE () 42:2@0..100#0 42:2@0..100#0 |               SUBTREE () 42:2@0..100#2 42:2@0..100#2 | ||||||
|                 LITERAL Str #[derive(DeriveError)] struct S ; 42:2@0..100#0 |                 LITERAL Str #[derive(DeriveError)] struct S ; 42:2@0..100#2 | ||||||
|               PUNCH   ; [alone] 42:2@0..100#0"#]],
 |               PUNCH   ; [alone] 42:2@0..100#2"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -53,14 +53,14 @@ fn test_fn_like_macro_noop() { | ||||||
|               PUNCH   , [alone] 1 |               PUNCH   , [alone] 1 | ||||||
|               SUBTREE [] 1 1"#]],
 |               SUBTREE [] 1 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 |             SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 | ||||||
|               IDENT   ident 42:2@0..5#0 |               IDENT   ident 42:2@0..5#2 | ||||||
|               PUNCH   , [alone] 42:2@5..6#0 |               PUNCH   , [alone] 42:2@5..6#2 | ||||||
|               LITERAL Integer 0 42:2@7..8#0 |               LITERAL Integer 0 42:2@7..8#2 | ||||||
|               PUNCH   , [alone] 42:2@8..9#0 |               PUNCH   , [alone] 42:2@8..9#2 | ||||||
|               LITERAL Integer 1 42:2@10..11#0 |               LITERAL Integer 1 42:2@10..11#2 | ||||||
|               PUNCH   , [alone] 42:2@11..12#0 |               PUNCH   , [alone] 42:2@11..12#2 | ||||||
|               SUBTREE [] 42:2@13..14#0 42:2@14..15#0"#]],
 |               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 |               PUNCH   , [alone] 1 | ||||||
|               SUBTREE [] 1 1"#]],
 |               SUBTREE [] 1 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 |             SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 | ||||||
|               IDENT   ident 42:2@0..5#0 |               IDENT   ident 42:2@0..5#2 | ||||||
|               PUNCH   , [alone] 42:2@5..6#0 |               PUNCH   , [alone] 42:2@5..6#2 | ||||||
|               SUBTREE [] 42:2@7..8#0 42:2@7..8#0"#]],
 |               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 |             SUBTREE $$ 1 1 | ||||||
|               IDENT   r#async 1"#]],
 |               IDENT   r#async 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 |             SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 | ||||||
|               IDENT   r#async 42:2@0..7#0"#]],
 |               IDENT   r#async 42:2@0..7#2"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -105,8 +105,8 @@ fn test_fn_like_fn_like_span_join() { | ||||||
|             SUBTREE $$ 1 1 |             SUBTREE $$ 1 1 | ||||||
|               IDENT   r#joined 1"#]],
 |               IDENT   r#joined 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 |             SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 | ||||||
|               IDENT   r#joined 42:2@0..11#0"#]],
 |               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   resolved_at_def_site 1 | ||||||
|               IDENT   start_span 1"#]],
 |               IDENT   start_span 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 |             SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 | ||||||
|               IDENT   set_def_site 41:1@0..150#0 |               IDENT   set_def_site 41:1@0..150#2 | ||||||
|               IDENT   resolved_at_def_site 42:2@13..33#0 |               IDENT   resolved_at_def_site 42:2@13..33#2 | ||||||
|               IDENT   start_span 42:2@34..34#0"#]],
 |               IDENT   start_span 42:2@34..34#2"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -143,14 +143,14 @@ fn test_fn_like_mk_literals() { | ||||||
|               LITERAL Integer 123i64 1 |               LITERAL Integer 123i64 1 | ||||||
|               LITERAL Integer 123 1"#]],
 |               LITERAL Integer 123 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 |             SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 | ||||||
|               LITERAL ByteStr byte_string 42:2@0..100#0 |               LITERAL ByteStr byte_string 42:2@0..100#2 | ||||||
|               LITERAL Char c 42:2@0..100#0 |               LITERAL Char c 42:2@0..100#2 | ||||||
|               LITERAL Str string 42:2@0..100#0 |               LITERAL Str string 42:2@0..100#2 | ||||||
|               LITERAL Float 3.14f64 42:2@0..100#0 |               LITERAL Float 3.14f64 42:2@0..100#2 | ||||||
|               LITERAL Float 3.14 42:2@0..100#0 |               LITERAL Float 3.14 42:2@0..100#2 | ||||||
|               LITERAL Integer 123i64 42:2@0..100#0 |               LITERAL Integer 123i64 42:2@0..100#2 | ||||||
|               LITERAL Integer 123 42:2@0..100#0"#]],
 |               LITERAL Integer 123 42:2@0..100#2"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -164,9 +164,9 @@ fn test_fn_like_mk_idents() { | ||||||
|               IDENT   standard 1 |               IDENT   standard 1 | ||||||
|               IDENT   r#raw 1"#]],
 |               IDENT   r#raw 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 |             SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 | ||||||
|               IDENT   standard 42:2@0..100#0 |               IDENT   standard 42:2@0..100#2 | ||||||
|               IDENT   r#raw 42:2@0..100#0"#]],
 |               IDENT   r#raw 42:2@0..100#2"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -198,27 +198,27 @@ fn test_fn_like_macro_clone_literals() { | ||||||
|               PUNCH   , [alone] 1 |               PUNCH   , [alone] 1 | ||||||
|               LITERAL CStr null 1"#]],
 |               LITERAL CStr null 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 |             SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 | ||||||
|               LITERAL Integer 1u16 42:2@0..4#0 |               LITERAL Integer 1u16 42:2@0..4#2 | ||||||
|               PUNCH   , [alone] 42:2@4..5#0 |               PUNCH   , [alone] 42:2@4..5#2 | ||||||
|               LITERAL Integer 2_u32 42:2@6..11#0 |               LITERAL Integer 2_u32 42:2@6..11#2 | ||||||
|               PUNCH   , [alone] 42:2@11..12#0 |               PUNCH   , [alone] 42:2@11..12#2 | ||||||
|               PUNCH   - [alone] 42:2@13..14#0 |               PUNCH   - [alone] 42:2@13..14#2 | ||||||
|               LITERAL Integer 4i64 42:2@14..18#0 |               LITERAL Integer 4i64 42:2@14..18#2 | ||||||
|               PUNCH   , [alone] 42:2@18..19#0 |               PUNCH   , [alone] 42:2@18..19#2 | ||||||
|               LITERAL Float 3.14f32 42:2@20..27#0 |               LITERAL Float 3.14f32 42:2@20..27#2 | ||||||
|               PUNCH   , [alone] 42:2@27..28#0 |               PUNCH   , [alone] 42:2@27..28#2 | ||||||
|               LITERAL Str hello bridge 42:2@29..43#0 |               LITERAL Str hello bridge 42:2@29..43#2 | ||||||
|               PUNCH   , [alone] 42:2@43..44#0 |               PUNCH   , [alone] 42:2@43..44#2 | ||||||
|               LITERAL Str suffixedsuffix 42:2@45..61#0 |               LITERAL Str suffixedsuffix 42:2@45..61#2 | ||||||
|               PUNCH   , [alone] 42:2@61..62#0 |               PUNCH   , [alone] 42:2@61..62#2 | ||||||
|               LITERAL StrRaw(2) raw 42:2@63..73#0 |               LITERAL StrRaw(2) raw 42:2@63..73#2 | ||||||
|               PUNCH   , [alone] 42:2@73..74#0 |               PUNCH   , [alone] 42:2@73..74#2 | ||||||
|               LITERAL Char a 42:2@75..78#0 |               LITERAL Char a 42:2@75..78#2 | ||||||
|               PUNCH   , [alone] 42:2@78..79#0 |               PUNCH   , [alone] 42:2@78..79#2 | ||||||
|               LITERAL Byte b 42:2@80..84#0 |               LITERAL Byte b 42:2@80..84#2 | ||||||
|               PUNCH   , [alone] 42:2@84..85#0 |               PUNCH   , [alone] 42:2@84..85#2 | ||||||
|               LITERAL CStr null 42:2@86..93#0"#]],
 |               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 |                 LITERAL Str #[attr_error(some arguments)] mod m {} 1 | ||||||
|               PUNCH   ; [alone] 1"#]],
 |               PUNCH   ; [alone] 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 |             SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 | ||||||
|               IDENT   compile_error 42:2@0..100#0 |               IDENT   compile_error 42:2@0..100#2 | ||||||
|               PUNCH   ! [alone] 42:2@0..100#0 |               PUNCH   ! [alone] 42:2@0..100#2 | ||||||
|               SUBTREE () 42:2@0..100#0 42:2@0..100#0 |               SUBTREE () 42:2@0..100#2 42:2@0..100#2 | ||||||
|                 LITERAL Str #[attr_error(some arguments)] mod m {} 42:2@0..100#0 |                 LITERAL Str #[attr_error(some arguments)] mod m {} 42:2@0..100#2 | ||||||
|               PUNCH   ; [alone] 42:2@0..100#0"#]],
 |               PUNCH   ; [alone] 42:2@0..100#2"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -76,7 +76,7 @@ fn assert_expand_impl( | ||||||
|             file_id: EditionedFileId::current_edition(FileId::from_raw(41)), |             file_id: EditionedFileId::current_edition(FileId::from_raw(41)), | ||||||
|             ast_id: ErasedFileAstId::from_raw(1), |             ast_id: ErasedFileAstId::from_raw(1), | ||||||
|         }, |         }, | ||||||
|         ctx: SyntaxContextId::ROOT, |         ctx: SyntaxContextId::root(span::Edition::CURRENT), | ||||||
|     }; |     }; | ||||||
|     let call_site = Span { |     let call_site = Span { | ||||||
|         range: TextRange::new(0.into(), 100.into()), |         range: TextRange::new(0.into(), 100.into()), | ||||||
|  | @ -84,7 +84,7 @@ fn assert_expand_impl( | ||||||
|             file_id: EditionedFileId::current_edition(FileId::from_raw(42)), |             file_id: EditionedFileId::current_edition(FileId::from_raw(42)), | ||||||
|             ast_id: ErasedFileAstId::from_raw(2), |             ast_id: ErasedFileAstId::from_raw(2), | ||||||
|         }, |         }, | ||||||
|         ctx: SyntaxContextId::ROOT, |         ctx: SyntaxContextId::root(span::Edition::CURRENT), | ||||||
|     }; |     }; | ||||||
|     let mixed_site = call_site; |     let mixed_site = call_site; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ use crate::InternId; | ||||||
| #[cfg(feature = "ra-salsa")] | #[cfg(feature = "ra-salsa")] | ||||||
| use ra_salsa::{InternId, InternValue}; | use ra_salsa::{InternId, InternValue}; | ||||||
| 
 | 
 | ||||||
| use crate::MacroCallId; | use crate::{Edition, MacroCallId}; | ||||||
| 
 | 
 | ||||||
| /// Interned [`SyntaxContextData`].
 | /// Interned [`SyntaxContextData`].
 | ||||||
| #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||||||
|  | @ -59,11 +59,20 @@ impl fmt::Display for SyntaxContextId { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl 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.
 |     /// 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 { |     pub fn is_root(self) -> bool { | ||||||
|         self == Self::ROOT |         self.into_u32() <= Edition::LATEST as u32 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Deconstruct a `SyntaxContextId` into a raw `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.
 |     // per crate. Though that is likely not a problem as `MacroCallId`s are already crate calling dependent.
 | ||||||
|     pub outer_expn: Option<MacroCallId>, |     pub outer_expn: Option<MacroCallId>, | ||||||
|     pub outer_transparency: Transparency, |     pub outer_transparency: Transparency, | ||||||
|  |     pub edition: Edition, | ||||||
|     pub parent: SyntaxContextId, |     pub parent: SyntaxContextId, | ||||||
|     /// This context, but with all transparent and semi-transparent expansions filtered away.
 |     /// This context, but with all transparent and semi-transparent expansions filtered away.
 | ||||||
|     pub opaque: SyntaxContextId, |     pub opaque: SyntaxContextId, | ||||||
|  | @ -98,10 +108,10 @@ pub struct SyntaxContextData { | ||||||
| 
 | 
 | ||||||
| #[cfg(feature = "ra-salsa")] | #[cfg(feature = "ra-salsa")] | ||||||
| impl InternValue for SyntaxContextData { | impl InternValue for SyntaxContextData { | ||||||
|     type Key = (SyntaxContextId, Option<MacroCallId>, Transparency); |     type Key = (SyntaxContextId, Option<MacroCallId>, Transparency, Edition); | ||||||
| 
 | 
 | ||||||
|     fn into_key(&self) -> Self::Key { |     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 { | impl SyntaxContextData { | ||||||
|     pub fn root() -> Self { |     pub fn root(edition: Edition) -> Self { | ||||||
|         SyntaxContextData { |         SyntaxContextData { | ||||||
|             outer_expn: None, |             outer_expn: None, | ||||||
|             outer_transparency: Transparency::Opaque, |             outer_transparency: Transparency::Opaque, | ||||||
|             parent: SyntaxContextId::ROOT, |             parent: SyntaxContextId::root(edition), | ||||||
|             opaque: SyntaxContextId::ROOT, |             opaque: SyntaxContextId::root(edition), | ||||||
|             opaque_and_semitransparent: SyntaxContextId::ROOT, |             opaque_and_semitransparent: SyntaxContextId::root(edition), | ||||||
|  |             edition, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -208,7 +208,7 @@ impl RealSpanMap { | ||||||
|         Span { |         Span { | ||||||
|             range: range - offset, |             range: range - offset, | ||||||
|             anchor: SpanAnchor { file_id: self.file_id, ast_id }, |             anchor: SpanAnchor { file_id: self.file_id, ast_id }, | ||||||
|             ctx: SyntaxContextId::ROOT, |             ctx: SyntaxContextId::root(self.file_id.edition()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| //! Conversions between [`SyntaxNode`] and [`tt::TokenTree`].
 | //! Conversions between [`SyntaxNode`] and [`tt::TokenTree`].
 | ||||||
| 
 | 
 | ||||||
| use std::fmt; | use std::{fmt, hash::Hash}; | ||||||
| 
 | 
 | ||||||
| use intern::Symbol; | use intern::Symbol; | ||||||
| use rustc_hash::{FxHashMap, FxHashSet}; | use rustc_hash::{FxHashMap, FxHashSet}; | ||||||
|  | @ -58,7 +58,7 @@ pub mod dummy_test_span_utils { | ||||||
|             ), |             ), | ||||||
|             ast_id: span::ROOT_ERASED_FILE_AST_ID, |             ast_id: span::ROOT_ERASED_FILE_AST_ID, | ||||||
|         }, |         }, | ||||||
|         ctx: SyntaxContextId::ROOT, |         ctx: SyntaxContextId::root(Edition::CURRENT), | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     pub struct DummyTestSpanMap; |     pub struct DummyTestSpanMap; | ||||||
|  | @ -74,7 +74,7 @@ pub mod dummy_test_span_utils { | ||||||
|                     ), |                     ), | ||||||
|                     ast_id: span::ROOT_ERASED_FILE_AST_ID, |                     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<Ctx>( | pub fn token_tree_to_syntax_node<Ctx>( | ||||||
|     tt: &tt::TopSubtree<SpanData<Ctx>>, |     tt: &tt::TopSubtree<SpanData<Ctx>>, | ||||||
|     entry_point: parser::TopEntryPoint, |     entry_point: parser::TopEntryPoint, | ||||||
|     edition: parser::Edition, |     span_to_edition: &mut dyn FnMut(Ctx) -> Edition, | ||||||
|  |     top_edition: Edition, | ||||||
| ) -> (Parse<SyntaxNode>, SpanMap<Ctx>) | ) -> (Parse<SyntaxNode>, SpanMap<Ctx>) | ||||||
| where | where | ||||||
|     SpanData<Ctx>: Copy + fmt::Debug, |     Ctx: Copy + fmt::Debug + PartialEq + PartialEq + Eq + Hash, | ||||||
|     Ctx: PartialEq, |  | ||||||
| { | { | ||||||
|     let buffer = tt.view().strip_invisible(); |     let buffer = tt.view().strip_invisible(); | ||||||
|     let parser_input = to_parser_input(edition, buffer); |     let parser_input = to_parser_input(buffer, span_to_edition); | ||||||
|     let parser_output = entry_point.parse(&parser_input, 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()); |     let mut tree_sink = TtTreeSink::new(buffer.cursor()); | ||||||
|     for event in parser_output.iter() { |     for event in parser_output.iter() { | ||||||
|         match event { |         match event { | ||||||
|  |  | ||||||
|  | @ -2,17 +2,20 @@ | ||||||
| //! format that works for our parser.
 | //! format that works for our parser.
 | ||||||
| 
 | 
 | ||||||
| use std::fmt; | use std::fmt; | ||||||
|  | use std::hash::Hash; | ||||||
| 
 | 
 | ||||||
| use span::Edition; | use rustc_hash::FxHashMap; | ||||||
|  | use span::{Edition, SpanData}; | ||||||
| use syntax::{SyntaxKind, SyntaxKind::*, T}; | use syntax::{SyntaxKind, SyntaxKind::*, T}; | ||||||
| 
 | 
 | ||||||
| pub fn to_parser_input<S: Copy + fmt::Debug>( | pub fn to_parser_input<Ctx: Copy + fmt::Debug + PartialEq + Eq + Hash>( | ||||||
|     edition: Edition, |     buffer: tt::TokenTreesView<'_, SpanData<Ctx>>, | ||||||
|     buffer: tt::TokenTreesView<'_, S>, |     span_to_edition: &mut dyn FnMut(Ctx) -> Edition, | ||||||
| ) -> parser::Input { | ) -> parser::Input { | ||||||
|     let mut res = parser::Input::default(); |     let mut res = parser::Input::default(); | ||||||
| 
 | 
 | ||||||
|     let mut current = buffer.cursor(); |     let mut current = buffer.cursor(); | ||||||
|  |     let mut syntax_context_to_edition_cache = FxHashMap::default(); | ||||||
| 
 | 
 | ||||||
|     while !current.eof() { |     while !current.eof() { | ||||||
|         let tt = current.token_tree(); |         let tt = current.token_tree(); | ||||||
|  | @ -57,20 +60,25 @@ pub fn to_parser_input<S: Copy + fmt::Debug>( | ||||||
|                             res.was_joint(); |                             res.was_joint(); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     tt::Leaf::Ident(ident) => match ident.sym.as_str() { |                     tt::Leaf::Ident(ident) => { | ||||||
|                         "_" => res.push(T![_]), |                         let edition = *syntax_context_to_edition_cache | ||||||
|                         i if i.starts_with('\'') => res.push(LIFETIME_IDENT), |                             .entry(ident.span.ctx) | ||||||
|                         _ if ident.is_raw.yes() => res.push(IDENT), |                             .or_insert_with(|| span_to_edition(ident.span.ctx)); | ||||||
|                         text => match SyntaxKind::from_keyword(text, edition) { |                         match ident.sym.as_str() { | ||||||
|                             Some(kind) => res.push(kind), |                             "_" => res.push(T![_]), | ||||||
|                             None => { |                             i if i.starts_with('\'') => res.push(LIFETIME_IDENT), | ||||||
|                                 let contextual_keyword = |                             _ if ident.is_raw.yes() => res.push(IDENT), | ||||||
|                                     SyntaxKind::from_contextual_keyword(text, edition) |                             text => match SyntaxKind::from_keyword(text, edition) { | ||||||
|                                         .unwrap_or(SyntaxKind::IDENT); |                                 Some(kind) => res.push(kind), | ||||||
|                                 res.push_ident(contextual_keyword); |                                 None => { | ||||||
|                             } |                                     let contextual_keyword = | ||||||
|                         }, |                                         SyntaxKind::from_contextual_keyword(text, edition) | ||||||
|                     }, |                                             .unwrap_or(SyntaxKind::IDENT); | ||||||
|  |                                     res.push_ident(contextual_keyword); | ||||||
|  |                                 } | ||||||
|  |                             }, | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|                     tt::Leaf::Punct(punct) => { |                     tt::Leaf::Punct(punct) => { | ||||||
|                         let kind = SyntaxKind::from_char(punct.char) |                         let kind = SyntaxKind::from_char(punct.char) | ||||||
|                             .unwrap_or_else(|| panic!("{punct:#?} is not a valid punct")); |                             .unwrap_or_else(|| panic!("{punct:#?} is not a valid punct")); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lukas Wirth
						Lukas Wirth