]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #45602 - petrochenkov:ospan, r=michaelwoerister
authorkennytm <kennytm@gmail.com>
Wed, 1 Nov 2017 05:32:10 +0000 (13:32 +0800)
committerGitHub <noreply@github.com>
Wed, 1 Nov 2017 05:32:10 +0000 (13:32 +0800)
Optimize some span operations

Do not decode span data twice/thrice/etc unnecessarily.
Applied to stable hashing and all methods in `impl Span`.

Follow up to https://github.com/rust-lang/rust/pull/44646
r? @michaelwoerister

src/librustc/ich/hcx.rs
src/libsyntax_pos/lib.rs

index f46540114f75058e324bebe9f1ee150b4740382a..d24344e4e2166c9960ccbd3115700f186a1113d9 100644 (file)
@@ -371,17 +371,18 @@ fn hash_stable<W: StableHasherResult>(&self,
         // If this is not an empty or invalid span, we want to hash the last
         // position that belongs to it, as opposed to hashing the first
         // position past it.
-        let span_hi = if self.hi() > self.lo() {
+        let span = self.data();
+        let span_hi = if span.hi > span.lo {
             // We might end up in the middle of a multibyte character here,
             // but that's OK, since we are not trying to decode anything at
             // this position.
-            self.hi() - ::syntax_pos::BytePos(1)
+            span.hi - ::syntax_pos::BytePos(1)
         } else {
-            self.hi()
+            span.hi
         };
 
         {
-            let loc1 = hcx.codemap().byte_pos_to_line_and_col(self.lo());
+            let loc1 = hcx.codemap().byte_pos_to_line_and_col(span.lo);
             let loc1 = loc1.as_ref()
                            .map(|&(ref fm, line, col)| (&fm.name[..], line, col.to_usize()))
                            .unwrap_or(("???", 0, 0));
@@ -414,7 +415,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             }
         }
 
-        if self.ctxt() == SyntaxContext::empty() {
+        if span.ctxt == SyntaxContext::empty() {
             0u8.hash_stable(hcx, hasher);
         } else {
             1u8.hash_stable(hcx, hasher);
index d30d79ece15c73cf62d566b10cc74dff87d18e11..44e73d876e85a9f1ee3a84d7c4ebac2b7df138c2 100644 (file)
@@ -75,6 +75,21 @@ pub struct SpanData {
     pub ctxt: SyntaxContext,
 }
 
+impl SpanData {
+    #[inline]
+    pub fn with_lo(&self, lo: BytePos) -> Span {
+        Span::new(lo, self.hi, self.ctxt)
+    }
+    #[inline]
+    pub fn with_hi(&self, hi: BytePos) -> Span {
+        Span::new(self.lo, hi, self.ctxt)
+    }
+    #[inline]
+    pub fn with_ctxt(&self, ctxt: SyntaxContext) -> Span {
+        Span::new(self.lo, self.hi, ctxt)
+    }
+}
+
 // The interner in thread-local, so `Span` shouldn't move between threads.
 impl !Send for Span {}
 impl !Sync for Span {}
@@ -109,8 +124,7 @@ pub fn lo(self) -> BytePos {
     }
     #[inline]
     pub fn with_lo(self, lo: BytePos) -> Span {
-        let base = self.data();
-        Span::new(lo, base.hi, base.ctxt)
+        self.data().with_lo(lo)
     }
     #[inline]
     pub fn hi(self) -> BytePos {
@@ -118,8 +132,7 @@ pub fn hi(self) -> BytePos {
     }
     #[inline]
     pub fn with_hi(self, hi: BytePos) -> Span {
-        let base = self.data();
-        Span::new(base.lo, hi, base.ctxt)
+        self.data().with_hi(hi)
     }
     #[inline]
     pub fn ctxt(self) -> SyntaxContext {
@@ -127,20 +140,21 @@ pub fn ctxt(self) -> SyntaxContext {
     }
     #[inline]
     pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
-        let base = self.data();
-        Span::new(base.lo, base.hi, ctxt)
+        self.data().with_ctxt(ctxt)
     }
 
     /// Returns a new span representing just the end-point of this span
     pub fn end_point(self) -> Span {
-        let lo = cmp::max(self.hi().0 - 1, self.lo().0);
-        self.with_lo(BytePos(lo))
+        let span = self.data();
+        let lo = cmp::max(span.hi.0 - 1, span.lo.0);
+        span.with_lo(BytePos(lo))
     }
 
     /// Returns a new span representing the next character after the end-point of this span
     pub fn next_point(self) -> Span {
-        let lo = cmp::max(self.hi().0, self.lo().0 + 1);
-        Span::new(BytePos(lo), BytePos(lo), self.ctxt())
+        let span = self.data();
+        let lo = cmp::max(span.hi.0, span.lo.0 + 1);
+        Span::new(BytePos(lo), BytePos(lo), span.ctxt)
     }
 
     /// Returns `self` if `self` is not the dummy span, and `other` otherwise.
@@ -150,7 +164,9 @@ pub fn substitute_dummy(self, other: Span) -> Span {
 
     /// Return true if `self` fully encloses `other`.
     pub fn contains(self, other: Span) -> bool {
-        self.lo() <= other.lo() && other.hi() <= self.hi()
+        let span = self.data();
+        let other = other.data();
+        span.lo <= other.lo && other.hi <= span.hi
     }
 
     /// Return true if the spans are equal with regards to the source text.
@@ -158,13 +174,17 @@ pub fn contains(self, other: Span) -> bool {
     /// Use this instead of `==` when either span could be generated code,
     /// and you only care that they point to the same bytes of source text.
     pub fn source_equal(&self, other: &Span) -> bool {
-        self.lo() == other.lo() && self.hi() == other.hi()
+        let span = self.data();
+        let other = other.data();
+        span.lo == other.lo && span.hi == other.hi
     }
 
     /// Returns `Some(span)`, where the start is trimmed by the end of `other`
     pub fn trim_start(self, other: Span) -> Option<Span> {
-        if self.hi() > other.hi() {
-            Some(self.with_lo(cmp::max(self.lo(), other.hi())))
+        let span = self.data();
+        let other = other.data();
+        if span.hi > other.hi {
+            Some(span.with_lo(cmp::max(span.lo, other.hi)))
         } else {
             None
         }
@@ -268,29 +288,35 @@ pub fn macro_backtrace(mut self) -> Vec<MacroBacktrace> {
 
     /// Return a `Span` that would enclose both `self` and `end`.
     pub fn to(self, end: Span) -> Span {
+        let span = self.data();
+        let end = end.data();
         Span::new(
-            cmp::min(self.lo(), end.lo()),
-            cmp::max(self.hi(), end.hi()),
+            cmp::min(span.lo, end.lo),
+            cmp::max(span.hi, end.hi),
             // FIXME(jseyfried): self.ctxt should always equal end.ctxt here (c.f. issue #23480)
-            if self.ctxt() == SyntaxContext::empty() { end.ctxt() } else { self.ctxt() },
+            if span.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt },
         )
     }
 
     /// Return a `Span` between the end of `self` to the beginning of `end`.
     pub fn between(self, end: Span) -> Span {
+        let span = self.data();
+        let end = end.data();
         Span::new(
-            self.hi(),
-            end.lo(),
-            if end.ctxt() == SyntaxContext::empty() { end.ctxt() } else { self.ctxt() },
+            span.hi,
+            end.lo,
+            if end.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt },
         )
     }
 
     /// Return a `Span` between the beginning of `self` to the beginning of `end`.
     pub fn until(self, end: Span) -> Span {
+        let span = self.data();
+        let end = end.data();
         Span::new(
-            self.lo(),
-            end.lo(),
-            if end.ctxt() == SyntaxContext::empty() { end.ctxt() } else { self.ctxt() },
+            span.lo,
+            end.lo,
+            if end.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt },
         )
     }
 }
@@ -316,13 +342,14 @@ fn default() -> Self {
 
 impl serialize::UseSpecializedEncodable for Span {
     fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        let span = self.data();
         s.emit_struct("Span", 2, |s| {
             s.emit_struct_field("lo", 0, |s| {
-                self.lo().encode(s)
+                span.lo.encode(s)
             })?;
 
             s.emit_struct_field("hi", 1, |s| {
-                self.hi().encode(s)
+                span.hi.encode(s)
             })
         })
     }