]> git.lizzy.rs Git - rust.git/blobdiff - src/libsyntax/codemap.rs
Only retain external static symbols across LTO
[rust.git] / src / libsyntax / codemap.rs
index e80c9e4a6cea48544d7d72e84a55bd949f74f74c..74302e2f6a0fdb7b0f32cfaa9fe5bd0ebadfccdb 100644 (file)
@@ -123,7 +123,7 @@ fn sub(self, rhs: CharPos) -> CharPos {
 /// able to use many of the functions on spans in codemap and you cannot assume
 /// that the length of the span = hi - lo; there may be space in the BytePos
 /// range between files.
-#[derive(Clone, Copy, Hash)]
+#[derive(Clone, Copy, Hash, PartialEq, Eq)]
 pub struct Span {
     pub lo: BytePos,
     pub hi: BytePos,
@@ -151,13 +151,21 @@ pub struct MultiSpan {
 impl Span {
     /// Returns `self` if `self` is not the dummy span, and `other` otherwise.
     pub fn substitute_dummy(self, other: Span) -> Span {
-        if self == DUMMY_SP { other } else { self }
+        if self.source_equal(&DUMMY_SP) { other } else { self }
     }
 
     pub fn contains(self, other: Span) -> bool {
         self.lo <= other.lo && other.hi <= self.hi
     }
 
+    /// Return true if the spans are equal with regards to the source text.
+    ///
+    /// 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
+    }
+
     /// Returns `Some(span)`, a union of `self` and `other`, on overlap.
     pub fn merge(self, other: Span) -> Option<Span> {
         if self.expn_id != other.expn_id {
@@ -192,15 +200,6 @@ pub struct Spanned<T> {
     pub span: Span,
 }
 
-impl PartialEq for Span {
-    fn eq(&self, other: &Span) -> bool {
-        return (*self).lo == (*other).lo && (*self).hi == (*other).hi;
-    }
-    fn ne(&self, other: &Span) -> bool { !(*self).eq(other) }
-}
-
-impl Eq for Span {}
-
 impl Encodable for Span {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_struct("Span", 2, |s| {
@@ -940,7 +939,7 @@ pub fn lookup_char_pos_adj(&self, pos: BytePos) -> LocWithOpt {
     }
 
     pub fn span_to_string(&self, sp: Span) -> String {
-        if self.files.borrow().is_empty() && sp == DUMMY_SP {
+        if self.files.borrow().is_empty() && sp.source_equal(&DUMMY_SP) {
             return "no-location".to_string();
         }
 
@@ -1053,9 +1052,18 @@ fn span_to_expanded_string_internal(&self, sp:Span, indent: &str) -> String {
     /// the macro callsite that expanded to it.
     pub fn source_callsite(&self, sp: Span) -> Span {
         let mut span = sp;
+        // Special case - if a macro is parsed as an argument to another macro, the source
+        // callsite is the first callsite, which is also source-equivalent to the span.
+        let mut first = true;
         while span.expn_id != NO_EXPANSION && span.expn_id != COMMAND_LINE_EXPN {
             if let Some(callsite) = self.with_expn_info(span.expn_id,
                                                |ei| ei.map(|ei| ei.call_site.clone())) {
+                if first && span.source_equal(&callsite) {
+                    if self.lookup_char_pos(span.lo).file.is_real_file() {
+                        return Span { expn_id: NO_EXPANSION, .. span };
+                    }
+                }
+                first = false;
                 span = callsite;
             }
             else {
@@ -1072,10 +1080,20 @@ pub fn source_callsite(&self, sp: Span) -> Span {
     /// corresponding to the source callsite.
     pub fn source_callee(&self, sp: Span) -> Option<NameAndSpan> {
         let mut span = sp;
+        // Special case - if a macro is parsed as an argument to another macro, the source
+        // callsite is source-equivalent to the span, and the source callee is the first callee.
+        let mut first = true;
         while let Some(callsite) = self.with_expn_info(span.expn_id,
                                             |ei| ei.map(|ei| ei.call_site.clone())) {
+            if first && span.source_equal(&callsite) {
+                if self.lookup_char_pos(span.lo).file.is_real_file() {
+                    return self.with_expn_info(span.expn_id,
+                                               |ei| ei.map(|ei| ei.callee.clone()));
+                }
+            }
+            first = false;
             if let Some(_) = self.with_expn_info(callsite.expn_id,
-                                                |ei| ei.map(|ei| ei.call_site.clone())) {
+                                                 |ei| ei.map(|ei| ei.call_site.clone())) {
                 span = callsite;
             }
             else {
@@ -1328,7 +1346,7 @@ pub fn span_allows_unstable(&self, span: Span) -> bool {
                 expninfo.map_or(/* hit the top level */ true, |info| {
 
                     let span_comes_from_this_expansion =
-                        info.callee.span.map_or(span == info.call_site, |mac_span| {
+                        info.callee.span.map_or(span.source_equal(&info.call_site), |mac_span| {
                             mac_span.contains(span)
                         });