about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-def/src/data/adt.rs10
-rw-r--r--crates/hir-def/src/expander.rs31
-rw-r--r--crates/hir-def/src/find_path.rs6
-rw-r--r--crates/hir-def/src/hir/type_ref.rs5
-rw-r--r--crates/hir-def/src/item_tree.rs20
-rw-r--r--crates/hir-def/src/item_tree/lower.rs40
-rw-r--r--crates/hir-def/src/lib.rs7
-rw-r--r--crates/hir-def/src/lower.rs37
-rw-r--r--crates/hir-def/src/visibility.rs21
-rw-r--r--crates/hir-expand/src/attrs.rs6
-rw-r--r--crates/hir-expand/src/eager.rs8
-rw-r--r--crates/hir-expand/src/mod_path.rs18
-rw-r--r--crates/hir-ty/src/display.rs5
-rw-r--r--crates/hir/src/semantics.rs7
-rw-r--r--crates/hir/src/source_analyzer.rs4
-rw-r--r--crates/span/src/ast_id.rs14
16 files changed, 125 insertions, 114 deletions
diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs
index f07b1257662..5790e600f63 100644
--- a/crates/hir-def/src/data/adt.rs
+++ b/crates/hir-def/src/data/adt.rs
@@ -400,7 +400,7 @@ pub(crate) fn lower_struct(
     item_tree: &ItemTree,
     fields: &Fields,
 ) -> StructKind {
-    let ctx = LowerCtx::with_file_id(db, ast.file_id);
+    let ctx = LowerCtx::new(db, ast.file_id);
 
     match (&ast.value, fields) {
         (ast::StructKind::Tuple(fl), Fields::Tuple(fields)) => {
@@ -415,7 +415,9 @@ pub(crate) fn lower_struct(
                     || FieldData {
                         name: Name::new_tuple_field(i),
                         type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
-                        visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
+                        visibility: RawVisibility::from_ast(db, fd.visibility(), &mut |range| {
+                            ctx.span_map().span_for_range(range).ctx
+                        }),
                     },
                 );
             }
@@ -433,7 +435,9 @@ pub(crate) fn lower_struct(
                     || FieldData {
                         name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
                         type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
-                        visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
+                        visibility: RawVisibility::from_ast(db, fd.visibility(), &mut |range| {
+                            ctx.span_map().span_for_range(range).ctx
+                        }),
                     },
                 );
             }
diff --git a/crates/hir-def/src/expander.rs b/crates/hir-def/src/expander.rs
index b99df1ed593..b0872fcdc0e 100644
--- a/crates/hir-def/src/expander.rs
+++ b/crates/hir-def/src/expander.rs
@@ -1,5 +1,7 @@
 //! Macro expansion utilities.
 
+use std::cell::OnceCell;
+
 use base_db::CrateId;
 use cfg::CfgOptions;
 use drop_bomb::DropBomb;
@@ -18,7 +20,7 @@ use crate::{
 #[derive(Debug)]
 pub struct Expander {
     cfg_options: CfgOptions,
-    span_map: SpanMap,
+    span_map: OnceCell<SpanMap>,
     krate: CrateId,
     current_file_id: HirFileId,
     pub(crate) module: ModuleId,
@@ -42,7 +44,7 @@ impl Expander {
             recursion_depth: 0,
             recursion_limit,
             cfg_options: db.crate_graph()[module.krate].cfg_options.clone(),
-            span_map: db.span_map(current_file_id),
+            span_map: OnceCell::new(),
             krate: module.krate,
         }
     }
@@ -100,7 +102,7 @@ impl Expander {
     }
 
     pub fn ctx<'a>(&self, db: &'a dyn DefDatabase) -> LowerCtx<'a> {
-        LowerCtx::new(db, self.span_map.clone(), self.current_file_id)
+        LowerCtx::with_span_map_cell(db, self.current_file_id, self.span_map.clone())
     }
 
     pub(crate) fn in_file<T>(&self, value: T) -> InFile<T> {
@@ -108,7 +110,15 @@ impl Expander {
     }
 
     pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::HasAttrs) -> Attrs {
-        Attrs::filter(db, self.krate, RawAttrs::new(db.upcast(), owner, self.span_map.as_ref()))
+        Attrs::filter(
+            db,
+            self.krate,
+            RawAttrs::new(
+                db.upcast(),
+                owner,
+                self.span_map.get_or_init(|| db.span_map(self.current_file_id)).as_ref(),
+            ),
+        )
     }
 
     pub(crate) fn cfg_options(&self) -> &CfgOptions {
@@ -120,7 +130,7 @@ impl Expander {
     }
 
     pub(crate) fn parse_path(&mut self, db: &dyn DefDatabase, path: ast::Path) -> Option<Path> {
-        let ctx = LowerCtx::new(db, self.span_map.clone(), self.current_file_id);
+        let ctx = LowerCtx::with_span_map_cell(db, self.current_file_id, self.span_map.clone());
         Path::from_src(&ctx, path)
     }
 
@@ -165,10 +175,11 @@ impl Expander {
                     let parse = res.value.0.cast::<T>()?;
 
                     self.recursion_depth += 1;
-                    let old_span_map = std::mem::replace(
-                        &mut self.span_map,
-                        SpanMap::ExpansionSpanMap(res.value.1),
-                    );
+                    let old_span_map = OnceCell::new();
+                    if let Some(prev) = self.span_map.take() {
+                        _ = old_span_map.set(prev);
+                    };
+                    _ = self.span_map.set(SpanMap::ExpansionSpanMap(res.value.1));
                     let old_file_id =
                         std::mem::replace(&mut self.current_file_id, macro_file.into());
                     let mark = Mark {
@@ -187,6 +198,6 @@ impl Expander {
 #[derive(Debug)]
 pub struct Mark {
     file_id: HirFileId,
-    span_map: SpanMap,
+    span_map: OnceCell<SpanMap>,
     bomb: DropBomb,
 }
diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs
index 26247ba5b50..0cd4a5db8c3 100644
--- a/crates/hir-def/src/find_path.rs
+++ b/crates/hir-def/src/find_path.rs
@@ -611,8 +611,10 @@ mod tests {
         let parsed_path_file = syntax::SourceFile::parse(&format!("use {path};"));
         let ast_path =
             parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap();
-        let mod_path =
-            ModPath::from_src(&db, ast_path, db.span_map(pos.file_id.into()).as_ref()).unwrap();
+        let mod_path = ModPath::from_src(&db, ast_path, &mut |range| {
+            db.span_map(pos.file_id.into()).as_ref().span_for_range(range).ctx
+        })
+        .unwrap();
 
         let def_map = module.def_map(&db);
         let resolved = def_map
diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs
index 8db00f9d76e..ec207a7f965 100644
--- a/crates/hir-def/src/hir/type_ref.rs
+++ b/crates/hir-def/src/hir/type_ref.rs
@@ -251,7 +251,7 @@ impl TypeRef {
                 TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
             }
             ast::Type::MacroType(mt) => match mt.macro_call() {
-                Some(mc) => ctx.ast_id(&mc).map(TypeRef::Macro).unwrap_or(TypeRef::Error),
+                Some(mc) => TypeRef::Macro(ctx.ast_id(&mc)),
                 None => TypeRef::Error,
             },
         }
@@ -398,9 +398,8 @@ pub enum ConstRef {
 impl ConstRef {
     pub(crate) fn from_const_arg(lower_ctx: &LowerCtx<'_>, arg: Option<ast::ConstArg>) -> Self {
         if let Some(arg) = arg {
-            let ast_id = lower_ctx.ast_id(&arg);
             if let Some(expr) = arg.expr() {
-                return Self::from_expr(expr, ast_id);
+                return Self::from_expr(expr, Some(lower_ctx.ast_id(&arg)));
             }
         }
         Self::Scalar(LiteralConstRef::Unknown)
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 179da788d33..bd3d377ec08 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -29,9 +29,6 @@
 //!
 //! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its
 //! surface syntax.
-//!
-//! Note that we cannot store [`span::Span`]s inside of this, as typing in an item invalidates its
-//! encompassing span!
 
 mod lower;
 mod pretty;
@@ -824,11 +821,13 @@ impl Use {
         // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
         let ast = InFile::new(file_id, self.ast_id).to_node(db.upcast());
         let ast_use_tree = ast.use_tree().expect("missing `use_tree`");
-        let span_map = db.span_map(file_id);
-        let (_, source_map) = lower::lower_use_tree(db, span_map.as_ref(), ast_use_tree)
-            .expect("failed to lower use tree");
+        let (_, source_map) = lower::lower_use_tree(db, ast_use_tree, &mut |range| {
+            db.span_map(file_id).span_for_range(range).ctx
+        })
+        .expect("failed to lower use tree");
         source_map[index].clone()
     }
+
     /// Maps a `UseTree` contained in this import back to its AST node.
     pub fn use_tree_source_map(
         &self,
@@ -839,10 +838,11 @@ impl Use {
         // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
         let ast = InFile::new(file_id, self.ast_id).to_node(db.upcast());
         let ast_use_tree = ast.use_tree().expect("missing `use_tree`");
-        let span_map = db.span_map(file_id);
-        lower::lower_use_tree(db, span_map.as_ref(), ast_use_tree)
-            .expect("failed to lower use tree")
-            .1
+        lower::lower_use_tree(db, ast_use_tree, &mut |range| {
+            db.span_map(file_id).span_for_range(range).ctx
+        })
+        .expect("failed to lower use tree")
+        .1
     }
 }
 
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index 21cffafa952..bf3d54f4caf 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -4,7 +4,7 @@ use std::collections::hash_map::Entry;
 
 use hir_expand::{mod_path::path, name, name::AsName, span_map::SpanMapRef, HirFileId};
 use la_arena::Arena;
-use span::AstIdMap;
+use span::{AstIdMap, SyntaxContextId};
 use syntax::{
     ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString},
     AstNode,
@@ -45,7 +45,7 @@ impl<'a> Ctx<'a> {
             db,
             tree: ItemTree::default(),
             source_ast_id_map: db.ast_id_map(file),
-            body_ctx: crate::lower::LowerCtx::with_file_id(db, file),
+            body_ctx: crate::lower::LowerCtx::new(db, file),
         }
     }
 
@@ -535,7 +535,9 @@ impl<'a> Ctx<'a> {
     fn lower_use(&mut self, use_item: &ast::Use) -> Option<FileItemTreeId<Use>> {
         let visibility = self.lower_visibility(use_item);
         let ast_id = self.source_ast_id_map.ast_id(use_item);
-        let (use_tree, _) = lower_use_tree(self.db, self.span_map(), use_item.use_tree()?)?;
+        let (use_tree, _) = lower_use_tree(self.db, use_item.use_tree()?, &mut |range| {
+            self.span_map().span_for_range(range).ctx
+        })?;
 
         let res = Use { visibility, ast_id, use_tree };
         Some(id(self.data().uses.alloc(res)))
@@ -558,7 +560,9 @@ impl<'a> Ctx<'a> {
 
     fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
         let span_map = self.span_map();
-        let path = Interned::new(ModPath::from_src(self.db.upcast(), m.path()?, span_map)?);
+        let path = Interned::new(ModPath::from_src(self.db.upcast(), m.path()?, &mut |range| {
+            span_map.span_for_range(range).ctx
+        })?);
         let ast_id = self.source_ast_id_map.ast_id(m);
         let expand_to = hir_expand::ExpandTo::from_call_site(m);
         let res = MacroCall {
@@ -672,8 +676,9 @@ impl<'a> Ctx<'a> {
     }
 
     fn lower_visibility(&mut self, item: &dyn ast::HasVisibility) -> RawVisibilityId {
-        let vis =
-            RawVisibility::from_opt_ast_with_span_map(self.db, item.visibility(), self.span_map());
+        let vis = RawVisibility::from_ast(self.db, item.visibility(), &mut |range| {
+            self.span_map().span_for_range(range).ctx
+        });
         self.data().vis.alloc(vis)
     }
 
@@ -745,12 +750,15 @@ fn lower_abi(abi: ast::Abi) -> Interned<str> {
 
 struct UseTreeLowering<'a> {
     db: &'a dyn DefDatabase,
-    span_map: SpanMapRef<'a>,
     mapping: Arena<ast::UseTree>,
 }
 
 impl UseTreeLowering<'_> {
-    fn lower_use_tree(&mut self, tree: ast::UseTree) -> Option<UseTree> {
+    fn lower_use_tree(
+        &mut self,
+        tree: ast::UseTree,
+        span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
+    ) -> Option<UseTree> {
         if let Some(use_tree_list) = tree.use_tree_list() {
             let prefix = match tree.path() {
                 // E.g. use something::{{{inner}}};
@@ -758,15 +766,17 @@ impl UseTreeLowering<'_> {
                 // E.g. `use something::{inner}` (prefix is `None`, path is `something`)
                 // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
                 Some(path) => {
-                    match ModPath::from_src(self.db.upcast(), path, self.span_map) {
+                    match ModPath::from_src(self.db.upcast(), path, span_for_range) {
                         Some(it) => Some(it),
                         None => return None, // FIXME: report errors somewhere
                     }
                 }
             };
 
-            let list =
-                use_tree_list.use_trees().filter_map(|tree| self.lower_use_tree(tree)).collect();
+            let list = use_tree_list
+                .use_trees()
+                .filter_map(|tree| self.lower_use_tree(tree, span_for_range))
+                .collect();
 
             Some(
                 self.use_tree(
@@ -777,7 +787,7 @@ impl UseTreeLowering<'_> {
         } else {
             let is_glob = tree.star_token().is_some();
             let path = match tree.path() {
-                Some(path) => Some(ModPath::from_src(self.db.upcast(), path, self.span_map)?),
+                Some(path) => Some(ModPath::from_src(self.db.upcast(), path, span_for_range)?),
                 None => None,
             };
             let alias = tree.rename().map(|a| {
@@ -813,10 +823,10 @@ impl UseTreeLowering<'_> {
 
 pub(crate) fn lower_use_tree(
     db: &dyn DefDatabase,
-    span_map: SpanMapRef<'_>,
     tree: ast::UseTree,
+    span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
 ) -> Option<(UseTree, Arena<ast::UseTree>)> {
-    let mut lowering = UseTreeLowering { db, span_map, mapping: Arena::new() };
-    let tree = lowering.lower_use_tree(tree)?;
+    let mut lowering = UseTreeLowering { db, mapping: Arena::new() };
+    let tree = lowering.lower_use_tree(tree, span_for_range)?;
     Some((tree, lowering.mapping))
 }
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index de3ab57a124..d63f2268aa4 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -1341,8 +1341,11 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
         let expands_to = hir_expand::ExpandTo::from_call_site(self.value);
         let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
         let span_map = db.span_map(self.file_id);
-        let path =
-            self.value.path().and_then(|path| path::ModPath::from_src(db, path, span_map.as_ref()));
+        let path = self.value.path().and_then(|path| {
+            path::ModPath::from_src(db, path, &mut |range| {
+                span_map.as_ref().span_for_range(range).ctx
+            })
+        });
 
         let Some(path) = path else {
             return Ok(ExpandResult::only_err(ExpandError::other("malformed macro invocation")));
diff --git a/crates/hir-def/src/lower.rs b/crates/hir-def/src/lower.rs
index 2fa6acdf175..d574d80a8e0 100644
--- a/crates/hir-def/src/lower.rs
+++ b/crates/hir-def/src/lower.rs
@@ -13,39 +13,36 @@ use crate::{db::DefDatabase, path::Path};
 
 pub struct LowerCtx<'a> {
     pub db: &'a dyn DefDatabase,
-    span_map: SpanMap,
-    // FIXME: This optimization is probably pointless, ast id map should pretty much always exist anyways.
-    ast_id_map: Option<(HirFileId, OnceCell<Arc<AstIdMap>>)>,
+    file_id: HirFileId,
+    span_map: OnceCell<SpanMap>,
+    ast_id_map: OnceCell<Arc<AstIdMap>>,
 }
 
 impl<'a> LowerCtx<'a> {
-    pub fn new(db: &'a dyn DefDatabase, span_map: SpanMap, file_id: HirFileId) -> Self {
-        LowerCtx { db, span_map, ast_id_map: Some((file_id, OnceCell::new())) }
+    pub fn new(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
+        LowerCtx { db, file_id, span_map: OnceCell::new(), ast_id_map: OnceCell::new() }
     }
 
-    pub fn with_file_id(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
-        LowerCtx {
-            db,
-            span_map: db.span_map(file_id),
-            ast_id_map: Some((file_id, OnceCell::new())),
-        }
-    }
-
-    pub fn with_span_map(db: &'a dyn DefDatabase, span_map: SpanMap) -> Self {
-        LowerCtx { db, span_map, ast_id_map: None }
+    pub fn with_span_map_cell(
+        db: &'a dyn DefDatabase,
+        file_id: HirFileId,
+        span_map: OnceCell<SpanMap>,
+    ) -> Self {
+        LowerCtx { db, file_id, span_map, ast_id_map: OnceCell::new() }
     }
 
     pub(crate) fn span_map(&self) -> SpanMapRef<'_> {
-        self.span_map.as_ref()
+        self.span_map.get_or_init(|| self.db.span_map(self.file_id)).as_ref()
     }
 
     pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> {
         Path::from_src(self, ast)
     }
 
-    pub(crate) fn ast_id<N: AstIdNode>(&self, item: &N) -> Option<AstId<N>> {
-        let &(file_id, ref ast_id_map) = self.ast_id_map.as_ref()?;
-        let ast_id_map = ast_id_map.get_or_init(|| self.db.ast_id_map(file_id));
-        Some(InFile::new(file_id, ast_id_map.ast_id(item)))
+    pub(crate) fn ast_id<N: AstIdNode>(&self, item: &N) -> AstId<N> {
+        InFile::new(
+            self.file_id,
+            self.ast_id_map.get_or_init(|| self.db.ast_id_map(self.file_id)).ast_id(item),
+        )
     }
 }
diff --git a/crates/hir-def/src/visibility.rs b/crates/hir-def/src/visibility.rs
index 0f3fac1cecd..1ef8fa772a1 100644
--- a/crates/hir-def/src/visibility.rs
+++ b/crates/hir-def/src/visibility.rs
@@ -2,8 +2,8 @@
 
 use std::iter;
 
-use hir_expand::{span_map::SpanMapRef, InFile};
 use la_arena::ArenaMap;
+use span::SyntaxContextId;
 use syntax::ast;
 use triomphe::Arc;
 
@@ -35,35 +35,24 @@ impl RawVisibility {
 
     pub(crate) fn from_ast(
         db: &dyn DefDatabase,
-        node: InFile<Option<ast::Visibility>>,
-    ) -> RawVisibility {
-        let node = match node.transpose() {
-            None => return RawVisibility::private(),
-            Some(node) => node,
-        };
-        Self::from_ast_with_span_map(db, node.value, db.span_map(node.file_id).as_ref())
-    }
-
-    pub(crate) fn from_opt_ast_with_span_map(
-        db: &dyn DefDatabase,
         node: Option<ast::Visibility>,
-        span_map: SpanMapRef<'_>,
+        span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
     ) -> RawVisibility {
         let node = match node {
             None => return RawVisibility::private(),
             Some(node) => node,
         };
-        Self::from_ast_with_span_map(db, node, span_map)
+        Self::from_ast_with_span_map(db, node, span_for_range)
     }
 
     fn from_ast_with_span_map(
         db: &dyn DefDatabase,
         node: ast::Visibility,
-        span_map: SpanMapRef<'_>,
+        span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
     ) -> RawVisibility {
         let path = match node.kind() {
             ast::VisibilityKind::In(path) => {
-                let path = ModPath::from_src(db.upcast(), path, span_map);
+                let path = ModPath::from_src(db.upcast(), path, span_for_range);
                 match path {
                     None => return RawVisibility::private(),
                     Some(path) => path,
diff --git a/crates/hir-expand/src/attrs.rs b/crates/hir-expand/src/attrs.rs
index 1c92dea38e6..7793e995323 100644
--- a/crates/hir-expand/src/attrs.rs
+++ b/crates/hir-expand/src/attrs.rs
@@ -90,7 +90,7 @@ impl RawAttrs {
     }
 
     /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
-    // FIXME: This should return a different type
+    // FIXME: This should return a different type, signaling it was filtered?
     pub fn filter(self, db: &dyn ExpandDatabase, krate: CrateId) -> RawAttrs {
         let has_cfg_attrs = self
             .iter()
@@ -201,7 +201,9 @@ impl Attr {
         span_map: SpanMapRef<'_>,
         id: AttrId,
     ) -> Option<Attr> {
-        let path = Interned::new(ModPath::from_src(db, ast.path()?, span_map)?);
+        let path = Interned::new(ModPath::from_src(db, ast.path()?, &mut |range| {
+            span_map.span_for_range(range).ctx
+        })?);
         let span = span_map.span_for_range(ast.syntax().text_range());
         let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
             let value = match lit.kind() {
diff --git a/crates/hir-expand/src/eager.rs b/crates/hir-expand/src/eager.rs
index da85c2ec7ac..5337a5bb028 100644
--- a/crates/hir-expand/src/eager.rs
+++ b/crates/hir-expand/src/eager.rs
@@ -27,7 +27,6 @@ use crate::{
     ast::{self, AstNode},
     db::ExpandDatabase,
     mod_path::ModPath,
-    span_map::SpanMapRef,
     EagerCallInfo, ExpandError, ExpandResult, ExpandTo, ExpansionSpanMap, InFile, Intern,
     MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind,
 };
@@ -155,10 +154,9 @@ fn eager_macro_recur(
             }
         };
 
-        let def = match call
-            .path()
-            .and_then(|path| ModPath::from_src(db, path, SpanMapRef::ExpansionSpanMap(span_map)))
-        {
+        let def = match call.path().and_then(|path| {
+            ModPath::from_src(db, path, &mut |range| span_map.span_at(range.start()).ctx)
+        }) {
             Some(path) => match macro_resolver(path.clone()) {
                 Some(def) => def,
                 None => {
diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs
index ae10ad2f801..fc186d2c26d 100644
--- a/crates/hir-expand/src/mod_path.rs
+++ b/crates/hir-expand/src/mod_path.rs
@@ -9,7 +9,6 @@ use crate::{
     db::ExpandDatabase,
     hygiene::{marks_rev, SyntaxContextExt, Transparency},
     name::{known, AsName, Name},
-    span_map::SpanMapRef,
     tt,
 };
 use base_db::CrateId;
@@ -49,9 +48,9 @@ impl ModPath {
     pub fn from_src(
         db: &dyn ExpandDatabase,
         path: ast::Path,
-        span_map: SpanMapRef<'_>,
+        span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
     ) -> Option<ModPath> {
-        convert_path(db, path, span_map)
+        convert_path(db, path, span_for_range)
     }
 
     pub fn from_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option<ModPath> {
@@ -221,7 +220,7 @@ fn display_fmt_path(
 fn convert_path(
     db: &dyn ExpandDatabase,
     path: ast::Path,
-    span_map: SpanMapRef<'_>,
+    span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
 ) -> Option<ModPath> {
     let mut segments = path.segments();
 
@@ -230,12 +229,9 @@ fn convert_path(
         ast::PathSegmentKind::Name(name_ref) => {
             if name_ref.text() == "$crate" {
                 ModPath::from_kind(
-                    resolve_crate_root(
-                        db,
-                        span_map.span_for_range(name_ref.syntax().text_range()).ctx,
-                    )
-                    .map(PathKind::DollarCrate)
-                    .unwrap_or(PathKind::Crate),
+                    resolve_crate_root(db, span_for_range(name_ref.syntax().text_range()))
+                        .map(PathKind::DollarCrate)
+                        .unwrap_or(PathKind::Crate),
                 )
             } else {
                 let mut res = ModPath::from_kind(
@@ -289,7 +285,7 @@ fn convert_path(
     // We follow what it did anyway :)
     if mod_path.segments.len() == 1 && mod_path.kind == PathKind::Plain {
         if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
-            let syn_ctx = span_map.span_for_range(segment.syntax().text_range()).ctx;
+            let syn_ctx = span_for_range(segment.syntax().text_range());
             if let Some(macro_call_id) = db.lookup_intern_syntax_context(syn_ctx).outer_expn {
                 if db.lookup_intern_macro_call(macro_call_id).def.local_inner {
                     mod_path.kind = match resolve_crate_root(db, syn_ctx) {
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index fe191a456a9..20964f5acbd 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -1781,10 +1781,7 @@ impl HirDisplay for TypeRef {
                 f.write_joined(bounds, " + ")?;
             }
             TypeRef::Macro(macro_call) => {
-                let ctx = hir_def::lower::LowerCtx::with_span_map(
-                    f.db.upcast(),
-                    f.db.span_map(macro_call.file_id),
-                );
+                let ctx = hir_def::lower::LowerCtx::new(f.db.upcast(), macro_call.file_id);
                 let macro_call = macro_call.to_node(f.db.upcast());
                 match macro_call.path() {
                     Some(path) => match Path::from_src(&ctx, path) {
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index ca8bd65510b..99907ea15b5 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -1073,7 +1073,7 @@ impl<'db> SemanticsImpl<'db> {
 
     pub fn resolve_type(&self, ty: &ast::Type) -> Option<Type> {
         let analyze = self.analyze(ty.syntax())?;
-        let ctx = LowerCtx::with_file_id(self.db.upcast(), analyze.file_id);
+        let ctx = LowerCtx::new(self.db.upcast(), analyze.file_id);
         let ty = hir_ty::TyLoweringContext::new_maybe_unowned(
             self.db,
             &analyze.resolver,
@@ -1085,8 +1085,7 @@ impl<'db> SemanticsImpl<'db> {
 
     pub fn resolve_trait(&self, path: &ast::Path) -> Option<Trait> {
         let analyze = self.analyze(path.syntax())?;
-        let span_map = self.db.span_map(analyze.file_id);
-        let ctx = LowerCtx::with_span_map(self.db.upcast(), span_map);
+        let ctx = LowerCtx::new(self.db.upcast(), analyze.file_id);
         let hir_path = Path::from_src(&ctx, path.clone())?;
         match analyze.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), &hir_path)? {
             TypeNs::TraitId(id) => Some(Trait { id }),
@@ -1694,7 +1693,7 @@ impl SemanticsScope<'_> {
     /// Resolve a path as-if it was written at the given scope. This is
     /// necessary a heuristic, as it doesn't take hygiene into account.
     pub fn speculative_resolve(&self, path: &ast::Path) -> Option<PathResolution> {
-        let ctx = LowerCtx::with_file_id(self.db.upcast(), self.file_id);
+        let ctx = LowerCtx::new(self.db.upcast(), self.file_id);
         let path = Path::from_src(&ctx, path.clone())?;
         resolve_hir_path(self.db, &self.resolver, &path)
     }
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index a147102bcd8..f87e0a3897a 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -549,7 +549,7 @@ impl SourceAnalyzer {
         db: &dyn HirDatabase,
         macro_call: InFile<&ast::MacroCall>,
     ) -> Option<Macro> {
-        let ctx = LowerCtx::with_file_id(db.upcast(), macro_call.file_id);
+        let ctx = LowerCtx::new(db.upcast(), macro_call.file_id);
         let path = macro_call.value.path().and_then(|ast| Path::from_src(&ctx, ast))?;
         self.resolver
             .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Bang))
@@ -662,7 +662,7 @@ impl SourceAnalyzer {
         }
 
         // This must be a normal source file rather than macro file.
-        let ctx = LowerCtx::with_span_map(db.upcast(), db.span_map(self.file_id));
+        let ctx = LowerCtx::new(db.upcast(), self.file_id);
         let hir_path = Path::from_src(&ctx, path.clone())?;
 
         // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are
diff --git a/crates/span/src/ast_id.rs b/crates/span/src/ast_id.rs
index 2d98aa81e50..332745aae6e 100644
--- a/crates/span/src/ast_id.rs
+++ b/crates/span/src/ast_id.rs
@@ -83,24 +83,28 @@ register_ast_id_node! {
     Item,
         Adt,
             Enum,
+                Variant,
             Struct,
+                RecordField,
+                TupleField,
             Union,
-        Const,
+        AssocItem,
+            Const,
+            Fn,
+            MacroCall,
+            TypeAlias,
         ExternBlock,
         ExternCrate,
-        Fn,
         Impl,
         Macro,
             MacroDef,
             MacroRules,
-        MacroCall,
         Module,
         Static,
         Trait,
         TraitAlias,
-        TypeAlias,
         Use,
-    AssocItem, BlockExpr, Variant, RecordField, TupleField, ConstArg, Param, SelfParam
+    BlockExpr, ConstArg, Param, SelfParam
 }
 
 /// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back.