Skip to content

Commit 2aecf4b

Browse files
committed
Introduce an abstraction over Span.
1 parent 289c8f7 commit 2aecf4b

File tree

1 file changed

+101
-22
lines changed

1 file changed

+101
-22
lines changed

src/librustc_span/lib.rs

+101-22
Original file line numberDiff line numberDiff line change
@@ -239,18 +239,66 @@ impl Ord for Span {
239239
}
240240
}
241241

242+
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
243+
pub enum SpanId {
244+
Span(Span),
245+
DefId(DefId),
246+
}
247+
248+
impl Default for SpanId {
249+
fn default() -> SpanId {
250+
SpanId::Span(DUMMY_SP)
251+
}
252+
}
253+
254+
impl From<Span> for SpanId {
255+
fn from(span: Span) -> SpanId {
256+
SpanId::Span(span)
257+
}
258+
}
259+
260+
impl SpanId {
261+
pub fn is_dummy(self) -> bool {
262+
match self {
263+
SpanId::Span(sp) => sp.is_dummy(),
264+
_ => false,
265+
}
266+
}
267+
}
268+
269+
pub trait SpanLike:
270+
Copy + Clone + std::fmt::Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default
271+
{
272+
fn is_dummy(&self) -> bool;
273+
}
274+
275+
impl SpanLike for Span {
276+
fn is_dummy(&self) -> bool {
277+
Span::is_dummy(*self)
278+
}
279+
}
280+
281+
impl SpanLike for SpanId {
282+
fn is_dummy(&self) -> bool {
283+
SpanId::is_dummy(*self)
284+
}
285+
}
286+
242287
/// A collection of spans. Spans have two orthogonal attributes:
243288
///
244289
/// - They can be *primary spans*. In this case they are the locus of
245290
/// the error, and would be rendered with `^^^`.
246291
/// - They can have a *label*. In this case, the label is written next
247292
/// to the mark in the snippet when we render.
248293
#[derive(Clone, Debug, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)]
249-
pub struct MultiSpan {
294+
pub struct Multi<Span> {
250295
primary_spans: Vec<Span>,
251296
span_labels: Vec<(Span, String)>,
252297
}
253298

299+
pub type MultiSpan = Multi<Span>;
300+
pub type MultiSpanId = Multi<SpanId>;
301+
254302
impl Span {
255303
#[inline]
256304
pub fn lo(self) -> BytePos {
@@ -592,7 +640,7 @@ impl Span {
592640
}
593641

594642
#[derive(Clone, Debug)]
595-
pub struct SpanLabel {
643+
pub struct Labelled<Span> {
596644
/// The span we are going to include in the final snippet.
597645
pub span: Span,
598646

@@ -604,6 +652,9 @@ pub struct SpanLabel {
604652
pub label: Option<String>,
605653
}
606654

655+
pub type SpanLabel = Labelled<Span>;
656+
pub type SpanIdLabel = Labelled<SpanId>;
657+
607658
impl Default for Span {
608659
fn default() -> Self {
609660
DUMMY_SP
@@ -651,19 +702,19 @@ impl fmt::Debug for SpanData {
651702
}
652703
}
653704

654-
impl MultiSpan {
705+
impl<Span: SpanLike> Multi<Span> {
655706
#[inline]
656-
pub fn new() -> MultiSpan {
657-
MultiSpan { primary_spans: vec![], span_labels: vec![] }
707+
pub fn new() -> Self {
708+
Self { primary_spans: vec![], span_labels: vec![] }
658709
}
659710

660-
pub fn from_span(primary_span: Span) -> MultiSpan {
661-
MultiSpan { primary_spans: vec![primary_span], span_labels: vec![] }
711+
pub fn from_span(primary_span: impl Into<Span>) -> Self {
712+
Self { primary_spans: vec![primary_span.into()], span_labels: vec![] }
662713
}
663714

664-
pub fn from_spans(mut vec: Vec<Span>) -> MultiSpan {
715+
pub fn from_spans(mut vec: Vec<Span>) -> Self {
665716
vec.sort();
666-
MultiSpan { primary_spans: vec, span_labels: vec![] }
717+
Self { primary_spans: vec, span_labels: vec![] }
667718
}
668719

669720
pub fn push_span_label(&mut self, span: Span, label: String) {
@@ -720,22 +771,23 @@ impl MultiSpan {
720771
/// span `P`, if there is at least one label with span `P`, we return
721772
/// those labels (marked as primary). But otherwise we return
722773
/// `SpanLabel` instances with empty labels.
723-
pub fn span_labels(&self) -> Vec<SpanLabel> {
724-
let is_primary = |span| self.primary_spans.contains(&span);
774+
pub fn span_labels(&self) -> Vec<Labelled<Span>> {
775+
let is_primary = |span| self.primary_spans.contains(span);
725776

726777
let mut span_labels = self
727778
.span_labels
728779
.iter()
729-
.map(|&(span, ref label)| SpanLabel {
730-
span,
780+
.map(|(span, label)| Labelled {
781+
span: span.clone(),
731782
is_primary: is_primary(span),
732783
label: Some(label.clone()),
733784
})
734785
.collect::<Vec<_>>();
735786

736-
for &span in &self.primary_spans {
737-
if !span_labels.iter().any(|sl| sl.span == span) {
738-
span_labels.push(SpanLabel { span, is_primary: true, label: None });
787+
for span in &self.primary_spans {
788+
if !span_labels.iter().any(|sl| &sl.span == span) {
789+
let span = span.clone();
790+
span_labels.push(Labelled { span, is_primary: true, label: None });
739791
}
740792
}
741793

@@ -748,15 +800,42 @@ impl MultiSpan {
748800
}
749801
}
750802

751-
impl From<Span> for MultiSpan {
752-
fn from(span: Span) -> MultiSpan {
753-
MultiSpan::from_span(span)
803+
impl<S> Multi<S> {
804+
pub fn map_span<S2>(&self, f: impl Fn(&S) -> S2) -> Multi<S2> {
805+
Multi {
806+
primary_spans: self.primary_spans.iter().map(&f).collect(),
807+
span_labels: self.span_labels.iter().map(|(s, l)| (f(s), l.clone())).collect(),
808+
}
809+
}
810+
}
811+
812+
impl<Span: SpanLike> From<Span> for Multi<Span> {
813+
fn from(span: Span) -> Multi<Span> {
814+
Multi::from_span(span)
815+
}
816+
}
817+
818+
impl From<Span> for MultiSpanId {
819+
fn from(span: Span) -> MultiSpanId {
820+
Multi::from_span(span)
821+
}
822+
}
823+
824+
impl From<MultiSpan> for MultiSpanId {
825+
fn from(ms: MultiSpan) -> MultiSpanId {
826+
ms.map_span(|s| SpanId::Span(*s))
827+
}
828+
}
829+
830+
impl<Span: SpanLike> From<Vec<Span>> for Multi<Span> {
831+
fn from(spans: Vec<Span>) -> Multi<Span> {
832+
Multi::from_spans(spans)
754833
}
755834
}
756835

757-
impl From<Vec<Span>> for MultiSpan {
758-
fn from(spans: Vec<Span>) -> MultiSpan {
759-
MultiSpan::from_spans(spans)
836+
impl From<Vec<Span>> for MultiSpanId {
837+
fn from(spans: Vec<Span>) -> MultiSpanId {
838+
Multi::from_spans(spans).into()
760839
}
761840
}
762841

0 commit comments

Comments
 (0)