1use std::ops::{Bound, Range};
2use std::sync::Arc;
3
4use ast::token::IdentIsRaw;
5use pm::bridge::{
6 DelimSpan, Diagnostic, ExpnGlobals, Group, Ident, LitKind, Literal, Punct, TokenTree, server,
7};
8use pm::{Delimiter, Level};
9use rustc_ast as ast;
10use rustc_ast::token;
11use rustc_ast::tokenstream::{self, DelimSpacing, Spacing, TokenStream};
12use rustc_ast::util::literal::escape_byte_str_symbol;
13use rustc_ast_pretty::pprust;
14use rustc_data_structures::fx::FxHashMap;
15use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult};
16use rustc_parse::lexer::nfc_normalize;
17use rustc_parse::parser::Parser;
18use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
19use rustc_session::parse::ParseSess;
20use rustc_span::def_id::CrateNum;
21use rustc_span::{BytePos, FileName, Pos, SourceFile, Span, Symbol, sym};
22use smallvec::{SmallVec, smallvec};
23
24use crate::base::ExtCtxt;
25
26trait FromInternal<T> {
27 fn from_internal(x: T) -> Self;
28}
29
30trait ToInternal<T> {
31 fn to_internal(self) -> T;
32}
33
34impl FromInternal<token::Delimiter> for Delimiter {
35 fn from_internal(delim: token::Delimiter) -> Delimiter {
36 match delim {
37 token::Delimiter::Parenthesis => Delimiter::Parenthesis,
38 token::Delimiter::Brace => Delimiter::Brace,
39 token::Delimiter::Bracket => Delimiter::Bracket,
40 token::Delimiter::Invisible(_) => Delimiter::None,
41 }
42 }
43}
44
45impl ToInternal<token::Delimiter> for Delimiter {
46 fn to_internal(self) -> token::Delimiter {
47 match self {
48 Delimiter::Parenthesis => token::Delimiter::Parenthesis,
49 Delimiter::Brace => token::Delimiter::Brace,
50 Delimiter::Bracket => token::Delimiter::Bracket,
51 Delimiter::None => token::Delimiter::Invisible(token::InvisibleOrigin::ProcMacro),
52 }
53 }
54}
55
56impl FromInternal<token::LitKind> for LitKind {
57 fn from_internal(kind: token::LitKind) -> Self {
58 match kind {
59 token::Byte => LitKind::Byte,
60 token::Char => LitKind::Char,
61 token::Integer => LitKind::Integer,
62 token::Float => LitKind::Float,
63 token::Str => LitKind::Str,
64 token::StrRaw(n) => LitKind::StrRaw(n),
65 token::ByteStr => LitKind::ByteStr,
66 token::ByteStrRaw(n) => LitKind::ByteStrRaw(n),
67 token::CStr => LitKind::CStr,
68 token::CStrRaw(n) => LitKind::CStrRaw(n),
69 token::Err(_guar) => {
70 LitKind::ErrWithGuar
74 }
75 token::Bool => unreachable!(),
76 }
77 }
78}
79
80impl ToInternal<token::LitKind> for LitKind {
81 fn to_internal(self) -> token::LitKind {
82 match self {
83 LitKind::Byte => token::Byte,
84 LitKind::Char => token::Char,
85 LitKind::Integer => token::Integer,
86 LitKind::Float => token::Float,
87 LitKind::Str => token::Str,
88 LitKind::StrRaw(n) => token::StrRaw(n),
89 LitKind::ByteStr => token::ByteStr,
90 LitKind::ByteStrRaw(n) => token::ByteStrRaw(n),
91 LitKind::CStr => token::CStr,
92 LitKind::CStrRaw(n) => token::CStrRaw(n),
93 LitKind::ErrWithGuar => {
94 #[allow(deprecated)]
100 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
101 token::Err(guar)
102 }
103 }
104 }
105}
106
107impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStream, Span, Symbol>> {
108 fn from_internal((stream, rustc): (TokenStream, &mut Rustc<'_, '_>)) -> Self {
109 use rustc_ast::token::*;
110
111 let mut trees = Vec::with_capacity(stream.len().next_power_of_two());
114 let mut iter = stream.iter();
115
116 while let Some(tree) = iter.next() {
117 let (Token { kind, span }, joint) = match tree.clone() {
118 tokenstream::TokenTree::Delimited(span, _, delim, tts) => {
119 let delimiter = pm::Delimiter::from_internal(delim);
120 trees.push(TokenTree::Group(Group {
121 delimiter,
122 stream: Some(tts),
123 span: DelimSpan {
124 open: span.open,
125 close: span.close,
126 entire: span.entire(),
127 },
128 }));
129 continue;
130 }
131 tokenstream::TokenTree::Token(token, spacing) => {
132 let joint = match spacing {
142 Spacing::Alone | Spacing::JointHidden => false,
143 Spacing::Joint => true,
144 };
145 (token, joint)
146 }
147 };
148
149 let mut op = |s: &str| {
153 assert!(s.is_ascii());
154 trees.extend(s.bytes().enumerate().map(|(i, ch)| {
155 let is_final = i == s.len() - 1;
156 let span = if (span.hi() - span.lo()).to_usize() == s.len() {
162 let lo = span.lo() + BytePos::from_usize(i);
163 let hi = lo + BytePos::from_usize(1);
164 span.with_lo(lo).with_hi(hi)
165 } else {
166 span
167 };
168 let joint = if is_final { joint } else { true };
169 TokenTree::Punct(Punct { ch, joint, span })
170 }));
171 };
172
173 match kind {
174 Eq => op("="),
175 Lt => op("<"),
176 Le => op("<="),
177 EqEq => op("=="),
178 Ne => op("!="),
179 Ge => op(">="),
180 Gt => op(">"),
181 AndAnd => op("&&"),
182 OrOr => op("||"),
183 Not => op("!"),
184 Tilde => op("~"),
185 BinOp(Plus) => op("+"),
186 BinOp(Minus) => op("-"),
187 BinOp(Star) => op("*"),
188 BinOp(Slash) => op("/"),
189 BinOp(Percent) => op("%"),
190 BinOp(Caret) => op("^"),
191 BinOp(And) => op("&"),
192 BinOp(Or) => op("|"),
193 BinOp(Shl) => op("<<"),
194 BinOp(Shr) => op(">>"),
195 BinOpEq(Plus) => op("+="),
196 BinOpEq(Minus) => op("-="),
197 BinOpEq(Star) => op("*="),
198 BinOpEq(Slash) => op("/="),
199 BinOpEq(Percent) => op("%="),
200 BinOpEq(Caret) => op("^="),
201 BinOpEq(And) => op("&="),
202 BinOpEq(Or) => op("|="),
203 BinOpEq(Shl) => op("<<="),
204 BinOpEq(Shr) => op(">>="),
205 At => op("@"),
206 Dot => op("."),
207 DotDot => op(".."),
208 DotDotDot => op("..."),
209 DotDotEq => op("..="),
210 Comma => op(","),
211 Semi => op(";"),
212 Colon => op(":"),
213 PathSep => op("::"),
214 RArrow => op("->"),
215 LArrow => op("<-"),
216 FatArrow => op("=>"),
217 Pound => op("#"),
218 Dollar => op("$"),
219 Question => op("?"),
220 SingleQuote => op("'"),
221
222 Ident(sym, is_raw) => {
223 trees.push(TokenTree::Ident(Ident { sym, is_raw: is_raw.into(), span }))
224 }
225 NtIdent(ident, is_raw) => trees.push(TokenTree::Ident(Ident {
226 sym: ident.name,
227 is_raw: is_raw.into(),
228 span: ident.span,
229 })),
230
231 Lifetime(name, is_raw) => {
232 let ident = rustc_span::Ident::new(name, span).without_first_quote();
233 trees.extend([
234 TokenTree::Punct(Punct { ch: b'\'', joint: true, span }),
235 TokenTree::Ident(Ident { sym: ident.name, is_raw: is_raw.into(), span }),
236 ]);
237 }
238 NtLifetime(ident, is_raw) => {
239 let stream =
240 TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span);
241 trees.push(TokenTree::Group(Group {
242 delimiter: pm::Delimiter::None,
243 stream: Some(stream),
244 span: DelimSpan::from_single(span),
245 }))
246 }
247
248 Literal(token::Lit { kind, symbol, suffix }) => {
249 trees.push(TokenTree::Literal(self::Literal {
250 kind: FromInternal::from_internal(kind),
251 symbol,
252 suffix,
253 span,
254 }));
255 }
256 DocComment(_, attr_style, data) => {
257 let mut escaped = String::new();
258 for ch in data.as_str().chars() {
259 escaped.extend(ch.escape_debug());
260 }
261 let stream = [
262 Ident(sym::doc, IdentIsRaw::No),
263 Eq,
264 TokenKind::lit(token::Str, Symbol::intern(&escaped), None),
265 ]
266 .into_iter()
267 .map(|kind| tokenstream::TokenTree::token_alone(kind, span))
268 .collect();
269 trees.push(TokenTree::Punct(Punct { ch: b'#', joint: false, span }));
270 if attr_style == ast::AttrStyle::Inner {
271 trees.push(TokenTree::Punct(Punct { ch: b'!', joint: false, span }));
272 }
273 trees.push(TokenTree::Group(Group {
274 delimiter: pm::Delimiter::Bracket,
275 stream: Some(stream),
276 span: DelimSpan::from_single(span),
277 }));
278 }
279
280 Interpolated(nt) => {
281 let stream = TokenStream::from_nonterminal_ast(&nt);
282 crate::base::nt_pretty_printing_compatibility_hack(&nt, rustc.ecx.sess);
291 trees.push(TokenTree::Group(Group {
292 delimiter: pm::Delimiter::None,
293 stream: Some(stream),
294 span: DelimSpan::from_single(span),
295 }))
296 }
297
298 OpenDelim(..) | CloseDelim(..) => unreachable!(),
299 Eof => unreachable!(),
300 }
301 }
302 trees
303 }
304}
305
306impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>>
308 for (TokenTree<TokenStream, Span, Symbol>, &mut Rustc<'_, '_>)
309{
310 fn to_internal(self) -> SmallVec<[tokenstream::TokenTree; 2]> {
311 use rustc_ast::token::*;
312
313 let (tree, rustc) = self;
319 match tree {
320 TokenTree::Punct(Punct { ch, joint, span }) => {
321 let kind = match ch {
322 b'=' => Eq,
323 b'<' => Lt,
324 b'>' => Gt,
325 b'!' => Not,
326 b'~' => Tilde,
327 b'+' => BinOp(Plus),
328 b'-' => BinOp(Minus),
329 b'*' => BinOp(Star),
330 b'/' => BinOp(Slash),
331 b'%' => BinOp(Percent),
332 b'^' => BinOp(Caret),
333 b'&' => BinOp(And),
334 b'|' => BinOp(Or),
335 b'@' => At,
336 b'.' => Dot,
337 b',' => Comma,
338 b';' => Semi,
339 b':' => Colon,
340 b'#' => Pound,
341 b'$' => Dollar,
342 b'?' => Question,
343 b'\'' => SingleQuote,
344 _ => unreachable!(),
345 };
346 smallvec![if joint {
352 tokenstream::TokenTree::token_joint(kind, span)
353 } else {
354 tokenstream::TokenTree::token_alone(kind, span)
355 }]
356 }
357 TokenTree::Group(Group { delimiter, stream, span: DelimSpan { open, close, .. } }) => {
358 smallvec![tokenstream::TokenTree::Delimited(
359 tokenstream::DelimSpan { open, close },
360 DelimSpacing::new(Spacing::Alone, Spacing::Alone),
361 delimiter.to_internal(),
362 stream.unwrap_or_default(),
363 )]
364 }
365 TokenTree::Ident(self::Ident { sym, is_raw, span }) => {
366 rustc.psess().symbol_gallery.insert(sym, span);
367 smallvec![tokenstream::TokenTree::token_alone(Ident(sym, is_raw.into()), span)]
368 }
369 TokenTree::Literal(self::Literal {
370 kind: self::LitKind::Integer,
371 symbol,
372 suffix,
373 span,
374 }) if symbol.as_str().starts_with('-') => {
375 let minus = BinOp(BinOpToken::Minus);
376 let symbol = Symbol::intern(&symbol.as_str()[1..]);
377 let integer = TokenKind::lit(token::Integer, symbol, suffix);
378 let a = tokenstream::TokenTree::token_joint_hidden(minus, span);
379 let b = tokenstream::TokenTree::token_alone(integer, span);
380 smallvec![a, b]
381 }
382 TokenTree::Literal(self::Literal {
383 kind: self::LitKind::Float,
384 symbol,
385 suffix,
386 span,
387 }) if symbol.as_str().starts_with('-') => {
388 let minus = BinOp(BinOpToken::Minus);
389 let symbol = Symbol::intern(&symbol.as_str()[1..]);
390 let float = TokenKind::lit(token::Float, symbol, suffix);
391 let a = tokenstream::TokenTree::token_joint_hidden(minus, span);
392 let b = tokenstream::TokenTree::token_alone(float, span);
393 smallvec![a, b]
394 }
395 TokenTree::Literal(self::Literal { kind, symbol, suffix, span }) => {
396 smallvec![tokenstream::TokenTree::token_alone(
397 TokenKind::lit(kind.to_internal(), symbol, suffix),
398 span,
399 )]
400 }
401 }
402 }
403}
404
405impl ToInternal<rustc_errors::Level> for Level {
406 fn to_internal(self) -> rustc_errors::Level {
407 match self {
408 Level::Error => rustc_errors::Level::Error,
409 Level::Warning => rustc_errors::Level::Warning,
410 Level::Note => rustc_errors::Level::Note,
411 Level::Help => rustc_errors::Level::Help,
412 _ => unreachable!("unknown proc_macro::Level variant: {:?}", self),
413 }
414 }
415}
416
417pub(crate) struct FreeFunctions;
418
419pub(crate) struct Rustc<'a, 'b> {
420 ecx: &'a mut ExtCtxt<'b>,
421 def_site: Span,
422 call_site: Span,
423 mixed_site: Span,
424 krate: CrateNum,
425 rebased_spans: FxHashMap<usize, Span>,
426}
427
428impl<'a, 'b> Rustc<'a, 'b> {
429 pub(crate) fn new(ecx: &'a mut ExtCtxt<'b>) -> Self {
430 let expn_data = ecx.current_expansion.id.expn_data();
431 Rustc {
432 def_site: ecx.with_def_site_ctxt(expn_data.def_site),
433 call_site: ecx.with_call_site_ctxt(expn_data.call_site),
434 mixed_site: ecx.with_mixed_site_ctxt(expn_data.call_site),
435 krate: expn_data.macro_def_id.unwrap().krate,
436 rebased_spans: FxHashMap::default(),
437 ecx,
438 }
439 }
440
441 fn psess(&self) -> &ParseSess {
442 self.ecx.psess()
443 }
444}
445
446impl server::Types for Rustc<'_, '_> {
447 type FreeFunctions = FreeFunctions;
448 type TokenStream = TokenStream;
449 type SourceFile = Arc<SourceFile>;
450 type Span = Span;
451 type Symbol = Symbol;
452}
453
454impl server::FreeFunctions for Rustc<'_, '_> {
455 fn injected_env_var(&mut self, var: &str) -> Option<String> {
456 self.ecx.sess.opts.logical_env.get(var).cloned()
457 }
458
459 fn track_env_var(&mut self, var: &str, value: Option<&str>) {
460 self.psess()
461 .env_depinfo
462 .borrow_mut()
463 .insert((Symbol::intern(var), value.map(Symbol::intern)));
464 }
465
466 fn track_path(&mut self, path: &str) {
467 self.psess().file_depinfo.borrow_mut().insert(Symbol::intern(path));
468 }
469
470 fn literal_from_str(&mut self, s: &str) -> Result<Literal<Self::Span, Self::Symbol>, ()> {
471 let name = FileName::proc_macro_source_code(s);
472 let mut parser =
473 unwrap_or_emit_fatal(new_parser_from_source_str(self.psess(), name, s.to_owned()));
474
475 let first_span = parser.token.span.data();
476 let minus_present = parser.eat(exp!(Minus));
477
478 let lit_span = parser.token.span.data();
479 let token::Literal(mut lit) = parser.token.kind else {
480 return Err(());
481 };
482
483 if (lit_span.hi.0 - first_span.lo.0) as usize != s.len() {
486 return Err(());
487 }
488
489 if minus_present {
490 if first_span.hi.0 != lit_span.lo.0 {
493 return Err(());
494 }
495
496 match lit.kind {
498 token::LitKind::Bool
499 | token::LitKind::Byte
500 | token::LitKind::Char
501 | token::LitKind::Str
502 | token::LitKind::StrRaw(_)
503 | token::LitKind::ByteStr
504 | token::LitKind::ByteStrRaw(_)
505 | token::LitKind::CStr
506 | token::LitKind::CStrRaw(_)
507 | token::LitKind::Err(_) => return Err(()),
508 token::LitKind::Integer | token::LitKind::Float => {}
509 }
510
511 let symbol = Symbol::intern(&s[..1 + lit.symbol.as_str().len()]);
513 lit = token::Lit::new(lit.kind, symbol, lit.suffix);
514 }
515 let token::Lit { kind, symbol, suffix } = lit;
516 Ok(Literal {
517 kind: FromInternal::from_internal(kind),
518 symbol,
519 suffix,
520 span: self.call_site,
521 })
522 }
523
524 fn emit_diagnostic(&mut self, diagnostic: Diagnostic<Self::Span>) {
525 let message = rustc_errors::DiagMessage::from(diagnostic.message);
526 let mut diag: Diag<'_, ()> =
527 Diag::new(self.psess().dcx(), diagnostic.level.to_internal(), message);
528 diag.span(MultiSpan::from_spans(diagnostic.spans));
529 for child in diagnostic.children {
530 #[allow(rustc::untranslatable_diagnostic)]
533 diag.sub(child.level.to_internal(), child.message, MultiSpan::from_spans(child.spans));
534 }
535 diag.emit();
536 }
537}
538
539impl server::TokenStream for Rustc<'_, '_> {
540 fn is_empty(&mut self, stream: &Self::TokenStream) -> bool {
541 stream.is_empty()
542 }
543
544 fn from_str(&mut self, src: &str) -> Self::TokenStream {
545 unwrap_or_emit_fatal(source_str_to_stream(
546 self.psess(),
547 FileName::proc_macro_source_code(src),
548 src.to_string(),
549 Some(self.call_site),
550 ))
551 }
552
553 fn to_string(&mut self, stream: &Self::TokenStream) -> String {
554 pprust::tts_to_string(stream)
555 }
556
557 fn expand_expr(&mut self, stream: &Self::TokenStream) -> Result<Self::TokenStream, ()> {
558 let expr: PResult<'_, _> = try {
560 let mut p = Parser::new(self.psess(), stream.clone(), Some("proc_macro expand expr"));
561 let expr = p.parse_expr()?;
562 if p.token != token::Eof {
563 p.unexpected()?;
564 }
565 expr
566 };
567 let expr = expr.map_err(|err| {
568 err.emit();
569 })?;
570
571 let expr = self
573 .ecx
574 .expander()
575 .fully_expand_fragment(crate::expand::AstFragment::Expr(expr))
576 .make_expr();
577
578 match &expr.kind {
583 ast::ExprKind::Lit(token_lit) if token_lit.kind == token::Bool => {
584 Ok(tokenstream::TokenStream::token_alone(
585 token::Ident(token_lit.symbol, IdentIsRaw::No),
586 expr.span,
587 ))
588 }
589 ast::ExprKind::Lit(token_lit) => {
590 Ok(tokenstream::TokenStream::token_alone(token::Literal(*token_lit), expr.span))
591 }
592 ast::ExprKind::IncludedBytes(bytes) => {
593 let lit = token::Lit::new(token::ByteStr, escape_byte_str_symbol(bytes), None);
594 Ok(tokenstream::TokenStream::token_alone(token::TokenKind::Literal(lit), expr.span))
595 }
596 ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind {
597 ast::ExprKind::Lit(token_lit) => match token_lit {
598 token::Lit { kind: token::Integer | token::Float, .. } => {
599 Ok(Self::TokenStream::from_iter([
600 tokenstream::TokenTree::token_joint_hidden(
603 token::BinOp(token::Minus),
604 e.span,
605 ),
606 tokenstream::TokenTree::token_alone(token::Literal(*token_lit), e.span),
607 ]))
608 }
609 _ => Err(()),
610 },
611 _ => Err(()),
612 },
613 _ => Err(()),
614 }
615 }
616
617 fn from_token_tree(
618 &mut self,
619 tree: TokenTree<Self::TokenStream, Self::Span, Self::Symbol>,
620 ) -> Self::TokenStream {
621 Self::TokenStream::new((tree, &mut *self).to_internal().into_iter().collect::<Vec<_>>())
622 }
623
624 fn concat_trees(
625 &mut self,
626 base: Option<Self::TokenStream>,
627 trees: Vec<TokenTree<Self::TokenStream, Self::Span, Self::Symbol>>,
628 ) -> Self::TokenStream {
629 let mut stream = base.unwrap_or_default();
630 for tree in trees {
631 for tt in (tree, &mut *self).to_internal() {
632 stream.push_tree(tt);
633 }
634 }
635 stream
636 }
637
638 fn concat_streams(
639 &mut self,
640 base: Option<Self::TokenStream>,
641 streams: Vec<Self::TokenStream>,
642 ) -> Self::TokenStream {
643 let mut stream = base.unwrap_or_default();
644 for s in streams {
645 stream.push_stream(s);
646 }
647 stream
648 }
649
650 fn into_trees(
651 &mut self,
652 stream: Self::TokenStream,
653 ) -> Vec<TokenTree<Self::TokenStream, Self::Span, Self::Symbol>> {
654 FromInternal::from_internal((stream, self))
655 }
656}
657
658impl server::SourceFile for Rustc<'_, '_> {
659 fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
660 Arc::ptr_eq(file1, file2)
661 }
662
663 fn path(&mut self, file: &Self::SourceFile) -> String {
664 match &file.name {
665 FileName::Real(name) => name
666 .local_path()
667 .expect("attempting to get a file path in an imported file in `proc_macro::SourceFile::path`")
668 .to_str()
669 .expect("non-UTF8 file path in `proc_macro::SourceFile::path`")
670 .to_string(),
671 _ => file.name.prefer_local().to_string(),
672 }
673 }
674
675 fn is_real(&mut self, file: &Self::SourceFile) -> bool {
676 file.is_real_file()
677 }
678}
679
680impl server::Span for Rustc<'_, '_> {
681 fn debug(&mut self, span: Self::Span) -> String {
682 if self.ecx.ecfg.span_debug {
683 format!("{span:?}")
684 } else {
685 format!("{:?} bytes({}..{})", span.ctxt(), span.lo().0, span.hi().0)
686 }
687 }
688
689 fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
690 self.psess().source_map().lookup_char_pos(span.lo()).file
691 }
692
693 fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
694 span.parent_callsite()
695 }
696
697 fn source(&mut self, span: Self::Span) -> Self::Span {
698 span.source_callsite()
699 }
700
701 fn byte_range(&mut self, span: Self::Span) -> Range<usize> {
702 let source_map = self.psess().source_map();
703
704 let relative_start_pos = source_map.lookup_byte_offset(span.lo()).pos;
705 let relative_end_pos = source_map.lookup_byte_offset(span.hi()).pos;
706
707 Range { start: relative_start_pos.0 as usize, end: relative_end_pos.0 as usize }
708 }
709 fn start(&mut self, span: Self::Span) -> Self::Span {
710 span.shrink_to_lo()
711 }
712
713 fn end(&mut self, span: Self::Span) -> Self::Span {
714 span.shrink_to_hi()
715 }
716
717 fn line(&mut self, span: Self::Span) -> usize {
718 let loc = self.psess().source_map().lookup_char_pos(span.lo());
719 loc.line
720 }
721
722 fn column(&mut self, span: Self::Span) -> usize {
723 let loc = self.psess().source_map().lookup_char_pos(span.lo());
724 loc.col.to_usize() + 1
725 }
726
727 fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> {
728 let self_loc = self.psess().source_map().lookup_char_pos(first.lo());
729 let other_loc = self.psess().source_map().lookup_char_pos(second.lo());
730
731 if self_loc.file.name != other_loc.file.name {
732 return None;
733 }
734
735 Some(first.to(second))
736 }
737
738 fn subspan(
739 &mut self,
740 span: Self::Span,
741 start: Bound<usize>,
742 end: Bound<usize>,
743 ) -> Option<Self::Span> {
744 let length = span.hi().to_usize() - span.lo().to_usize();
745
746 let start = match start {
747 Bound::Included(lo) => lo,
748 Bound::Excluded(lo) => lo.checked_add(1)?,
749 Bound::Unbounded => 0,
750 };
751
752 let end = match end {
753 Bound::Included(hi) => hi.checked_add(1)?,
754 Bound::Excluded(hi) => hi,
755 Bound::Unbounded => length,
756 };
757
758 if start > u32::MAX as usize
760 || end > u32::MAX as usize
761 || (u32::MAX - start as u32) < span.lo().to_u32()
762 || (u32::MAX - end as u32) < span.lo().to_u32()
763 || start >= end
764 || end > length
765 {
766 return None;
767 }
768
769 let new_lo = span.lo() + BytePos::from_usize(start);
770 let new_hi = span.lo() + BytePos::from_usize(end);
771 Some(span.with_lo(new_lo).with_hi(new_hi))
772 }
773
774 fn resolved_at(&mut self, span: Self::Span, at: Self::Span) -> Self::Span {
775 span.with_ctxt(at.ctxt())
776 }
777
778 fn source_text(&mut self, span: Self::Span) -> Option<String> {
779 self.psess().source_map().span_to_snippet(span).ok()
780 }
781
782 fn save_span(&mut self, span: Self::Span) -> usize {
807 self.psess().save_proc_macro_span(span)
808 }
809
810 fn recover_proc_macro_span(&mut self, id: usize) -> Self::Span {
811 let (resolver, krate, def_site) = (&*self.ecx.resolver, self.krate, self.def_site);
812 *self.rebased_spans.entry(id).or_insert_with(|| {
813 resolver.get_proc_macro_quoted_span(krate, id).with_ctxt(def_site.ctxt())
816 })
817 }
818}
819
820impl server::Symbol for Rustc<'_, '_> {
821 fn normalize_and_validate_ident(&mut self, string: &str) -> Result<Self::Symbol, ()> {
822 let sym = nfc_normalize(string);
823 if rustc_lexer::is_ident(sym.as_str()) { Ok(sym) } else { Err(()) }
824 }
825}
826
827impl server::Server for Rustc<'_, '_> {
828 fn globals(&mut self) -> ExpnGlobals<Self::Span> {
829 ExpnGlobals {
830 def_site: self.def_site,
831 call_site: self.call_site,
832 mixed_site: self.mixed_site,
833 }
834 }
835
836 fn intern_symbol(string: &str) -> Self::Symbol {
837 Symbol::intern(string)
838 }
839
840 fn with_symbol_string(symbol: &Self::Symbol, f: impl FnOnce(&str)) {
841 f(symbol.as_str())
842 }
843}