]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/ext/proc_macro_server.rs
Privatize DiagnosticBuilder constructors
[rust.git] / src / libsyntax / ext / proc_macro_server.rs
1 use crate::ast;
2 use crate::ext::base::ExtCtxt;
3 use crate::parse::{self, token, ParseSess};
4 use crate::parse::lexer::comments;
5 use crate::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
6
7 use errors::Diagnostic;
8 use rustc_data_structures::sync::Lrc;
9 use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};
10 use syntax_pos::symbol::{kw, sym, Symbol};
11
12 use proc_macro::{Delimiter, Level, LineColumn, Spacing};
13 use proc_macro::bridge::{server, TokenTree};
14 use std::{ascii, panic};
15 use std::ops::Bound;
16
17 trait FromInternal<T> {
18     fn from_internal(x: T) -> Self;
19 }
20
21 trait ToInternal<T> {
22     fn to_internal(self) -> T;
23 }
24
25 impl FromInternal<token::DelimToken> for Delimiter {
26     fn from_internal(delim: token::DelimToken) -> Delimiter {
27         match delim {
28             token::Paren => Delimiter::Parenthesis,
29             token::Brace => Delimiter::Brace,
30             token::Bracket => Delimiter::Bracket,
31             token::NoDelim => Delimiter::None,
32         }
33     }
34 }
35
36 impl ToInternal<token::DelimToken> for Delimiter {
37     fn to_internal(self) -> token::DelimToken {
38         match self {
39             Delimiter::Parenthesis => token::Paren,
40             Delimiter::Brace => token::Brace,
41             Delimiter::Bracket => token::Bracket,
42             Delimiter::None => token::NoDelim,
43         }
44     }
45 }
46
47 impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)>
48     for TokenTree<Group, Punct, Ident, Literal>
49 {
50     fn from_internal(((tree, is_joint), sess, stack): (TreeAndJoint, &ParseSess, &mut Vec<Self>))
51                     -> Self {
52         use crate::parse::token::*;
53
54         let joint = is_joint == Joint;
55         let Token { kind, span } = match tree {
56             tokenstream::TokenTree::Delimited(span, delim, tts) => {
57                 let delimiter = Delimiter::from_internal(delim);
58                 return TokenTree::Group(Group {
59                     delimiter,
60                     stream: tts.into(),
61                     span,
62                 });
63             }
64             tokenstream::TokenTree::Token(token) => token,
65         };
66
67         macro_rules! tt {
68             ($ty:ident { $($field:ident $(: $value:expr)*),+ $(,)? }) => (
69                 TokenTree::$ty(self::$ty {
70                     $($field $(: $value)*,)+
71                     span,
72                 })
73             );
74             ($ty:ident::$method:ident($($value:expr),*)) => (
75                 TokenTree::$ty(self::$ty::$method($($value,)* span))
76             );
77         }
78         macro_rules! op {
79             ($a:expr) => {
80                 tt!(Punct::new($a, joint))
81             };
82             ($a:expr, $b:expr) => {{
83                 stack.push(tt!(Punct::new($b, joint)));
84                 tt!(Punct::new($a, true))
85             }};
86             ($a:expr, $b:expr, $c:expr) => {{
87                 stack.push(tt!(Punct::new($c, joint)));
88                 stack.push(tt!(Punct::new($b, true)));
89                 tt!(Punct::new($a, true))
90             }};
91         }
92
93         match kind {
94             Eq => op!('='),
95             Lt => op!('<'),
96             Le => op!('<', '='),
97             EqEq => op!('=', '='),
98             Ne => op!('!', '='),
99             Ge => op!('>', '='),
100             Gt => op!('>'),
101             AndAnd => op!('&', '&'),
102             OrOr => op!('|', '|'),
103             Not => op!('!'),
104             Tilde => op!('~'),
105             BinOp(Plus) => op!('+'),
106             BinOp(Minus) => op!('-'),
107             BinOp(Star) => op!('*'),
108             BinOp(Slash) => op!('/'),
109             BinOp(Percent) => op!('%'),
110             BinOp(Caret) => op!('^'),
111             BinOp(And) => op!('&'),
112             BinOp(Or) => op!('|'),
113             BinOp(Shl) => op!('<', '<'),
114             BinOp(Shr) => op!('>', '>'),
115             BinOpEq(Plus) => op!('+', '='),
116             BinOpEq(Minus) => op!('-', '='),
117             BinOpEq(Star) => op!('*', '='),
118             BinOpEq(Slash) => op!('/', '='),
119             BinOpEq(Percent) => op!('%', '='),
120             BinOpEq(Caret) => op!('^', '='),
121             BinOpEq(And) => op!('&', '='),
122             BinOpEq(Or) => op!('|', '='),
123             BinOpEq(Shl) => op!('<', '<', '='),
124             BinOpEq(Shr) => op!('>', '>', '='),
125             At => op!('@'),
126             Dot => op!('.'),
127             DotDot => op!('.', '.'),
128             DotDotDot => op!('.', '.', '.'),
129             DotDotEq => op!('.', '.', '='),
130             Comma => op!(','),
131             Semi => op!(';'),
132             Colon => op!(':'),
133             ModSep => op!(':', ':'),
134             RArrow => op!('-', '>'),
135             LArrow => op!('<', '-'),
136             FatArrow => op!('=', '>'),
137             Pound => op!('#'),
138             Dollar => op!('$'),
139             Question => op!('?'),
140             SingleQuote => op!('\''),
141
142             Ident(name, false) if name == kw::DollarCrate => tt!(Ident::dollar_crate()),
143             Ident(name, is_raw) => tt!(Ident::new(name, is_raw)),
144             Lifetime(name) => {
145                 let ident = ast::Ident::new(name, span).without_first_quote();
146                 stack.push(tt!(Ident::new(ident.name, false)));
147                 tt!(Punct::new('\'', true))
148             }
149             Literal(lit) => tt!(Literal { lit }),
150             DocComment(c) => {
151                 let style = comments::doc_comment_style(&c.as_str());
152                 let stripped = comments::strip_doc_comment_decoration(&c.as_str());
153                 let mut escaped = String::new();
154                 for ch in stripped.chars() {
155                     escaped.extend(ch.escape_debug());
156                 }
157                 let stream = vec![
158                     Ident(sym::doc, false),
159                     Eq,
160                     TokenKind::lit(token::Str, Symbol::intern(&escaped), None),
161                 ]
162                 .into_iter()
163                 .map(|kind| tokenstream::TokenTree::token(kind, span))
164                 .collect();
165                 stack.push(TokenTree::Group(Group {
166                     delimiter: Delimiter::Bracket,
167                     stream,
168                     span: DelimSpan::from_single(span),
169                 }));
170                 if style == ast::AttrStyle::Inner {
171                     stack.push(tt!(Punct::new('!', false)));
172                 }
173                 tt!(Punct::new('#', false))
174             }
175
176             Interpolated(nt) => {
177                 let stream = nt.to_tokenstream(sess, span);
178                 TokenTree::Group(Group {
179                     delimiter: Delimiter::None,
180                     stream,
181                     span: DelimSpan::from_single(span),
182                 })
183             }
184
185             OpenDelim(..) | CloseDelim(..) => unreachable!(),
186             Whitespace | Comment | Shebang(..) | Unknown(..) | Eof => unreachable!(),
187         }
188     }
189 }
190
191 impl ToInternal<TokenStream> for TokenTree<Group, Punct, Ident, Literal> {
192     fn to_internal(self) -> TokenStream {
193         use crate::parse::token::*;
194
195         let (ch, joint, span) = match self {
196             TokenTree::Punct(Punct { ch, joint, span }) => (ch, joint, span),
197             TokenTree::Group(Group {
198                 delimiter,
199                 stream,
200                 span,
201             }) => {
202                 return tokenstream::TokenTree::Delimited(
203                     span,
204                     delimiter.to_internal(),
205                     stream.into(),
206                 )
207                 .into();
208             }
209             TokenTree::Ident(self::Ident { sym, is_raw, span }) => {
210                 return tokenstream::TokenTree::token(Ident(sym, is_raw), span).into();
211             }
212             TokenTree::Literal(self::Literal {
213                 lit: token::Lit { kind: token::Integer, symbol, suffix },
214                 span,
215             }) if symbol.as_str().starts_with("-") => {
216                 let minus = BinOp(BinOpToken::Minus);
217                 let symbol = Symbol::intern(&symbol.as_str()[1..]);
218                 let integer = TokenKind::lit(token::Integer, symbol, suffix);
219                 let a = tokenstream::TokenTree::token(minus, span);
220                 let b = tokenstream::TokenTree::token(integer, span);
221                 return vec![a, b].into_iter().collect();
222             }
223             TokenTree::Literal(self::Literal {
224                 lit: token::Lit { kind: token::Float, symbol, suffix },
225                 span,
226             }) if symbol.as_str().starts_with("-") => {
227                 let minus = BinOp(BinOpToken::Minus);
228                 let symbol = Symbol::intern(&symbol.as_str()[1..]);
229                 let float = TokenKind::lit(token::Float, symbol, suffix);
230                 let a = tokenstream::TokenTree::token(minus, span);
231                 let b = tokenstream::TokenTree::token(float, span);
232                 return vec![a, b].into_iter().collect();
233             }
234             TokenTree::Literal(self::Literal { lit, span }) => {
235                 return tokenstream::TokenTree::token(Literal(lit), span).into()
236             }
237         };
238
239         let kind = match ch {
240             '=' => Eq,
241             '<' => Lt,
242             '>' => Gt,
243             '!' => Not,
244             '~' => Tilde,
245             '+' => BinOp(Plus),
246             '-' => BinOp(Minus),
247             '*' => BinOp(Star),
248             '/' => BinOp(Slash),
249             '%' => BinOp(Percent),
250             '^' => BinOp(Caret),
251             '&' => BinOp(And),
252             '|' => BinOp(Or),
253             '@' => At,
254             '.' => Dot,
255             ',' => Comma,
256             ';' => Semi,
257             ':' => Colon,
258             '#' => Pound,
259             '$' => Dollar,
260             '?' => Question,
261             '\'' => SingleQuote,
262             _ => unreachable!(),
263         };
264
265         let tree = tokenstream::TokenTree::token(kind, span);
266         TokenStream::new(vec![(tree, if joint { Joint } else { NonJoint })])
267     }
268 }
269
270 impl ToInternal<errors::Level> for Level {
271     fn to_internal(self) -> errors::Level {
272         match self {
273             Level::Error => errors::Level::Error,
274             Level::Warning => errors::Level::Warning,
275             Level::Note => errors::Level::Note,
276             Level::Help => errors::Level::Help,
277             _ => unreachable!("unknown proc_macro::Level variant: {:?}", self),
278         }
279     }
280 }
281
282 #[derive(Clone)]
283 pub struct TokenStreamIter {
284     cursor: tokenstream::Cursor,
285     stack: Vec<TokenTree<Group, Punct, Ident, Literal>>,
286 }
287
288 #[derive(Clone)]
289 pub struct Group {
290     delimiter: Delimiter,
291     stream: TokenStream,
292     span: DelimSpan,
293 }
294
295 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
296 pub struct Punct {
297     ch: char,
298     // NB. not using `Spacing` here because it doesn't implement `Hash`.
299     joint: bool,
300     span: Span,
301 }
302
303 impl Punct {
304     fn new(ch: char, joint: bool, span: Span) -> Punct {
305         const LEGAL_CHARS: &[char] = &['=', '<', '>', '!', '~', '+', '-', '*', '/', '%', '^',
306                                        '&', '|', '@', '.', ',', ';', ':', '#', '$', '?', '\''];
307         if !LEGAL_CHARS.contains(&ch) {
308             panic!("unsupported character `{:?}`", ch)
309         }
310         Punct { ch, joint, span }
311     }
312 }
313
314 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
315 pub struct Ident {
316     sym: Symbol,
317     is_raw: bool,
318     span: Span,
319 }
320
321 impl Ident {
322     fn is_valid(string: &str) -> bool {
323         let mut chars = string.chars();
324         if let Some(start) = chars.next() {
325             rustc_lexer::is_id_start(start) && chars.all(rustc_lexer::is_id_continue)
326         } else {
327             false
328         }
329     }
330     fn new(sym: Symbol, is_raw: bool, span: Span) -> Ident {
331         let string = sym.as_str();
332         if !Self::is_valid(&string) {
333             panic!("`{:?}` is not a valid identifier", string)
334         }
335         // Get rid of gensyms to conservatively check rawness on the string contents only.
336         if is_raw && !sym.as_interned_str().as_symbol().can_be_raw() {
337             panic!("`{}` cannot be a raw identifier", string);
338         }
339         Ident { sym, is_raw, span }
340     }
341     fn dollar_crate(span: Span) -> Ident {
342         // `$crate` is accepted as an ident only if it comes from the compiler.
343         Ident { sym: kw::DollarCrate, is_raw: false, span }
344     }
345 }
346
347 // FIXME(eddyb) `Literal` should not expose internal `Debug` impls.
348 #[derive(Clone, Debug)]
349 pub struct Literal {
350     lit: token::Lit,
351     span: Span,
352 }
353
354 pub(crate) struct Rustc<'a> {
355     sess: &'a ParseSess,
356     def_site: Span,
357     call_site: Span,
358 }
359
360 impl<'a> Rustc<'a> {
361     pub fn new(cx: &'a ExtCtxt<'_>) -> Self {
362         let expn_data = cx.current_expansion.id.expn_data();
363         Rustc {
364             sess: cx.parse_sess,
365             def_site: cx.with_def_site_ctxt(expn_data.def_site),
366             call_site: cx.with_call_site_ctxt(expn_data.call_site),
367         }
368     }
369
370     fn lit(&mut self, kind: token::LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Literal {
371         Literal {
372             lit: token::Lit::new(kind, symbol, suffix),
373             span: server::Span::call_site(self),
374         }
375     }
376 }
377
378 impl server::Types for Rustc<'_> {
379     type TokenStream = TokenStream;
380     type TokenStreamBuilder = tokenstream::TokenStreamBuilder;
381     type TokenStreamIter = TokenStreamIter;
382     type Group = Group;
383     type Punct = Punct;
384     type Ident = Ident;
385     type Literal = Literal;
386     type SourceFile = Lrc<SourceFile>;
387     type MultiSpan = Vec<Span>;
388     type Diagnostic = Diagnostic;
389     type Span = Span;
390 }
391
392 impl server::TokenStream for Rustc<'_> {
393     fn new(&mut self) -> Self::TokenStream {
394         TokenStream::empty()
395     }
396     fn is_empty(&mut self, stream: &Self::TokenStream) -> bool {
397         stream.is_empty()
398     }
399     fn from_str(&mut self, src: &str) -> Self::TokenStream {
400         parse::parse_stream_from_source_str(
401             FileName::proc_macro_source_code(src),
402             src.to_string(),
403             self.sess,
404             Some(self.call_site),
405         )
406     }
407     fn to_string(&mut self, stream: &Self::TokenStream) -> String {
408         stream.to_string()
409     }
410     fn from_token_tree(
411         &mut self,
412         tree: TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>,
413     ) -> Self::TokenStream {
414         tree.to_internal()
415     }
416     fn into_iter(&mut self, stream: Self::TokenStream) -> Self::TokenStreamIter {
417         TokenStreamIter {
418             cursor: stream.trees(),
419             stack: vec![],
420         }
421     }
422 }
423
424 impl server::TokenStreamBuilder for Rustc<'_> {
425     fn new(&mut self) -> Self::TokenStreamBuilder {
426         tokenstream::TokenStreamBuilder::new()
427     }
428     fn push(&mut self, builder: &mut Self::TokenStreamBuilder, stream: Self::TokenStream) {
429         builder.push(stream);
430     }
431     fn build(&mut self, builder: Self::TokenStreamBuilder) -> Self::TokenStream {
432         builder.build()
433     }
434 }
435
436 impl server::TokenStreamIter for Rustc<'_> {
437     fn next(
438         &mut self,
439         iter: &mut Self::TokenStreamIter,
440     ) -> Option<TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>> {
441         loop {
442             let tree = iter.stack.pop().or_else(|| {
443                 let next = iter.cursor.next_with_joint()?;
444                 Some(TokenTree::from_internal((next, self.sess, &mut iter.stack)))
445             })?;
446             // HACK: The condition "dummy span + group with empty delimiter" represents an AST
447             // fragment approximately converted into a token stream. This may happen, for
448             // example, with inputs to proc macro attributes, including derives. Such "groups"
449             // need to flattened during iteration over stream's token trees.
450             // Eventually this needs to be removed in favor of keeping original token trees
451             // and not doing the roundtrip through AST.
452             if let TokenTree::Group(ref group) = tree {
453                 if group.delimiter == Delimiter::None && group.span.entire().is_dummy() {
454                     iter.cursor.append(group.stream.clone());
455                     continue;
456                 }
457             }
458             return Some(tree);
459         }
460     }
461 }
462
463 impl server::Group for Rustc<'_> {
464     fn new(&mut self, delimiter: Delimiter, stream: Self::TokenStream) -> Self::Group {
465         Group {
466             delimiter,
467             stream,
468             span: DelimSpan::from_single(server::Span::call_site(self)),
469         }
470     }
471     fn delimiter(&mut self, group: &Self::Group) -> Delimiter {
472         group.delimiter
473     }
474     fn stream(&mut self, group: &Self::Group) -> Self::TokenStream {
475         group.stream.clone()
476     }
477     fn span(&mut self, group: &Self::Group) -> Self::Span {
478         group.span.entire()
479     }
480     fn span_open(&mut self, group: &Self::Group) -> Self::Span {
481         group.span.open
482     }
483     fn span_close(&mut self, group: &Self::Group) -> Self::Span {
484         group.span.close
485     }
486     fn set_span(&mut self, group: &mut Self::Group, span: Self::Span) {
487         group.span = DelimSpan::from_single(span);
488     }
489 }
490
491 impl server::Punct for Rustc<'_> {
492     fn new(&mut self, ch: char, spacing: Spacing) -> Self::Punct {
493         Punct::new(ch, spacing == Spacing::Joint, server::Span::call_site(self))
494     }
495     fn as_char(&mut self, punct: Self::Punct) -> char {
496         punct.ch
497     }
498     fn spacing(&mut self, punct: Self::Punct) -> Spacing {
499         if punct.joint {
500             Spacing::Joint
501         } else {
502             Spacing::Alone
503         }
504     }
505     fn span(&mut self, punct: Self::Punct) -> Self::Span {
506         punct.span
507     }
508     fn with_span(&mut self, punct: Self::Punct, span: Self::Span) -> Self::Punct {
509         Punct { span, ..punct }
510     }
511 }
512
513 impl server::Ident for Rustc<'_> {
514     fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident {
515         Ident::new(Symbol::intern(string), is_raw, span)
516     }
517     fn span(&mut self, ident: Self::Ident) -> Self::Span {
518         ident.span
519     }
520     fn with_span(&mut self, ident: Self::Ident, span: Self::Span) -> Self::Ident {
521         Ident { span, ..ident }
522     }
523 }
524
525 impl server::Literal for Rustc<'_> {
526     // FIXME(eddyb) `Literal` should not expose internal `Debug` impls.
527     fn debug(&mut self, literal: &Self::Literal) -> String {
528         format!("{:?}", literal)
529     }
530     fn integer(&mut self, n: &str) -> Self::Literal {
531         self.lit(token::Integer, Symbol::intern(n), None)
532     }
533     fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal {
534         self.lit(token::Integer, Symbol::intern(n), Some(Symbol::intern(kind)))
535     }
536     fn float(&mut self, n: &str) -> Self::Literal {
537         self.lit(token::Float, Symbol::intern(n), None)
538     }
539     fn f32(&mut self, n: &str) -> Self::Literal {
540         self.lit(token::Float, Symbol::intern(n), Some(sym::f32))
541     }
542     fn f64(&mut self, n: &str) -> Self::Literal {
543         self.lit(token::Float, Symbol::intern(n), Some(sym::f64))
544     }
545     fn string(&mut self, string: &str) -> Self::Literal {
546         let mut escaped = String::new();
547         for ch in string.chars() {
548             escaped.extend(ch.escape_debug());
549         }
550         self.lit(token::Str, Symbol::intern(&escaped), None)
551     }
552     fn character(&mut self, ch: char) -> Self::Literal {
553         let mut escaped = String::new();
554         escaped.extend(ch.escape_unicode());
555         self.lit(token::Char, Symbol::intern(&escaped), None)
556     }
557     fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal {
558         let string = bytes
559             .iter()
560             .cloned()
561             .flat_map(ascii::escape_default)
562             .map(Into::<char>::into)
563             .collect::<String>();
564         self.lit(token::ByteStr, Symbol::intern(&string), None)
565     }
566     fn span(&mut self, literal: &Self::Literal) -> Self::Span {
567         literal.span
568     }
569     fn set_span(&mut self, literal: &mut Self::Literal, span: Self::Span) {
570         literal.span = span;
571     }
572     fn subspan(
573         &mut self,
574         literal: &Self::Literal,
575         start: Bound<usize>,
576         end: Bound<usize>,
577     ) -> Option<Self::Span> {
578         let span = literal.span;
579         let length = span.hi().to_usize() - span.lo().to_usize();
580
581         let start = match start {
582             Bound::Included(lo) => lo,
583             Bound::Excluded(lo) => lo + 1,
584             Bound::Unbounded => 0,
585         };
586
587         let end = match end {
588             Bound::Included(hi) => hi + 1,
589             Bound::Excluded(hi) => hi,
590             Bound::Unbounded => length,
591         };
592
593         // Bounds check the values, preventing addition overflow and OOB spans.
594         if start > u32::max_value() as usize
595             || end > u32::max_value() as usize
596             || (u32::max_value() - start as u32) < span.lo().to_u32()
597             || (u32::max_value() - end as u32) < span.lo().to_u32()
598             || start >= end
599             || end > length
600         {
601             return None;
602         }
603
604         let new_lo = span.lo() + BytePos::from_usize(start);
605         let new_hi = span.lo() + BytePos::from_usize(end);
606         Some(span.with_lo(new_lo).with_hi(new_hi))
607     }
608 }
609
610 impl server::SourceFile for Rustc<'_> {
611     fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
612         Lrc::ptr_eq(file1, file2)
613     }
614     fn path(&mut self, file: &Self::SourceFile) -> String {
615         match file.name {
616             FileName::Real(ref path) => path
617                 .to_str()
618                 .expect("non-UTF8 file path in `proc_macro::SourceFile::path`")
619                 .to_string(),
620             _ => file.name.to_string(),
621         }
622     }
623     fn is_real(&mut self, file: &Self::SourceFile) -> bool {
624         file.is_real_file()
625     }
626 }
627
628 impl server::MultiSpan for Rustc<'_> {
629     fn new(&mut self) -> Self::MultiSpan {
630         vec![]
631     }
632     fn push(&mut self, spans: &mut Self::MultiSpan, span: Self::Span) {
633         spans.push(span)
634     }
635 }
636
637 impl server::Diagnostic for Rustc<'_> {
638     fn new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic {
639         let mut diag = Diagnostic::new(level.to_internal(), msg);
640         diag.set_span(MultiSpan::from_spans(spans));
641         diag
642     }
643     fn sub(
644         &mut self,
645         diag: &mut Self::Diagnostic,
646         level: Level,
647         msg: &str,
648         spans: Self::MultiSpan,
649     ) {
650         diag.sub(level.to_internal(), msg, MultiSpan::from_spans(spans), None);
651     }
652     fn emit(&mut self, diag: Self::Diagnostic) {
653         self.sess.span_diagnostic.emit_diagnostic(&diag);
654     }
655 }
656
657 impl server::Span for Rustc<'_> {
658     fn debug(&mut self, span: Self::Span) -> String {
659         format!("{:?} bytes({}..{})", span.ctxt(), span.lo().0, span.hi().0)
660     }
661     fn def_site(&mut self) -> Self::Span {
662         self.def_site
663     }
664     fn call_site(&mut self) -> Self::Span {
665         self.call_site
666     }
667     fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
668         self.sess.source_map().lookup_char_pos(span.lo()).file
669     }
670     fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
671         span.parent()
672     }
673     fn source(&mut self, span: Self::Span) -> Self::Span {
674         span.source_callsite()
675     }
676     fn start(&mut self, span: Self::Span) -> LineColumn {
677         let loc = self.sess.source_map().lookup_char_pos(span.lo());
678         LineColumn {
679             line: loc.line,
680             column: loc.col.to_usize(),
681         }
682     }
683     fn end(&mut self, span: Self::Span) -> LineColumn {
684         let loc = self.sess.source_map().lookup_char_pos(span.hi());
685         LineColumn {
686             line: loc.line,
687             column: loc.col.to_usize(),
688         }
689     }
690     fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> {
691         let self_loc = self.sess.source_map().lookup_char_pos(first.lo());
692         let other_loc = self.sess.source_map().lookup_char_pos(second.lo());
693
694         if self_loc.file.name != other_loc.file.name {
695             return None;
696         }
697
698         Some(first.to(second))
699     }
700     fn resolved_at(&mut self, span: Self::Span, at: Self::Span) -> Self::Span {
701         span.with_ctxt(at.ctxt())
702     }
703     fn source_text(&mut self,  span: Self::Span) -> Option<String> {
704         self.sess.source_map().span_to_snippet(span).ok()
705     }
706 }