@@ -13,10 +13,11 @@ use syntax::{
1313
1414use crate :: {
1515 db:: ExpandDatabase ,
16- hygiene:: span_with_def_site_ctxt,
17- name, quote,
16+ hygiene:: { span_with_call_site_ctxt, span_with_def_site_ctxt} ,
17+ name:: { self , known} ,
18+ quote,
1819 tt:: { self , DelimSpan } ,
19- ExpandError , ExpandResult , HirFileIdExt , MacroCallId , MacroCallLoc ,
20+ ExpandError , ExpandResult , HirFileIdExt , MacroCallId ,
2021} ;
2122
2223macro_rules! register_builtin {
@@ -196,32 +197,38 @@ fn stringify_expand(
196197}
197198
198199fn assert_expand (
199- _db : & dyn ExpandDatabase ,
200- _id : MacroCallId ,
200+ db : & dyn ExpandDatabase ,
201+ id : MacroCallId ,
201202 tt : & tt:: Subtree ,
202203 span : Span ,
203204) -> ExpandResult < tt:: Subtree > {
204- let args = parse_exprs_with_sep ( tt, ',' , span) ;
205+ let call_site_span = span_with_call_site_ctxt ( db, span, id) ;
206+ let args = parse_exprs_with_sep ( tt, ',' , call_site_span) ;
205207 let dollar_crate = tt:: Ident { text : SmolStr :: new_inline ( "$crate" ) , span } ;
206208 let expanded = match & * args {
207209 [ cond, panic_args @ ..] => {
208210 let comma = tt:: Subtree {
209- delimiter : tt:: Delimiter :: invisible_spanned ( span ) ,
211+ delimiter : tt:: Delimiter :: invisible_spanned ( call_site_span ) ,
210212 token_trees : vec ! [ tt:: TokenTree :: Leaf ( tt:: Leaf :: Punct ( tt:: Punct {
211213 char : ',' ,
212214 spacing: tt:: Spacing :: Alone ,
213- span,
215+ span: call_site_span ,
214216 } ) ) ] ,
215217 } ;
216218 let cond = cond. clone ( ) ;
217219 let panic_args = itertools:: Itertools :: intersperse ( panic_args. iter ( ) . cloned ( ) , comma) ;
218- quote ! { span =>{
220+ let mac = if use_panic_2021 ( db, span) {
221+ quote ! { call_site_span => #dollar_crate:: panic:: panic_2021!( ##panic_args) }
222+ } else {
223+ quote ! { call_site_span => #dollar_crate:: panic!( ##panic_args) }
224+ } ;
225+ quote ! { call_site_span =>{
219226 if !( #cond) {
220- #dollar_crate :: panic! ( ##panic_args ) ;
227+ #mac ;
221228 }
222229 } }
223230 }
224- [ ] => quote ! { span =>{ } } ,
231+ [ ] => quote ! { call_site_span =>{ } } ,
225232 } ;
226233
227234 ExpandResult :: ok ( expanded)
@@ -337,17 +344,23 @@ fn panic_expand(
337344 tt : & tt:: Subtree ,
338345 span : Span ,
339346) -> ExpandResult < tt:: Subtree > {
340- let loc: MacroCallLoc = db. lookup_intern_macro_call ( id) ;
341347 let dollar_crate = tt:: Ident { text : SmolStr :: new_inline ( "$crate" ) , span } ;
348+ let call_site_span = span_with_call_site_ctxt ( db, span, id) ;
349+
350+ let mac =
351+ if use_panic_2021 ( db, call_site_span) { known:: panic_2021 } else { known:: panic_2015 } ;
352+
342353 // Expand to a macro call `$crate::panic::panic_{edition}`
343- let mut call = if db. crate_graph ( ) [ loc. krate ] . edition >= Edition :: Edition2021 {
344- quote ! ( span =>#dollar_crate:: panic:: panic_2021!)
345- } else {
346- quote ! ( span =>#dollar_crate:: panic:: panic_2015!)
347- } ;
354+ let mut call = quote ! ( call_site_span =>#dollar_crate:: panic:: #mac!) ;
348355
349356 // Pass the original arguments
350- call. token_trees . push ( tt:: TokenTree :: Subtree ( tt. clone ( ) ) ) ;
357+ let mut subtree = tt. clone ( ) ;
358+ subtree. delimiter = tt:: Delimiter {
359+ open : call_site_span,
360+ close : call_site_span,
361+ kind : tt:: DelimiterKind :: Parenthesis ,
362+ } ;
363+ call. token_trees . push ( tt:: TokenTree :: Subtree ( subtree) ) ;
351364 ExpandResult :: ok ( call)
352365}
353366
@@ -357,20 +370,50 @@ fn unreachable_expand(
357370 tt : & tt:: Subtree ,
358371 span : Span ,
359372) -> ExpandResult < tt:: Subtree > {
360- let loc: MacroCallLoc = db. lookup_intern_macro_call ( id) ;
361- // Expand to a macro call `$crate::panic::unreachable_{edition}`
362373 let dollar_crate = tt:: Ident { text : SmolStr :: new_inline ( "$crate" ) , span } ;
363- let mut call = if db. crate_graph ( ) [ loc. krate ] . edition >= Edition :: Edition2021 {
364- quote ! ( span =>#dollar_crate:: panic:: unreachable_2021!)
374+ let call_site_span = span_with_call_site_ctxt ( db, span, id) ;
375+
376+ let mac = if use_panic_2021 ( db, call_site_span) {
377+ known:: unreachable_2021
365378 } else {
366- quote ! ( span =>#dollar_crate :: panic :: unreachable_2015! )
379+ known :: unreachable_2015
367380 } ;
368381
382+ // Expand to a macro call `$crate::panic::panic_{edition}`
383+ let mut call = quote ! ( call_site_span =>#dollar_crate:: panic:: #mac!) ;
384+
369385 // Pass the original arguments
370- call. token_trees . push ( tt:: TokenTree :: Subtree ( tt. clone ( ) ) ) ;
386+ let mut subtree = tt. clone ( ) ;
387+ subtree. delimiter = tt:: Delimiter {
388+ open : call_site_span,
389+ close : call_site_span,
390+ kind : tt:: DelimiterKind :: Parenthesis ,
391+ } ;
392+ call. token_trees . push ( tt:: TokenTree :: Subtree ( subtree) ) ;
371393 ExpandResult :: ok ( call)
372394}
373395
396+ fn use_panic_2021 ( db : & dyn ExpandDatabase , span : Span ) -> bool {
397+ // To determine the edition, we check the first span up the expansion
398+ // stack that does not have #[allow_internal_unstable(edition_panic)].
399+ // (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.)
400+ loop {
401+ let Some ( expn) = db. lookup_intern_syntax_context ( span. ctx ) . outer_expn else {
402+ break false ;
403+ } ;
404+ let expn = db. lookup_intern_macro_call ( expn) ;
405+ // FIXME: Record allow_internal_unstable in the macro def (not been done yet because it
406+ // would consume quite a bit extra memory for all call locs...)
407+ // if let Some(features) = expn.def.allow_internal_unstable {
408+ // if features.iter().any(|&f| f == sym::edition_panic) {
409+ // span = expn.call_site;
410+ // continue;
411+ // }
412+ // }
413+ break expn. def . edition >= Edition :: Edition2021 ;
414+ }
415+ }
416+
374417fn unquote_str ( lit : & tt:: Literal ) -> Option < String > {
375418 let lit = ast:: make:: tokens:: literal ( & lit. to_string ( ) ) ;
376419 let token = ast:: String :: cast ( lit) ?;
0 commit comments