about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/base-db/src/input.rs1
-rw-r--r--crates/hir-def/src/db.rs17
-rw-r--r--crates/hir-def/src/lib.rs16
-rw-r--r--crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs38
-rw-r--r--crates/hir-def/src/nameres/collector.rs25
-rw-r--r--crates/hir-expand/src/builtin_fn_macro.rs91
-rw-r--r--crates/hir-expand/src/lib.rs3
-rw-r--r--crates/hir-expand/src/name.rs4
-rw-r--r--crates/hir-expand/src/quote.rs7
-rw-r--r--crates/test-utils/src/minicore.rs4
10 files changed, 151 insertions, 55 deletions
diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs
index 4fb204e625e..e45a81238ac 100644
--- a/crates/base-db/src/input.rs
+++ b/crates/base-db/src/input.rs
@@ -363,6 +363,7 @@ pub enum Edition {
 
 impl Edition {
     pub const CURRENT: Edition = Edition::Edition2021;
+    pub const DEFAULT: Edition = Edition::Edition2015;
 }
 
 #[derive(Default, Debug, Clone, PartialEq, Eq)]
diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs
index 901c446465d..91b99abc1ad 100644
--- a/crates/hir-def/src/db.rs
+++ b/crates/hir-def/src/db.rs
@@ -24,9 +24,10 @@ use crate::{
     AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, DefWithBodyId,
     EnumId, EnumLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId,
     FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId, InTypeConstLoc, LocalEnumVariantId,
-    LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, MacroRulesLoc, ProcMacroId,
-    ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId,
-    TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId,
+    LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags,
+    ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId,
+    TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc,
+    VariantId,
 };
 
 #[salsa::query_group(InternDatabaseStorage)]
@@ -338,8 +339,10 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
                 span: db
                     .span_map(loc.id.file_id())
                     .span_for_range(db.ast_id_map(loc.id.file_id()).get(makro.ast_id).text_range()),
+                edition: loc.edition,
             }
         }
+
         MacroId::MacroRulesId(it) => {
             let loc: MacroRulesLoc = it.lookup(db);
 
@@ -348,11 +351,14 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
             MacroDefId {
                 krate: loc.container.krate,
                 kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()),
-                local_inner: loc.local_inner,
-                allow_internal_unsafe: loc.allow_internal_unsafe,
+                local_inner: loc.flags.contains(MacroRulesLocFlags::LOCAL_INNER),
+                allow_internal_unsafe: loc
+                    .flags
+                    .contains(MacroRulesLocFlags::ALLOW_INTERNAL_UNSAFE),
                 span: db
                     .span_map(loc.id.file_id())
                     .span_for_range(db.ast_id_map(loc.id.file_id()).get(makro.ast_id).text_range()),
+                edition: loc.edition,
             }
         }
         MacroId::ProcMacroId(it) => {
@@ -372,6 +378,7 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
                 span: db
                     .span_map(loc.id.file_id())
                     .span_for_range(db.ast_id_map(loc.id.file_id()).get(makro.ast_id).text_range()),
+                edition: loc.edition,
             }
         }
     }
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index 37f96df2699..22ba3aab4e9 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -63,7 +63,7 @@ use std::{
     panic::{RefUnwindSafe, UnwindSafe},
 };
 
-use base_db::{impl_intern_key, salsa, CrateId};
+use base_db::{impl_intern_key, salsa, CrateId, Edition};
 use hir_expand::{
     ast_id_map::{AstIdNode, FileAstId},
     attrs::{Attr, AttrId, AttrInput},
@@ -369,6 +369,7 @@ pub struct Macro2Loc {
     pub id: ItemTreeId<Macro2>,
     pub expander: MacroExpander,
     pub allow_internal_unsafe: bool,
+    pub edition: Edition,
 }
 impl_intern!(Macro2Id, Macro2Loc, intern_macro2, lookup_intern_macro2);
 
@@ -379,11 +380,19 @@ pub struct MacroRulesLoc {
     pub container: ModuleId,
     pub id: ItemTreeId<MacroRules>,
     pub expander: MacroExpander,
-    pub allow_internal_unsafe: bool,
-    pub local_inner: bool,
+    pub flags: MacroRulesLocFlags,
+    pub edition: Edition,
 }
 impl_intern!(MacroRulesId, MacroRulesLoc, intern_macro_rules, lookup_intern_macro_rules);
 
+bitflags::bitflags! {
+    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+    pub struct MacroRulesLocFlags: u8 {
+        const ALLOW_INTERNAL_UNSAFE = 1 << 0;
+        const LOCAL_INNER = 1 << 1;
+    }
+}
+
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
 pub struct ProcMacroId(salsa::InternId);
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -392,6 +401,7 @@ pub struct ProcMacroLoc {
     pub id: ItemTreeId<Function>,
     pub expander: CustomProcMacroExpander,
     pub kind: ProcMacroKind,
+    pub edition: Edition,
 }
 impl_intern!(ProcMacroId, ProcMacroLoc, intern_proc_macro, lookup_intern_proc_macro);
 
diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index 514219ee715..d4798f4507d 100644
--- a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -163,31 +163,43 @@ fn main() { ""; }
 fn test_assert_expand() {
     check(
         r#"
-#[rustc_builtin_macro]
-macro_rules! assert {
-    ($cond:expr) => ({ /* compiler built-in */ });
-    ($cond:expr, $($args:tt)*) => ({ /* compiler built-in */ })
-}
-
+//- minicore: assert
 fn main() {
     assert!(true, "{} {:?}", arg1(a, b, c), arg2);
 }
 "#,
-        expect![[r##"
-#[rustc_builtin_macro]
-macro_rules! assert {
-    ($cond:expr) => ({ /* compiler built-in */ });
-    ($cond:expr, $($args:tt)*) => ({ /* compiler built-in */ })
+        expect![[r#"
+fn main() {
+     {
+        if !(true ) {
+            $crate::panic::panic_2021!("{} {:?}", arg1(a, b, c), arg2);
+        }
+    };
+}
+"#]],
+    );
 }
 
+// FIXME: This is the wrong expansion, see FIXME on `builtin_fn_macro::use_panic_2021`
+#[test]
+fn test_assert_expand_2015() {
+    check(
+        r#"
+//- minicore: assert
+//- /main.rs edition:2015
+fn main() {
+    assert!(true, "{} {:?}", arg1(a, b, c), arg2);
+}
+"#,
+        expect![[r#"
 fn main() {
      {
         if !(true ) {
-            $crate::panic!("{} {:?}", arg1(a, b, c), arg2);
+            $crate::panic::panic_2021!("{} {:?}", arg1(a, b, c), arg2);
         }
     };
 }
-"##]],
+"#]],
     );
 }
 
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 090d8348390..3763bfcbcfa 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -54,8 +54,9 @@ use crate::{
     AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantId,
     ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern,
     ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId,
-    MacroRulesId, MacroRulesLoc, ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc,
-    StructLoc, TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseId, UseLoc,
+    MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId,
+    ProcMacroLoc, StaticLoc, StructLoc, TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc,
+    UnresolvedMacro, UseId, UseLoc,
 };
 
 static GLOB_RECURSION_LIMIT: Limit = Limit::new(100);
@@ -614,9 +615,14 @@ impl DefCollector<'_> {
                 _ => (CustomProcMacroExpander::dummy(), kind),
             };
 
-        let proc_macro_id =
-            ProcMacroLoc { container: self.def_map.crate_root(), id, expander, kind }
-                .intern(self.db);
+        let proc_macro_id = ProcMacroLoc {
+            container: self.def_map.crate_root(),
+            id,
+            expander,
+            kind,
+            edition: self.def_map.data.edition,
+        }
+        .intern(self.db);
         self.define_proc_macro(def.name.clone(), proc_macro_id);
         let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap();
         if let ProcMacroKind::CustomDerive { helpers } = def.kind {
@@ -2138,12 +2144,16 @@ impl ModCollector<'_, '_> {
         };
         let allow_internal_unsafe = attrs.by_key("allow_internal_unsafe").exists();
 
+        let mut flags = MacroRulesLocFlags::empty();
+        flags.set(MacroRulesLocFlags::LOCAL_INNER, local_inner);
+        flags.set(MacroRulesLocFlags::ALLOW_INTERNAL_UNSAFE, allow_internal_unsafe);
+
         let macro_id = MacroRulesLoc {
             container: module,
             id: ItemTreeId::new(self.tree_id, id),
-            local_inner,
-            allow_internal_unsafe,
+            flags,
             expander,
+            edition: self.def_collector.def_map.data.edition,
         }
         .intern(self.def_collector.db);
         self.def_collector.define_macro_rules(
@@ -2209,6 +2219,7 @@ impl ModCollector<'_, '_> {
             id: ItemTreeId::new(self.tree_id, id),
             expander,
             allow_internal_unsafe,
+            edition: self.def_collector.def_map.data.edition,
         }
         .intern(self.def_collector.db);
         self.def_collector.define_macro_def(
diff --git a/crates/hir-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs
index 2d7531d56d0..0475a0f4acc 100644
--- a/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/crates/hir-expand/src/builtin_fn_macro.rs
@@ -13,10 +13,11 @@ use syntax::{
 
 use crate::{
     db::ExpandDatabase,
-    hygiene::span_with_def_site_ctxt,
-    name, quote,
+    hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt},
+    name::{self, known},
+    quote,
     tt::{self, DelimSpan},
-    ExpandError, ExpandResult, HirFileIdExt, MacroCallId, MacroCallLoc,
+    ExpandError, ExpandResult, HirFileIdExt, MacroCallId,
 };
 
 macro_rules! register_builtin {
@@ -196,32 +197,38 @@ fn stringify_expand(
 }
 
 fn assert_expand(
-    _db: &dyn ExpandDatabase,
-    _id: MacroCallId,
+    db: &dyn ExpandDatabase,
+    id: MacroCallId,
     tt: &tt::Subtree,
     span: Span,
 ) -> ExpandResult<tt::Subtree> {
-    let args = parse_exprs_with_sep(tt, ',', span);
+    let call_site_span = span_with_call_site_ctxt(db, span, id);
+    let args = parse_exprs_with_sep(tt, ',', call_site_span);
     let dollar_crate = tt::Ident { text: SmolStr::new_inline("$crate"), span };
     let expanded = match &*args {
         [cond, panic_args @ ..] => {
             let comma = tt::Subtree {
-                delimiter: tt::Delimiter::invisible_spanned(span),
+                delimiter: tt::Delimiter::invisible_spanned(call_site_span),
                 token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct {
                     char: ',',
                     spacing: tt::Spacing::Alone,
-                    span,
+                    span: call_site_span,
                 }))],
             };
             let cond = cond.clone();
             let panic_args = itertools::Itertools::intersperse(panic_args.iter().cloned(), comma);
-            quote! {span =>{
+            let mac = if use_panic_2021(db, span) {
+                quote! {call_site_span => #dollar_crate::panic::panic_2021!(##panic_args) }
+            } else {
+                quote! {call_site_span => #dollar_crate::panic!(##panic_args) }
+            };
+            quote! {call_site_span =>{
                 if !(#cond) {
-                    #dollar_crate::panic!(##panic_args);
+                    #mac;
                 }
             }}
         }
-        [] => quote! {span =>{}},
+        [] => quote! {call_site_span =>{}},
     };
 
     ExpandResult::ok(expanded)
@@ -337,17 +344,23 @@ fn panic_expand(
     tt: &tt::Subtree,
     span: Span,
 ) -> ExpandResult<tt::Subtree> {
-    let loc: MacroCallLoc = db.lookup_intern_macro_call(id);
     let dollar_crate = tt::Ident { text: SmolStr::new_inline("$crate"), span };
+    let call_site_span = span_with_call_site_ctxt(db, span, id);
+
+    let mac =
+        if use_panic_2021(db, call_site_span) { known::panic_2021 } else { known::panic_2015 };
+
     // Expand to a macro call `$crate::panic::panic_{edition}`
-    let mut call = if db.crate_graph()[loc.krate].edition >= Edition::Edition2021 {
-        quote!(span =>#dollar_crate::panic::panic_2021!)
-    } else {
-        quote!(span =>#dollar_crate::panic::panic_2015!)
-    };
+    let mut call = quote!(call_site_span =>#dollar_crate::panic::#mac!);
 
     // Pass the original arguments
-    call.token_trees.push(tt::TokenTree::Subtree(tt.clone()));
+    let mut subtree = tt.clone();
+    subtree.delimiter = tt::Delimiter {
+        open: call_site_span,
+        close: call_site_span,
+        kind: tt::DelimiterKind::Parenthesis,
+    };
+    call.token_trees.push(tt::TokenTree::Subtree(subtree));
     ExpandResult::ok(call)
 }
 
@@ -357,20 +370,50 @@ fn unreachable_expand(
     tt: &tt::Subtree,
     span: Span,
 ) -> ExpandResult<tt::Subtree> {
-    let loc: MacroCallLoc = db.lookup_intern_macro_call(id);
-    // Expand to a macro call `$crate::panic::unreachable_{edition}`
     let dollar_crate = tt::Ident { text: SmolStr::new_inline("$crate"), span };
-    let mut call = if db.crate_graph()[loc.krate].edition >= Edition::Edition2021 {
-        quote!(span =>#dollar_crate::panic::unreachable_2021!)
+    let call_site_span = span_with_call_site_ctxt(db, span, id);
+
+    let mac = if use_panic_2021(db, call_site_span) {
+        known::unreachable_2021
     } else {
-        quote!(span =>#dollar_crate::panic::unreachable_2015!)
+        known::unreachable_2015
     };
 
+    // Expand to a macro call `$crate::panic::panic_{edition}`
+    let mut call = quote!(call_site_span =>#dollar_crate::panic::#mac!);
+
     // Pass the original arguments
-    call.token_trees.push(tt::TokenTree::Subtree(tt.clone()));
+    let mut subtree = tt.clone();
+    subtree.delimiter = tt::Delimiter {
+        open: call_site_span,
+        close: call_site_span,
+        kind: tt::DelimiterKind::Parenthesis,
+    };
+    call.token_trees.push(tt::TokenTree::Subtree(subtree));
     ExpandResult::ok(call)
 }
 
+fn use_panic_2021(db: &dyn ExpandDatabase, span: Span) -> bool {
+    // To determine the edition, we check the first span up the expansion
+    // stack that does not have #[allow_internal_unstable(edition_panic)].
+    // (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.)
+    loop {
+        let Some(expn) = db.lookup_intern_syntax_context(span.ctx).outer_expn else {
+            break false;
+        };
+        let expn = db.lookup_intern_macro_call(expn);
+        // FIXME: Record allow_internal_unstable in the macro def (not been done yet because it
+        // would consume quite a bit extra memory for all call locs...)
+        // if let Some(features) = expn.def.allow_internal_unstable {
+        //     if features.iter().any(|&f| f == sym::edition_panic) {
+        //         span = expn.call_site;
+        //         continue;
+        //     }
+        // }
+        break expn.def.edition >= Edition::Edition2021;
+    }
+}
+
 fn unquote_str(lit: &tt::Literal) -> Option<String> {
     let lit = ast::make::tokens::literal(&lit.to_string());
     let token = ast::String::cast(lit)?;
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index 3df62aefaad..b5197d4c25d 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -28,7 +28,7 @@ use triomphe::Arc;
 
 use std::{fmt, hash::Hash};
 
-use base_db::{CrateId, FileId};
+use base_db::{CrateId, Edition, FileId};
 use either::Either;
 use span::{FileRange, HirFileIdRepr, Span, SyntaxContextId};
 use syntax::{
@@ -176,6 +176,7 @@ pub struct MacroCallLoc {
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct MacroDefId {
     pub krate: CrateId,
+    pub edition: Edition,
     pub kind: MacroDefKind,
     pub local_inner: bool,
     pub allow_internal_unsafe: bool,
diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs
index a321f94cd75..d122938e8e5 100644
--- a/crates/hir-expand/src/name.rs
+++ b/crates/hir-expand/src/name.rs
@@ -318,6 +318,10 @@ pub mod known {
         new_lower_hex,
         new_upper_hex,
         from_usize,
+        panic_2015,
+        panic_2021,
+        unreachable_2015,
+        unreachable_2021,
         // Components of known path (type name)
         Iterator,
         IntoIterator,
diff --git a/crates/hir-expand/src/quote.rs b/crates/hir-expand/src/quote.rs
index 7c247246906..9bdd75f9d22 100644
--- a/crates/hir-expand/src/quote.rs
+++ b/crates/hir-expand/src/quote.rs
@@ -2,6 +2,8 @@
 
 use span::Span;
 
+use crate::name::Name;
+
 // A helper macro quote macro
 // FIXME:
 // 1. Not all puncts are handled
@@ -180,7 +182,7 @@ impl ToTokenTree for crate::tt::Subtree {
 }
 
 macro_rules! impl_to_to_tokentrees {
-    ($($span:ident: $ty:ty => $this:ident $im:block);*) => {
+    ($($span:ident: $ty:ty => $this:ident $im:block;)*) => {
         $(
             impl ToTokenTree for $ty {
                 fn to_token($this, $span: Span) -> crate::tt::TokenTree {
@@ -209,7 +211,8 @@ impl_to_to_tokentrees! {
     _span: crate::tt::Ident => self { self };
     _span: crate::tt::Punct => self { self };
     span: &str => self { crate::tt::Literal{text: format!("\"{}\"", self.escape_default()).into(), span}};
-    span: String => self { crate::tt::Literal{text: format!("\"{}\"", self.escape_default()).into(), span}}
+    span: String => self { crate::tt::Literal{text: format!("\"{}\"", self.escape_default()).into(), span}};
+    span: Name => self { crate::tt::Ident{text: self.to_smol_str(), span}};
 }
 
 #[cfg(test)]
diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs
index f766747d707..1f3136404c6 100644
--- a/crates/test-utils/src/minicore.rs
+++ b/crates/test-utils/src/minicore.rs
@@ -1381,6 +1381,7 @@ mod macros {
     // region:assert
     #[macro_export]
     #[rustc_builtin_macro]
+    #[allow_internal_unstable(core_panic, edition_panic, generic_assert_internals)]
     macro_rules! assert {
         ($($arg:tt)*) => {
             /* compiler built-in */
@@ -1389,6 +1390,7 @@ mod macros {
     // endregion:assert
 
     // region:fmt
+    #[allow_internal_unstable(fmt_internals, const_fmt_arguments_new)]
     #[macro_export]
     #[rustc_builtin_macro]
     macro_rules! const_format_args {
@@ -1396,6 +1398,7 @@ mod macros {
         ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }};
     }
 
+    #[allow_internal_unstable(fmt_internals)]
     #[macro_export]
     #[rustc_builtin_macro]
     macro_rules! format_args {
@@ -1403,6 +1406,7 @@ mod macros {
         ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }};
     }
 
+    #[allow_internal_unstable(fmt_internals)]
     #[macro_export]
     #[rustc_builtin_macro]
     macro_rules! format_args_nl {