about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-12-12 21:08:52 +0000
committerbors <bors@rust-lang.org>2023-12-12 21:08:52 +0000
commit5d7453ccd6e885b688b0bfcc6daca843e1f62c90 (patch)
tree7b5a551e35d801e6be819229546d523e111a2c80
parent98a8053143b4f67b8a2c8f5fb8acb1834295c357 (diff)
parentc209b5f97c35c6d5e9a0f6868edbed1665acbdc7 (diff)
downloadrust-5d7453ccd6e885b688b0bfcc6daca843e1f62c90.tar.gz
rust-5d7453ccd6e885b688b0bfcc6daca843e1f62c90.zip
Auto merge of #16106 - Veykril:fix-lifetime-span-split, r=Veykril
fix: Fix syntax bridge assigning invalid span to lifetime tokens

Fixes https://github.com/rust-lang/rust-analyzer/issues/16097
Fixes https://github.com/rust-lang/rust-analyzer/issues/16103
-rw-r--r--crates/hir-expand/src/span.rs29
-rw-r--r--crates/mbe/src/syntax_bridge.rs21
2 files changed, 22 insertions, 28 deletions
diff --git a/crates/hir-expand/src/span.rs b/crates/hir-expand/src/span.rs
index 0a6c22fe42d..fe476a40feb 100644
--- a/crates/hir-expand/src/span.rs
+++ b/crates/hir-expand/src/span.rs
@@ -75,27 +75,40 @@ pub struct RealSpanMap {
     /// Invariant: Sorted vec over TextSize
     // FIXME: SortedVec<(TextSize, ErasedFileAstId)>?
     pairs: Box<[(TextSize, ErasedFileAstId)]>,
+    end: TextSize,
 }
 
 impl RealSpanMap {
     /// Creates a real file span map that returns absolute ranges (relative ranges to the root ast id).
     pub fn absolute(file_id: FileId) -> Self {
-        RealSpanMap { file_id, pairs: Box::from([(TextSize::new(0), ROOT_ERASED_FILE_AST_ID)]) }
+        RealSpanMap {
+            file_id,
+            pairs: Box::from([(TextSize::new(0), ROOT_ERASED_FILE_AST_ID)]),
+            end: TextSize::new(!0),
+        }
     }
 
     pub fn from_file(db: &dyn ExpandDatabase, file_id: FileId) -> Self {
         let mut pairs = vec![(TextSize::new(0), ROOT_ERASED_FILE_AST_ID)];
         let ast_id_map = db.ast_id_map(file_id.into());
-        pairs.extend(
-            db.parse(file_id)
-                .tree()
-                .items()
-                .map(|item| (item.syntax().text_range().start(), ast_id_map.ast_id(&item).erase())),
-        );
-        RealSpanMap { file_id, pairs: pairs.into_boxed_slice() }
+        let tree = db.parse(file_id).tree();
+        pairs
+            .extend(tree.items().map(|item| {
+                (item.syntax().text_range().start(), ast_id_map.ast_id(&item).erase())
+            }));
+        RealSpanMap {
+            file_id,
+            pairs: pairs.into_boxed_slice(),
+            end: tree.syntax().text_range().end(),
+        }
     }
 
     pub fn span_for_range(&self, range: TextRange) -> SpanData {
+        assert!(
+            range.end() <= self.end,
+            "range {range:?} goes beyond the end of the file {:?}",
+            self.end
+        );
         let start = range.start();
         let idx = self
             .pairs
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs
index 1c46471a383..b89bfd74a6e 100644
--- a/crates/mbe/src/syntax_bridge.rs
+++ b/crates/mbe/src/syntax_bridge.rs
@@ -311,7 +311,7 @@ where
 
                             let ident = tt::Leaf::from(tt::Ident {
                                 text: SmolStr::new(&token.to_text(conv)[1..]),
-                                span: conv.span_for(TextRange::at(
+                                span: conv.span_for(TextRange::new(
                                     abs_range.start() + TextSize::of('\''),
                                     abs_range.end(),
                                 )),
@@ -625,25 +625,6 @@ impl<SpanMap, S> Converter<SpanMap, S> {
     }
 
     fn next_token(&mut self) -> Option<SyntaxToken> {
-        // while let Some(ev) = self.preorder.next() {
-        //     match ev {
-        //         WalkEvent::Enter(SyntaxElement::Token(t)) => {
-        //             if let Some(leafs) = self.append.remove(&t.clone().into()) {
-        //                 self.current_leafs.extend(leafs);
-        //             }
-        //             return Some(t);
-        //         }
-        //         WalkEvent::Enter(SyntaxElement::Node(n)) if self.remove.contains(&n) => {
-        //             self.preorder.skip_subtree();
-        //             if let Some(leafs) = self.append.remove(&n.into()) {
-        //                 self.current_leafs.extend(leafs);
-        //             }
-        //         }
-        //         _ => (),
-        //     }
-        // }
-        // None;
-
         while let Some(ev) = self.preorder.next() {
             match ev {
                 WalkEvent::Enter(SyntaxElement::Token(t)) => return Some(t),