Skip to content

Commit 2f88655

Browse files
committedMar 4, 2015
Encode codemap and span information in crate metadata.
This allows to create proper debuginfo line information for items inlined from other crates (e.g. instantiations of generics). Only the codemap's 'metadata' is stored in a crate's metadata. That is, just filename, line-beginnings, etc. but not the actual source code itself. We are thus missing the opportunity of making Rust the first "open-source-only" programming language out there. Pity.
1 parent fed1249 commit 2f88655

File tree

12 files changed

+693
-172
lines changed

12 files changed

+693
-172
lines changed
 

‎src/librustc/metadata/common.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,6 @@ pub const tag_macro_def: uint = 0x9e;
252252
pub const tag_macro_def_body: uint = 0x9f;
253253

254254
pub const tag_paren_sugar: uint = 0xa0;
255+
256+
pub const tag_codemap: uint = 0xa1;
257+
pub const tag_codemap_filemap: uint = 0xa2;

‎src/librustc/metadata/creader.rs

Lines changed: 133 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use syntax::ast;
2626
use syntax::abi;
2727
use syntax::attr;
2828
use syntax::attr::AttrMetaMethods;
29-
use syntax::codemap::{Span, mk_sp};
29+
use syntax::codemap::{self, Span, mk_sp, Pos};
3030
use syntax::parse;
3131
use syntax::parse::token::InternedString;
3232
use syntax::parse::token;
@@ -373,15 +373,17 @@ impl<'a> CrateReader<'a> {
373373
// Maintain a reference to the top most crate.
374374
let root = if root.is_some() { root } else { &crate_paths };
375375

376-
let cnum_map = self.resolve_crate_deps(root, lib.metadata.as_slice(), span);
376+
let loader::Library { dylib, rlib, metadata } = lib;
377377

378-
let loader::Library{ dylib, rlib, metadata } = lib;
378+
let cnum_map = self.resolve_crate_deps(root, metadata.as_slice(), span);
379+
let codemap_import_info = import_codemap(self.sess.codemap(), &metadata);
379380

380381
let cmeta = Rc::new( cstore::crate_metadata {
381382
name: name.to_string(),
382383
data: metadata,
383384
cnum_map: cnum_map,
384385
cnum: cnum,
386+
codemap_import_info: codemap_import_info,
385387
span: span,
386388
});
387389

@@ -586,3 +588,131 @@ impl<'a> CrateReader<'a> {
586588
}
587589
}
588590
}
591+
592+
/// Imports the codemap from an external crate into the codemap of the crate
593+
/// currently being compiled (the "local crate").
594+
///
595+
/// The import algorithm works analogous to how AST items are inlined from an
596+
/// external crate's metadata:
597+
/// For every FileMap in the external codemap an 'inline' copy is created in the
598+
/// local codemap. The correspondence relation between external and local
599+
/// FileMaps is recorded in the `ImportedFileMap` objects returned from this
600+
/// function. When an item from an external crate is later inlined into this
601+
/// crate, this correspondence information is used to translate the span
602+
/// information of the inlined item so that it refers the correct positions in
603+
/// the local codemap (see `astencode::DecodeContext::tr_span()`).
604+
///
605+
/// The import algorithm in the function below will reuse FileMaps already
606+
/// existing in the local codemap. For example, even if the FileMap of some
607+
/// source file of libstd gets imported many times, there will only ever be
608+
/// one FileMap object for the corresponding file in the local codemap.
609+
///
610+
/// Note that imported FileMaps do not actually contain the source code of the
611+
/// file they represent, just information about length, line breaks, and
612+
/// multibyte characters. This information is enough to generate valid debuginfo
613+
/// for items inlined from other crates.
614+
fn import_codemap(local_codemap: &codemap::CodeMap,
615+
metadata: &MetadataBlob)
616+
-> Vec<cstore::ImportedFileMap> {
617+
let external_codemap = decoder::get_imported_filemaps(metadata.as_slice());
618+
619+
let imported_filemaps = external_codemap.into_iter().map(|filemap_to_import| {
620+
// Try to find an existing FileMap that can be reused for the filemap to
621+
// be imported. A FileMap is reusable if it is exactly the same, just
622+
// positioned at a different offset within the codemap.
623+
let reusable_filemap = {
624+
local_codemap.files
625+
.borrow()
626+
.iter()
627+
.find(|fm| are_equal_modulo_startpos(&fm, &filemap_to_import))
628+
.map(|rc| rc.clone())
629+
};
630+
631+
match reusable_filemap {
632+
Some(fm) => {
633+
cstore::ImportedFileMap {
634+
original_start_pos: filemap_to_import.start_pos,
635+
original_end_pos: filemap_to_import.end_pos,
636+
translated_filemap: fm
637+
}
638+
}
639+
None => {
640+
// We can't reuse an existing FileMap, so allocate a new one
641+
// containing the information we need.
642+
let codemap::FileMap {
643+
name,
644+
start_pos,
645+
end_pos,
646+
lines,
647+
multibyte_chars,
648+
..
649+
} = filemap_to_import;
650+
651+
let source_length = (end_pos - start_pos).to_usize();
652+
653+
// Translate line-start positions and multibyte character
654+
// position into frame of reference local to file.
655+
// `CodeMap::new_imported_filemap()` will then translate those
656+
// coordinates to their new global frame of reference when the
657+
// offset of the FileMap is known.
658+
let lines = lines.into_inner().map_in_place(|pos| pos - start_pos);
659+
let multibyte_chars = multibyte_chars
660+
.into_inner()
661+
.map_in_place(|mbc|
662+
codemap::MultiByteChar {
663+
pos: mbc.pos + start_pos,
664+
bytes: mbc.bytes
665+
});
666+
667+
let local_version = local_codemap.new_imported_filemap(name,
668+
source_length,
669+
lines,
670+
multibyte_chars);
671+
cstore::ImportedFileMap {
672+
original_start_pos: start_pos,
673+
original_end_pos: end_pos,
674+
translated_filemap: local_version
675+
}
676+
}
677+
}
678+
}).collect();
679+
680+
return imported_filemaps;
681+
682+
fn are_equal_modulo_startpos(fm1: &codemap::FileMap,
683+
fm2: &codemap::FileMap)
684+
-> bool {
685+
if fm1.name != fm2.name {
686+
return false;
687+
}
688+
689+
let lines1 = fm1.lines.borrow();
690+
let lines2 = fm2.lines.borrow();
691+
692+
if lines1.len() != lines2.len() {
693+
return false;
694+
}
695+
696+
for (&line1, &line2) in lines1.iter().zip(lines2.iter()) {
697+
if (line1 - fm1.start_pos) != (line2 - fm2.start_pos) {
698+
return false;
699+
}
700+
}
701+
702+
let multibytes1 = fm1.multibyte_chars.borrow();
703+
let multibytes2 = fm2.multibyte_chars.borrow();
704+
705+
if multibytes1.len() != multibytes2.len() {
706+
return false;
707+
}
708+
709+
for (mb1, mb2) in multibytes1.iter().zip(multibytes2.iter()) {
710+
if (mb1.bytes != mb2.bytes) ||
711+
((mb1.pos - fm1.start_pos) != (mb2.pos - fm2.start_pos)) {
712+
return false;
713+
}
714+
}
715+
716+
true
717+
}
718+
}

‎src/librustc/metadata/cstore.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use std::cell::RefCell;
2727
use std::rc::Rc;
2828
use flate::Bytes;
2929
use syntax::ast;
30-
use syntax::codemap::Span;
30+
use syntax::codemap;
3131
use syntax::parse::token::IdentInterner;
3232

3333
// A map from external crate numbers (as decoded from some crate file) to
@@ -41,12 +41,24 @@ pub enum MetadataBlob {
4141
MetadataArchive(loader::ArchiveMetadata),
4242
}
4343

44+
/// Holds information about a codemap::FileMap imported from another crate.
45+
/// See creader::import_codemap() for more information.
46+
pub struct ImportedFileMap {
47+
/// This FileMap's byte-offset within the codemap of its original crate
48+
pub original_start_pos: codemap::BytePos,
49+
/// The end of this FileMap within the codemap of its original crate
50+
pub original_end_pos: codemap::BytePos,
51+
/// The imported FileMap's representation within the local codemap
52+
pub translated_filemap: Rc<codemap::FileMap>
53+
}
54+
4455
pub struct crate_metadata {
4556
pub name: String,
4657
pub data: MetadataBlob,
4758
pub cnum_map: cnum_map,
4859
pub cnum: ast::CrateNum,
49-
pub span: Span,
60+
pub codemap_import_info: Vec<ImportedFileMap>,
61+
pub span: codemap::Span,
5062
}
5163

5264
#[derive(Copy, Debug, PartialEq, Clone)]

‎src/librustc/metadata/decoder.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1561,11 +1561,26 @@ pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool {
15611561
}
15621562
}
15631563

1564-
15651564
pub fn is_default_trait<'tcx>(cdata: Cmd, id: ast::NodeId) -> bool {
15661565
let item_doc = lookup_item(id, cdata.data());
15671566
match item_family(item_doc) {
15681567
Family::DefaultImpl => true,
15691568
_ => false
15701569
}
15711570
}
1571+
1572+
pub fn get_imported_filemaps(metadata: &[u8]) -> Vec<codemap::FileMap> {
1573+
let crate_doc = rbml::Doc::new(metadata);
1574+
let cm_doc = reader::get_doc(crate_doc, tag_codemap);
1575+
1576+
let mut filemaps = vec![];
1577+
1578+
reader::tagged_docs(cm_doc, tag_codemap_filemap, |filemap_doc| {
1579+
let mut decoder = reader::Decoder::new(filemap_doc);
1580+
let filemap: codemap::FileMap = Decodable::decode(&mut decoder).unwrap();
1581+
filemaps.push(filemap);
1582+
true
1583+
});
1584+
1585+
return filemaps;
1586+
}

‎src/librustc/metadata/encoder.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1751,6 +1751,28 @@ fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) {
17511751
}
17521752
}
17531753

1754+
fn encode_codemap(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1755+
rbml_w.start_tag(tag_codemap);
1756+
let codemap = ecx.tcx.sess.codemap();
1757+
1758+
for filemap in &codemap.files.borrow()[..] {
1759+
1760+
if filemap.lines.borrow().len() == 0 || filemap.is_imported() {
1761+
// No need to export empty filemaps, as they can't contain spans
1762+
// that need translation.
1763+
// Also no need to re-export imported filemaps, as any downstream
1764+
// crate will import them from their original source.
1765+
continue;
1766+
}
1767+
1768+
rbml_w.start_tag(tag_codemap_filemap);
1769+
filemap.encode(rbml_w);
1770+
rbml_w.end_tag();
1771+
}
1772+
1773+
rbml_w.end_tag();
1774+
}
1775+
17541776
/// Serialize the text of the exported macros
17551777
fn encode_macro_defs(rbml_w: &mut Encoder,
17561778
krate: &ast::Crate) {
@@ -1968,6 +1990,7 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter,
19681990
lang_item_bytes: u64,
19691991
native_lib_bytes: u64,
19701992
plugin_registrar_fn_bytes: u64,
1993+
codemap_bytes: u64,
19711994
macro_defs_bytes: u64,
19721995
impl_bytes: u64,
19731996
misc_bytes: u64,
@@ -1982,6 +2005,7 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter,
19822005
lang_item_bytes: 0,
19832006
native_lib_bytes: 0,
19842007
plugin_registrar_fn_bytes: 0,
2008+
codemap_bytes: 0,
19852009
macro_defs_bytes: 0,
19862010
impl_bytes: 0,
19872011
misc_bytes: 0,
@@ -2047,6 +2071,11 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter,
20472071
encode_plugin_registrar_fn(&ecx, &mut rbml_w);
20482072
stats.plugin_registrar_fn_bytes = rbml_w.writer.tell().unwrap() - i;
20492073

2074+
// Encode codemap
2075+
i = rbml_w.writer.tell().unwrap();
2076+
encode_codemap(&ecx, &mut rbml_w);
2077+
stats.codemap_bytes = rbml_w.writer.tell().unwrap() - i;
2078+
20502079
// Encode macro definitions
20512080
i = rbml_w.writer.tell().unwrap();
20522081
encode_macro_defs(&mut rbml_w, krate);
@@ -2091,6 +2120,7 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter,
20912120
println!(" lang item bytes: {}", stats.lang_item_bytes);
20922121
println!(" native bytes: {}", stats.native_lib_bytes);
20932122
println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
2123+
println!(" codemap bytes: {}", stats.codemap_bytes);
20942124
println!(" macro def bytes: {}", stats.macro_defs_bytes);
20952125
println!(" impl bytes: {}", stats.impl_bytes);
20962126
println!(" misc bytes: {}", stats.misc_bytes);

‎src/librustc/middle/astencode.rs

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ use syntax;
4242
use std::old_io::Seek;
4343
use std::num::FromPrimitive;
4444
use std::rc::Rc;
45+
use std::cell::Cell;
4546

4647
use rbml::reader;
4748
use rbml::writer::Encoder;
@@ -58,7 +59,9 @@ struct DecodeContext<'a, 'b, 'tcx: 'a> {
5859
tcx: &'a ty::ctxt<'tcx>,
5960
cdata: &'b cstore::crate_metadata,
6061
from_id_range: ast_util::IdRange,
61-
to_id_range: ast_util::IdRange
62+
to_id_range: ast_util::IdRange,
63+
// Cache the last used filemap for translating spans as an optimization.
64+
last_filemap_index: Cell<usize>,
6265
}
6366

6467
trait tr {
@@ -120,6 +123,8 @@ impl<'a, 'b, 'c, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'c, 'tcx> {
120123
}
121124
}
122125

126+
/// Decodes an item from its AST in the cdata's metadata and adds it to the
127+
/// ast-map.
123128
pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
124129
tcx: &ty::ctxt<'tcx>,
125130
path: Vec<ast_map::PathElem>,
@@ -143,7 +148,8 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
143148
cdata: cdata,
144149
tcx: tcx,
145150
from_id_range: from_id_range,
146-
to_id_range: to_id_range
151+
to_id_range: to_id_range,
152+
last_filemap_index: Cell::new(0)
147153
};
148154
let raw_ii = decode_ast(ast_doc);
149155
let ii = ast_map::map_decoded_item(&dcx.tcx.map, path, raw_ii, dcx);
@@ -234,8 +240,47 @@ impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> {
234240
assert_eq!(did.krate, ast::LOCAL_CRATE);
235241
ast::DefId { krate: ast::LOCAL_CRATE, node: self.tr_id(did.node) }
236242
}
237-
pub fn tr_span(&self, _span: Span) -> Span {
238-
codemap::DUMMY_SP // FIXME (#1972): handle span properly
243+
244+
/// Translates a `Span` from an extern crate to the corresponding `Span`
245+
/// within the local crate's codemap. `creader::import_codemap()` will
246+
/// already have allocated any additionally needed FileMaps in the local
247+
/// codemap as a side-effect of creating the crate_metadata's
248+
/// `codemap_import_info`.
249+
pub fn tr_span(&self, span: Span) -> Span {
250+
let imported_filemaps = &self.cdata.codemap_import_info[..];
251+
252+
let filemap_index = {
253+
// Optimize for the case that most spans within a translated item
254+
// originate from the same filemap.
255+
let last_filemap_index = self.last_filemap_index.get();
256+
257+
if span.lo >= imported_filemaps[last_filemap_index].original_start_pos &&
258+
span.hi <= imported_filemaps[last_filemap_index].original_end_pos {
259+
last_filemap_index
260+
} else {
261+
let mut a = 0;
262+
let mut b = imported_filemaps.len();
263+
264+
while b - a > 1 {
265+
let m = (a + b) / 2;
266+
if imported_filemaps[m].original_start_pos > span.lo {
267+
b = m;
268+
} else {
269+
a = m;
270+
}
271+
}
272+
273+
self.last_filemap_index.set(a);
274+
a
275+
}
276+
};
277+
278+
let lo = (span.lo - imported_filemaps[filemap_index].original_start_pos) +
279+
imported_filemaps[filemap_index].translated_filemap.start_pos;
280+
let hi = (span.hi - imported_filemaps[filemap_index].original_start_pos) +
281+
imported_filemaps[filemap_index].translated_filemap.start_pos;
282+
283+
codemap::mk_sp(lo, hi)
239284
}
240285
}
241286

‎src/librustc_driver/pretty.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,11 @@ pub fn pretty_print_input(sess: Session,
542542

543543
let src_name = driver::source_name(input);
544544
let src = sess.codemap().get_filemap(&src_name[..])
545-
.src.as_bytes().to_vec();
545+
.src
546+
.as_ref()
547+
.unwrap()
548+
.as_bytes()
549+
.to_vec();
546550
let mut rdr = MemReader::new(src);
547551

548552
let out = match ofile {

‎src/libsyntax/codemap.rs

Lines changed: 278 additions & 39 deletions
Large diffs are not rendered by default.

‎src/libsyntax/parse/lexer/mod.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ pub struct StringReader<'a> {
7676
// are revised to go directly to token-trees.
7777
/// Is \x00<name>,<ctxt>\x00 is interpreted as encoded ast::Ident?
7878
read_embedded_ident: bool,
79+
80+
// cache a direct reference to the source text, so that we don't have to
81+
// retrieve it via `self.filemap.src.as_ref().unwrap()` all the time.
82+
source_text: Rc<String>
7983
}
8084

8185
impl<'a> Reader for StringReader<'a> {
@@ -141,7 +145,14 @@ pub fn make_reader_with_embedded_idents<'b>(span_diagnostic: &'b SpanHandler,
141145
impl<'a> StringReader<'a> {
142146
/// For comments.rs, which hackily pokes into pos and curr
143147
pub fn new_raw<'b>(span_diagnostic: &'b SpanHandler,
144-
filemap: Rc<codemap::FileMap>) -> StringReader<'b> {
148+
filemap: Rc<codemap::FileMap>) -> StringReader<'b> {
149+
if filemap.src.is_none() {
150+
span_diagnostic.handler.bug(&format!("Cannot lex filemap without source: {}",
151+
filemap.name)[..]);
152+
}
153+
154+
let source_text = (*filemap.src.as_ref().unwrap()).clone();
155+
145156
let mut sr = StringReader {
146157
span_diagnostic: span_diagnostic,
147158
pos: filemap.start_pos,
@@ -153,6 +164,7 @@ impl<'a> StringReader<'a> {
153164
peek_tok: token::Eof,
154165
peek_span: codemap::DUMMY_SP,
155166
read_embedded_ident: false,
167+
source_text: source_text
156168
};
157169
sr.bump();
158170
sr
@@ -213,7 +225,7 @@ impl<'a> StringReader<'a> {
213225
m.push_str(": ");
214226
let from = self.byte_offset(from_pos).to_usize();
215227
let to = self.byte_offset(to_pos).to_usize();
216-
m.push_str(&self.filemap.src[from..to]);
228+
m.push_str(&self.source_text[from..to]);
217229
self.fatal_span_(from_pos, to_pos, &m[..]);
218230
}
219231

@@ -270,9 +282,8 @@ impl<'a> StringReader<'a> {
270282
fn with_str_from_to<T, F>(&self, start: BytePos, end: BytePos, f: F) -> T where
271283
F: FnOnce(&str) -> T,
272284
{
273-
f(&self.filemap.src[
274-
self.byte_offset(start).to_usize()..
275-
self.byte_offset(end).to_usize()])
285+
f(&self.source_text[self.byte_offset(start).to_usize()..
286+
self.byte_offset(end).to_usize()])
276287
}
277288

278289
/// Converts CRLF to LF in the given string, raising an error on bare CR.
@@ -321,12 +332,10 @@ impl<'a> StringReader<'a> {
321332
pub fn bump(&mut self) {
322333
self.last_pos = self.pos;
323334
let current_byte_offset = self.byte_offset(self.pos).to_usize();
324-
if current_byte_offset < self.filemap.src.len() {
335+
if current_byte_offset < self.source_text.len() {
325336
assert!(self.curr.is_some());
326337
let last_char = self.curr.unwrap();
327-
let next = self.filemap
328-
.src
329-
.char_range_at(current_byte_offset);
338+
let next = self.source_text.char_range_at(current_byte_offset);
330339
let byte_offset_diff = next.next - current_byte_offset;
331340
self.pos = self.pos + Pos::from_usize(byte_offset_diff);
332341
self.curr = Some(next.ch);
@@ -346,8 +355,8 @@ impl<'a> StringReader<'a> {
346355

347356
pub fn nextch(&self) -> Option<char> {
348357
let offset = self.byte_offset(self.pos).to_usize();
349-
if offset < self.filemap.src.len() {
350-
Some(self.filemap.src.char_at(offset))
358+
if offset < self.source_text.len() {
359+
Some(self.source_text.char_at(offset))
351360
} else {
352361
None
353362
}
@@ -359,7 +368,7 @@ impl<'a> StringReader<'a> {
359368

360369
pub fn nextnextch(&self) -> Option<char> {
361370
let offset = self.byte_offset(self.pos).to_usize();
362-
let s = &*self.filemap.src;
371+
let s = &self.source_text[..];
363372
if offset >= s.len() { return None }
364373
let str::CharRange { next, .. } = s.char_range_at(offset);
365374
if next < s.len() {

‎src/libsyntax/parse/mod.rs

Lines changed: 44 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,7 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) ->
751751
#[cfg(test)]
752752
mod test {
753753
use super::*;
754+
use std::rc::Rc;
754755
use serialize::json;
755756
use codemap::{Span, BytePos, Pos, Spanned, NO_EXPANSION};
756757
use owned_slice::OwnedSlice;
@@ -855,117 +856,50 @@ mod test {
855856
}
856857

857858
#[test]
858-
fn string_to_tts_1 () {
859+
fn string_to_tts_1() {
859860
let tts = string_to_tts("fn a (b : i32) { b; }".to_string());
860-
assert_eq!(json::encode(&tts).unwrap(),
861-
"[\
862-
{\
863-
\"variant\":\"TtToken\",\
864-
\"fields\":[\
865-
null,\
866-
{\
867-
\"variant\":\"Ident\",\
868-
\"fields\":[\
869-
\"fn\",\
870-
\"Plain\"\
871-
]\
872-
}\
873-
]\
874-
},\
875-
{\
876-
\"variant\":\"TtToken\",\
877-
\"fields\":[\
878-
null,\
879-
{\
880-
\"variant\":\"Ident\",\
881-
\"fields\":[\
882-
\"a\",\
883-
\"Plain\"\
884-
]\
885-
}\
886-
]\
887-
},\
888-
{\
889-
\"variant\":\"TtDelimited\",\
890-
\"fields\":[\
891-
null,\
892-
{\
893-
\"delim\":\"Paren\",\
894-
\"open_span\":null,\
895-
\"tts\":[\
896-
{\
897-
\"variant\":\"TtToken\",\
898-
\"fields\":[\
899-
null,\
900-
{\
901-
\"variant\":\"Ident\",\
902-
\"fields\":[\
903-
\"b\",\
904-
\"Plain\"\
905-
]\
906-
}\
907-
]\
908-
},\
909-
{\
910-
\"variant\":\"TtToken\",\
911-
\"fields\":[\
912-
null,\
913-
\"Colon\"\
914-
]\
915-
},\
916-
{\
917-
\"variant\":\"TtToken\",\
918-
\"fields\":[\
919-
null,\
920-
{\
921-
\"variant\":\"Ident\",\
922-
\"fields\":[\
923-
\"i32\",\
924-
\"Plain\"\
925-
]\
926-
}\
927-
]\
928-
}\
929-
],\
930-
\"close_span\":null\
931-
}\
932-
]\
933-
},\
934-
{\
935-
\"variant\":\"TtDelimited\",\
936-
\"fields\":[\
937-
null,\
938-
{\
939-
\"delim\":\"Brace\",\
940-
\"open_span\":null,\
941-
\"tts\":[\
942-
{\
943-
\"variant\":\"TtToken\",\
944-
\"fields\":[\
945-
null,\
946-
{\
947-
\"variant\":\"Ident\",\
948-
\"fields\":[\
949-
\"b\",\
950-
\"Plain\"\
951-
]\
952-
}\
953-
]\
954-
},\
955-
{\
956-
\"variant\":\"TtToken\",\
957-
\"fields\":[\
958-
null,\
959-
\"Semi\"\
960-
]\
961-
}\
962-
],\
963-
\"close_span\":null\
964-
}\
965-
]\
966-
}\
967-
]"
968-
);
861+
862+
let expected = vec![
863+
ast::TtToken(sp(0, 2),
864+
token::Ident(str_to_ident("fn"),
865+
token::IdentStyle::Plain)),
866+
ast::TtToken(sp(3, 4),
867+
token::Ident(str_to_ident("a"),
868+
token::IdentStyle::Plain)),
869+
ast::TtDelimited(
870+
sp(5, 14),
871+
Rc::new(ast::Delimited {
872+
delim: token::DelimToken::Paren,
873+
open_span: sp(5, 6),
874+
tts: vec![
875+
ast::TtToken(sp(6, 7),
876+
token::Ident(str_to_ident("b"),
877+
token::IdentStyle::Plain)),
878+
ast::TtToken(sp(8, 9),
879+
token::Colon),
880+
ast::TtToken(sp(10, 13),
881+
token::Ident(str_to_ident("i32"),
882+
token::IdentStyle::Plain)),
883+
],
884+
close_span: sp(13, 14),
885+
})),
886+
ast::TtDelimited(
887+
sp(15, 21),
888+
Rc::new(ast::Delimited {
889+
delim: token::DelimToken::Brace,
890+
open_span: sp(15, 16),
891+
tts: vec![
892+
ast::TtToken(sp(17, 18),
893+
token::Ident(str_to_ident("b"),
894+
token::IdentStyle::Plain)),
895+
ast::TtToken(sp(18, 19),
896+
token::Semi)
897+
],
898+
close_span: sp(20, 21),
899+
}))
900+
];
901+
902+
assert_eq!(tts, expected);
969903
}
970904

971905
#[test] fn ret_expr() {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_type = "rlib"]
12+
#![omit_gdb_pretty_printer_section]
13+
14+
// no-prefer-dynamic
15+
// compile-flags:-g
16+
17+
pub fn generic_function<T: Clone>(val: T) -> (T, T) {
18+
let result = (val.clone(), val.clone());
19+
let a_variable: u32 = 123456789;
20+
let another_variable: f64 = 123456789.5;
21+
zzz();
22+
result
23+
}
24+
25+
#[inline(never)]
26+
fn zzz() {()}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![omit_gdb_pretty_printer_section]
12+
13+
// ignore-android: FIXME(#10381)
14+
// min-lldb-version: 310
15+
16+
// aux-build:cross_crate_spans.rs
17+
extern crate cross_crate_spans;
18+
19+
// compile-flags:-g
20+
21+
22+
// === GDB TESTS ===================================================================================
23+
24+
// gdb-command:break cross_crate_spans.rs:21
25+
// gdb-command:run
26+
27+
// gdb-command:print result
28+
// gdb-check:$1 = {17, 17}
29+
// gdb-command:print a_variable
30+
// gdb-check:$2 = 123456789
31+
// gdb-command:print another_variable
32+
// gdb-check:$3 = 123456789.5
33+
// gdb-command:continue
34+
35+
// gdb-command:print result
36+
// gdb-check:$4 = {1212, 1212}
37+
// gdb-command:print a_variable
38+
// gdb-check:$5 = 123456789
39+
// gdb-command:print another_variable
40+
// gdb-check:$6 = 123456789.5
41+
// gdb-command:continue
42+
43+
44+
45+
// === LLDB TESTS ==================================================================================
46+
47+
// lldb-command:b cross_crate_spans.rs:21
48+
// lldb-command:run
49+
50+
// lldb-command:print result
51+
// lldb-check:[...]$0 = (17, 17)
52+
// lldb-command:print a_variable
53+
// lldb-check:[...]$1 = 123456789
54+
// lldb-command:print another_variable
55+
// lldb-check:[...]$2 = 123456789.5
56+
// lldb-command:continue
57+
58+
// lldb-command:print result
59+
// lldb-check:[...]$3 = (1212, 1212)
60+
// lldb-command:print a_variable
61+
// lldb-check:[...]$4 = 123456789
62+
// lldb-command:print another_variable
63+
// lldb-check:[...]$5 = 123456789.5
64+
// lldb-command:continue
65+
66+
67+
// This test makes sure that we can break in functions inlined from other crates.
68+
69+
fn main() {
70+
71+
let _ = cross_crate_spans::generic_function(17u32);
72+
let _ = cross_crate_spans::generic_function(1212i16);
73+
74+
}

0 commit comments

Comments
 (0)
Please sign in to comment.