about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-09-11 23:35:28 +0000
committerbors <bors@rust-lang.org>2021-09-11 23:35:28 +0000
commite6455ea72ca3a4602f6a6b097cb80647a1f69388 (patch)
tree377f5e7bbeae8d9f83c1ac2f839c7f7f4fe1e770
parenteac0b26015ac0e4f8f025e82b3568ab5a85c2746 (diff)
parentce1da849b04bfa3847fbb4130424cac8cd51a227 (diff)
downloadrust-e6455ea72ca3a4602f6a6b097cb80647a1f69388.tar.gz
rust-e6455ea72ca3a4602f6a6b097cb80647a1f69388.zip
Auto merge of #84373 - cjgillot:resolve-span, r=michaelwoerister,petrochenkov
Encode spans relative to the enclosing item

The aim of this PR is to avoid recomputing queries when code is moved without modification.

MCP at https://github.com/rust-lang/compiler-team/issues/443

This is achieved by :
1. storing the HIR owner LocalDefId information inside the span;
2. encoding and decoding spans relative to the enclosing item in the incremental on-disk cache;
3. marking a dependency to the `source_span(LocalDefId)` query when we translate a span from the short (`Span`) representation to its explicit (`SpanData`) representation.

Since all client code uses `Span`, step 3 ensures that all manipulations
of span byte positions actually create the dependency edge between
the caller and the `source_span(LocalDefId)`.
This query return the actual absolute span of the parent item.
As a consequence, any source code motion that changes the absolute byte position of a node will either:
- modify the distance to the parent's beginning, so change the relative span's hash;
- dirty `source_span`, and trigger the incremental recomputation of all code that
  depends on the span's absolute byte position.

With this scheme, I believe the dependency tracking to be accurate.

For the moment, the spans are marked during lowering.
I'd rather do this during def-collection,
but the AST MutVisitor is not practical enough just yet.
The only difference is that we attach macro-expanded spans
to their expansion point instead of the macro itself.
-rw-r--r--clippy_lints/src/attrs.rs4
-rw-r--r--clippy_lints/src/cognitive_complexity.rs2
-rw-r--r--clippy_lints/src/copies.rs2
-rw-r--r--clippy_lints/src/doc.rs1
-rw-r--r--clippy_lints/src/implicit_hasher.rs4
-rw-r--r--clippy_lints/src/large_const_arrays.rs1
-rw-r--r--clippy_lints/src/methods/manual_split_once.rs2
-rw-r--r--clippy_lints/src/module_style.rs4
-rw-r--r--clippy_lints/src/regex.rs2
-rw-r--r--clippy_lints/src/tabs_in_doc_comments.rs1
10 files changed, 13 insertions, 10 deletions
diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs
index c9ff468874b..2ef7dcc1775 100644
--- a/clippy_lints/src/attrs.rs
+++ b/clippy_lints/src/attrs.rs
@@ -527,8 +527,8 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::It
                 return;
             }
 
-            let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt());
-            let end_of_attr_to_item = Span::new(attr.span.hi(), item.span.lo(), item.span.ctxt());
+            let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt(), item.span.parent());
+            let end_of_attr_to_item = Span::new(attr.span.hi(), item.span.lo(), item.span.ctxt(), item.span.parent());
 
             if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) {
                 let lines = snippet.split('\n').collect::<Vec<_>>();
diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs
index 96c30d57ee1..2203d1c39f1 100644
--- a/clippy_lints/src/cognitive_complexity.rs
+++ b/clippy_lints/src/cognitive_complexity.rs
@@ -95,7 +95,7 @@ impl CognitiveComplexity {
                     });
 
                     if let Some((low, high)) = pos {
-                        Span::new(low, high, header_span.ctxt())
+                        Span::new(low, high, header_span.ctxt(), header_span.parent())
                     } else {
                         return;
                     }
diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs
index d58e4949120..6ded2f233ef 100644
--- a/clippy_lints/src/copies.rs
+++ b/clippy_lints/src/copies.rs
@@ -472,7 +472,7 @@ fn emit_branches_sharing_code_lint(
 
         let mut span = moved_start.to(span_end);
         // Improve formatting if the inner block has indention (i.e. normal Rust formatting)
-        let test_span = Span::new(span.lo() - BytePos(4), span.lo(), span.ctxt());
+        let test_span = Span::new(span.lo() - BytePos(4), span.lo(), span.ctxt(), span.parent());
         if snippet_opt(cx, test_span)
             .map(|snip| snip == "    ")
             .unwrap_or_default()
diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs
index cb2b7f5be70..0b61909ddd8 100644
--- a/clippy_lints/src/doc.rs
+++ b/clippy_lints/src/doc.rs
@@ -665,6 +665,7 @@ fn check_text(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str
             span.lo() + BytePos::from_usize(offset),
             span.lo() + BytePos::from_usize(offset + word.len()),
             span.ctxt(),
+            span.parent(),
         );
 
         check_word(cx, word, span);
diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs
index 6b407c7bb67..2fe32fcf665 100644
--- a/clippy_lints/src/implicit_hasher.rs
+++ b/clippy_lints/src/implicit_hasher.rs
@@ -130,7 +130,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
                         let pos = snippet_opt(cx, item.span.until(target.span()))
                             .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4)));
                         if let Some(pos) = pos {
-                            Span::new(pos, pos, item.span.data().ctxt)
+                            Span::new(pos, pos, item.span.ctxt(), item.span.parent())
                         } else {
                             return;
                         }
@@ -173,7 +173,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
                                     Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32))
                                 })
                                 .expect("failed to create span for type parameters");
-                            Span::new(pos, pos, item.span.data().ctxt)
+                            Span::new(pos, pos, item.span.ctxt(), item.span.parent())
                         });
 
                         let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
diff --git a/clippy_lints/src/large_const_arrays.rs b/clippy_lints/src/large_const_arrays.rs
index 10281496c11..fe6814e35d0 100644
--- a/clippy_lints/src/large_const_arrays.rs
+++ b/clippy_lints/src/large_const_arrays.rs
@@ -63,6 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
                     hi_pos - BytePos::from_usize("const".len()),
                     hi_pos,
                     item.span.ctxt(),
+                    item.span.parent(),
                 );
                 span_lint_and_then(
                     cx,
diff --git a/clippy_lints/src/methods/manual_split_once.rs b/clippy_lints/src/methods/manual_split_once.rs
index e273186d051..00167650324 100644
--- a/clippy_lints/src/methods/manual_split_once.rs
+++ b/clippy_lints/src/methods/manual_split_once.rs
@@ -182,7 +182,7 @@ fn parse_iter_usage(
                 },
                 _,
             ) => {
-                let parent_span = e.span.parent().unwrap();
+                let parent_span = e.span.parent_callsite().unwrap();
                 if parent_span.ctxt() == ctxt {
                     (Some(UnwrapKind::QuestionMark), parent_span)
                 } else {
diff --git a/clippy_lints/src/module_style.rs b/clippy_lints/src/module_style.rs
index 80a930d0c54..f351d0098b7 100644
--- a/clippy_lints/src/module_style.rs
+++ b/clippy_lints/src/module_style.rs
@@ -120,7 +120,7 @@ impl EarlyLintPass for ModStyle {
                     correct.push("mod.rs");
                     cx.struct_span_lint(
                         SELF_NAMED_MODULE_FILES,
-                        Span::new(file.start_pos, file.start_pos, SyntaxContext::root()),
+                        Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
                         |build| {
                             let mut lint =
                                 build.build(&format!("`mod.rs` files are required, found `{}`", path.display()));
@@ -167,7 +167,7 @@ fn check_self_named_mod_exists(cx: &EarlyContext<'_>, path: &Path, file: &Source
 
         cx.struct_span_lint(
             MOD_MODULE_FILES,
-            Span::new(file.start_pos, file.start_pos, SyntaxContext::root()),
+            Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
             |build| {
                 let mut lint = build.build(&format!("`mod.rs` files are not allowed, found `{}`", path.display()));
                 lint.help(&format!("move `{}` to `{}`", path.display(), mod_file.display(),));
diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs
index 89be7bf844f..947c25ac880 100644
--- a/clippy_lints/src/regex.rs
+++ b/clippy_lints/src/regex.rs
@@ -87,7 +87,7 @@ fn str_span(base: Span, c: regex_syntax::ast::Span, offset: u16) -> Span {
     let end = base.lo() + BytePos(u32::try_from(c.end.offset).expect("offset too large") + offset);
     let start = base.lo() + BytePos(u32::try_from(c.start.offset).expect("offset too large") + offset);
     assert!(start <= end);
-    Span::new(start, end, base.ctxt())
+    Span::new(start, end, base.ctxt(), base.parent())
 }
 
 fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<String> {
diff --git a/clippy_lints/src/tabs_in_doc_comments.rs b/clippy_lints/src/tabs_in_doc_comments.rs
index 6a73b94d87e..4a67cabf323 100644
--- a/clippy_lints/src/tabs_in_doc_comments.rs
+++ b/clippy_lints/src/tabs_in_doc_comments.rs
@@ -69,6 +69,7 @@ impl TabsInDocComments {
                     attr.span.lo() + BytePos(3 + lo),
                     attr.span.lo() + BytePos(3 + hi),
                     attr.span.ctxt(),
+                    attr.span.parent(),
                 );
                 span_lint_and_sugg(
                     cx,