1393 lines
35 KiB
Rust
1393 lines
35 KiB
Rust
use super::ast::*;
|
|
use std::borrow::Cow;
|
|
|
|
/// Text categories, based on the parsing.
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
|
pub enum SpanKind {
|
|
/// Parentheses e.g.
|
|
///
|
|
/// Stores the delimiter depth, for e.g. rainbow delimiters.
|
|
Delimiter(usize),
|
|
/// Separators like `=`, ':' and ','
|
|
Separator,
|
|
/// Numbers
|
|
Number,
|
|
/// Known literals, like `true`, `false`, `None`, `Ok`, `Err`
|
|
Literal,
|
|
/// Lifetimes (`'foo`)
|
|
Lifetime,
|
|
/// Strings
|
|
String,
|
|
/// Paths
|
|
Path,
|
|
/// Spaces (returns original number of spaces)
|
|
Space(usize),
|
|
|
|
/// Constructor: the prefix of a delimited block.
|
|
/// i.e. `Some` in `Some(3)`
|
|
Constructor,
|
|
|
|
/// String prefix, suffix, hashtags, etc.
|
|
/// Also number suffix
|
|
Surroundings,
|
|
|
|
/// Any other text (the default)
|
|
Text,
|
|
}
|
|
|
|
/// A `Span` is a piece of categorized text, based on the parsing done by
|
|
/// [`parse_input`](crate::parse_input).
|
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
pub struct Span<'a> {
|
|
/// The segment of text.
|
|
pub text: Cow<'a, str>,
|
|
/// Its category.
|
|
pub kind: SpanKind,
|
|
}
|
|
|
|
/// Configuration options for [`into_spans`]
|
|
#[derive(Default)]
|
|
pub struct Config {
|
|
/// Turn sequences of more than 1 space into exactly 1 space.
|
|
pub collapse_space: bool,
|
|
/// Pretty print: wrap at braces etc to the given width
|
|
pub pretty_print: Option<usize>,
|
|
}
|
|
|
|
pub trait IntoSpans<'a>: private::IntoSpansImpl<'a> {}
|
|
|
|
/// Turn an ast node into [`Span`]s.
|
|
pub fn into_spans<'a>(ast: impl IntoSpans<'a>, config: Config) -> Vec<Span<'a>> {
|
|
let mut cx = private::Context {
|
|
config,
|
|
res: Vec::new(),
|
|
depth: 0,
|
|
ignore_next_space: false,
|
|
};
|
|
if let Some(width) = cx.config.pretty_print {
|
|
let res = ast.into_pretty_spans(&mut cx);
|
|
let _ = res.render_vec(width, &mut cx.res);
|
|
} else {
|
|
ast.into_spans(&mut cx)
|
|
}
|
|
cx.res
|
|
}
|
|
|
|
mod private {
|
|
use logparse_pretty_print::{PrettyBuilder, PrettyTree, Text};
|
|
|
|
use super::*;
|
|
|
|
pub struct Context<'a> {
|
|
pub config: Config,
|
|
pub res: Vec<Span<'a>>,
|
|
pub depth: usize,
|
|
pub ignore_next_space: bool,
|
|
}
|
|
|
|
impl<'a> Context<'a> {
|
|
fn push(&mut self, text: impl Into<Cow<'a, str>>, kind: SpanKind) {
|
|
self.res.push(Span {
|
|
text: text.into(),
|
|
kind,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<'a> Text<'a> for Span<'a> {
|
|
fn from_static_str(s: &'static str) -> Self {
|
|
Span {
|
|
text: Cow::Borrowed(s),
|
|
kind: SpanKind::Text,
|
|
}
|
|
}
|
|
|
|
fn as_str(&self) -> Cow<'_, str> {
|
|
self.text.clone()
|
|
}
|
|
}
|
|
|
|
pub trait IntoSpansImpl<'a> {
|
|
fn into_spans(self, cx: &mut Context<'a>);
|
|
fn into_pretty_spans(self, cx: &mut Context<'a>) -> PrettyTree<'a, Span<'a>>;
|
|
}
|
|
|
|
impl<'a, T> IntoSpans<'a> for T where T: IntoSpansImpl<'a> {}
|
|
|
|
impl<'a> IntoSpansImpl<'a> for Separator {
|
|
fn into_spans(self, cx: &mut Context<'a>) {
|
|
match self {
|
|
Separator::Eq => cx.push("=", SpanKind::Separator),
|
|
Separator::Colon => cx.push(":", SpanKind::Separator),
|
|
Separator::DoubleColon => cx.push("::", SpanKind::Separator),
|
|
}
|
|
}
|
|
|
|
fn into_pretty_spans(self, _cx: &mut Context<'a>) -> PrettyTree<'a, Span<'a>> {
|
|
match self {
|
|
Separator::Eq => PrettyTree::text(Span {
|
|
text: Cow::Borrowed("="),
|
|
kind: SpanKind::Separator,
|
|
}),
|
|
Separator::Colon => PrettyTree::text(Span {
|
|
text: Cow::Borrowed(":"),
|
|
kind: SpanKind::Separator,
|
|
}),
|
|
Separator::DoubleColon => PrettyTree::text(Span {
|
|
text: Cow::Borrowed("::"),
|
|
kind: SpanKind::Separator,
|
|
}),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> IntoSpansImpl<'a> for QuoteType {
|
|
fn into_spans(self, cx: &mut Context<'a>) {
|
|
match self {
|
|
QuoteType::Single => cx.push("'", SpanKind::Surroundings),
|
|
QuoteType::Double => cx.push("\"", SpanKind::Surroundings),
|
|
QuoteType::Backtick => cx.push("`", SpanKind::Surroundings),
|
|
}
|
|
}
|
|
|
|
fn into_pretty_spans(self, _cx: &mut Context<'a>) -> PrettyTree<'a, Span<'a>> {
|
|
match self {
|
|
QuoteType::Single => PrettyTree::text(Span {
|
|
text: Cow::Borrowed("'"),
|
|
kind: SpanKind::Surroundings,
|
|
}),
|
|
QuoteType::Double => PrettyTree::text(Span {
|
|
text: Cow::Borrowed("\""),
|
|
kind: SpanKind::Surroundings,
|
|
}),
|
|
QuoteType::Backtick => PrettyTree::text(Span {
|
|
text: Cow::Borrowed("`"),
|
|
kind: SpanKind::Surroundings,
|
|
}),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> IntoSpansImpl<'a> for AnyString<'a> {
|
|
fn into_spans(self, cx: &mut Context<'a>) {
|
|
let Self {
|
|
prefix,
|
|
ty,
|
|
contents,
|
|
num_hashtags,
|
|
suffix,
|
|
} = self;
|
|
cx.push(prefix, SpanKind::Surroundings);
|
|
for _ in 0..num_hashtags {
|
|
cx.push("#", SpanKind::Surroundings)
|
|
}
|
|
|
|
ty.into_spans(cx);
|
|
cx.push(contents, SpanKind::String);
|
|
ty.into_spans(cx);
|
|
|
|
for _ in 0..num_hashtags {
|
|
cx.push("#", SpanKind::Surroundings)
|
|
}
|
|
cx.push(suffix, SpanKind::Surroundings);
|
|
}
|
|
|
|
fn into_pretty_spans(self, cx: &mut Context<'a>) -> PrettyTree<'a, Span<'a>> {
|
|
let Self {
|
|
prefix,
|
|
ty,
|
|
contents,
|
|
num_hashtags,
|
|
suffix,
|
|
} = self;
|
|
|
|
let hashtags = "#".repeat(num_hashtags);
|
|
|
|
PrettyTree::text(Span {
|
|
text: prefix,
|
|
kind: SpanKind::Surroundings,
|
|
})
|
|
.append(PrettyTree::text(Span {
|
|
text: Cow::Owned(hashtags.clone()),
|
|
kind: SpanKind::Surroundings,
|
|
}))
|
|
.group()
|
|
.append(ty.into_pretty_spans(cx))
|
|
.group()
|
|
.append(PrettyTree::text(Span {
|
|
text: contents,
|
|
kind: SpanKind::String,
|
|
}))
|
|
.group()
|
|
.append(ty.into_pretty_spans(cx))
|
|
.group()
|
|
.append(PrettyTree::text(Span {
|
|
text: suffix,
|
|
kind: SpanKind::Surroundings,
|
|
}))
|
|
.group()
|
|
}
|
|
}
|
|
|
|
impl<'a> IntoSpansImpl<'a> for Path<'a> {
|
|
fn into_spans(self, cx: &mut Context<'a>) {
|
|
cx.push(self.to_string(), SpanKind::Path)
|
|
}
|
|
|
|
fn into_pretty_spans(self, _cx: &mut Context<'a>) -> PrettyTree<'a, Span<'a>> {
|
|
PrettyTree::text(Span {
|
|
text: Cow::Owned(self.to_string()),
|
|
kind: SpanKind::Path,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<'a> IntoSpansImpl<'a> for Number<'a> {
|
|
fn into_spans(self, cx: &mut Context<'a>) {
|
|
cx.push(self.number, SpanKind::Number);
|
|
|
|
if let Some(suffix) = self.suffix_without_underscore {
|
|
cx.push("_", SpanKind::Surroundings);
|
|
cx.push(suffix, SpanKind::Surroundings);
|
|
}
|
|
}
|
|
|
|
fn into_pretty_spans(self, _cx: &mut Context<'a>) -> PrettyTree<'a, Span<'a>> {
|
|
let main = PrettyTree::text(Span {
|
|
text: self.number,
|
|
kind: SpanKind::Number,
|
|
});
|
|
|
|
let suffix = if let Some(suffix) = self.suffix_without_underscore {
|
|
PrettyTree::text(Span {
|
|
text: Cow::Borrowed("_"),
|
|
kind: SpanKind::Surroundings,
|
|
})
|
|
.append(PrettyTree::text(Span {
|
|
text: suffix,
|
|
kind: SpanKind::Surroundings,
|
|
}))
|
|
.group()
|
|
} else {
|
|
PrettyTree::Nil
|
|
};
|
|
|
|
main.append(suffix).group()
|
|
}
|
|
}
|
|
|
|
impl<'a> IntoSpansImpl<'a> for Atom<'a> {
|
|
fn into_spans(self, cx: &mut Context<'a>) {
|
|
match self {
|
|
Atom::Text(text) => cx.push(text, SpanKind::Text),
|
|
}
|
|
}
|
|
|
|
fn into_pretty_spans(self, _cx: &mut Context<'a>) -> PrettyTree<'a, Span<'a>> {
|
|
match self {
|
|
Atom::Text(text) => PrettyTree::text(Span {
|
|
text,
|
|
kind: SpanKind::Text,
|
|
}),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> IntoSpansImpl<'a> for Space<'a> {
|
|
fn into_spans(self, cx: &mut Context<'a>) {
|
|
match self.0.len() {
|
|
0 => {}
|
|
1 => cx.push(self.0, SpanKind::Space(1)),
|
|
n if cx.config.collapse_space => cx.push(" ", SpanKind::Space(n)),
|
|
n => cx.push(self.0, SpanKind::Space(n)),
|
|
}
|
|
}
|
|
|
|
fn into_pretty_spans(self, cx: &mut Context<'a>) -> PrettyTree<'a, Span<'a>> {
|
|
if cx.ignore_next_space {
|
|
cx.ignore_next_space = false;
|
|
return PrettyTree::Nil;
|
|
}
|
|
|
|
match self.0.len() {
|
|
0 => PrettyTree::Nil,
|
|
1 => PrettyTree::line_or_space(),
|
|
n if cx.config.collapse_space => PrettyTree::line_or_space(),
|
|
n => PrettyTree::text(Span {
|
|
text: self.0,
|
|
kind: SpanKind::Space(n),
|
|
}),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> IntoSpansImpl<'a> for Token<'a> {
|
|
fn into_spans(self, cx: &mut Context<'a>) {
|
|
match self {
|
|
Token::True => cx.push("true", SpanKind::Literal),
|
|
Token::False => cx.push("false", SpanKind::Literal),
|
|
Token::None => cx.push("None", SpanKind::Literal),
|
|
Token::Path(path) => path.into_spans(cx),
|
|
Token::String(string) => string.into_spans(cx),
|
|
Token::Number(number) => number.into_spans(cx),
|
|
Token::Separated {
|
|
before,
|
|
space_before,
|
|
separator,
|
|
after,
|
|
} => {
|
|
before.into_spans(cx);
|
|
space_before.into_spans(cx);
|
|
separator.into_spans(cx);
|
|
after.into_spans(cx);
|
|
}
|
|
Token::Delimited(delimited) => {
|
|
delimited.into_spans(cx);
|
|
}
|
|
Token::Atom(atom) => {
|
|
atom.into_spans(cx);
|
|
}
|
|
Token::Lifetime(lifetime) => {
|
|
cx.push("'", SpanKind::Surroundings);
|
|
cx.push(lifetime, SpanKind::Lifetime);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn into_pretty_spans(self, cx: &mut Context<'a>) -> PrettyTree<'a, Span<'a>> {
|
|
match self {
|
|
Token::True => PrettyTree::text(Span {
|
|
text: Cow::Borrowed("true"),
|
|
kind: SpanKind::Literal,
|
|
}),
|
|
Token::False => PrettyTree::text(Span {
|
|
text: Cow::Borrowed("true"),
|
|
kind: SpanKind::Literal,
|
|
}),
|
|
Token::None => PrettyTree::text(Span {
|
|
text: Cow::Borrowed("None"),
|
|
kind: SpanKind::Literal,
|
|
}),
|
|
Token::Lifetime(lifetime) => PrettyTree::Text(Span {
|
|
text: Cow::Borrowed("'"),
|
|
kind: SpanKind::Surroundings,
|
|
})
|
|
.append(PrettyTree::text(Span {
|
|
text: lifetime,
|
|
kind: SpanKind::Lifetime,
|
|
}))
|
|
.group(),
|
|
Token::Path(path) => path.into_pretty_spans(cx),
|
|
Token::String(string) => string.into_pretty_spans(cx),
|
|
Token::Number(number) => number.into_pretty_spans(cx),
|
|
Token::Separated {
|
|
before,
|
|
space_before,
|
|
separator,
|
|
after,
|
|
} => before
|
|
.into_pretty_spans(cx)
|
|
.append(space_before.into_pretty_spans(cx))
|
|
.group()
|
|
.append(separator.into_pretty_spans(cx))
|
|
.group()
|
|
.append(after.into_pretty_spans(cx))
|
|
.group(),
|
|
Token::Delimited(delimited) => delimited.into_pretty_spans(cx),
|
|
Token::Atom(atom) => atom.into_pretty_spans(cx),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> IntoSpansImpl<'a> for Segment<'a> {
|
|
fn into_spans(self, cx: &mut Context<'a>) {
|
|
let Self {
|
|
leading_space,
|
|
token,
|
|
} = self;
|
|
leading_space.into_spans(cx);
|
|
token.into_spans(cx);
|
|
}
|
|
|
|
fn into_pretty_spans(self, cx: &mut Context<'a>) -> PrettyTree<'a, Span<'a>> {
|
|
let Self {
|
|
leading_space,
|
|
token,
|
|
} = self;
|
|
|
|
leading_space
|
|
.into_pretty_spans(cx)
|
|
.append(token.into_pretty_spans(cx))
|
|
.group()
|
|
}
|
|
}
|
|
|
|
impl<'a> IntoSpansImpl<'a> for Segments<'a> {
|
|
fn into_spans(self, cx: &mut Context<'a>) {
|
|
let Self {
|
|
segments,
|
|
trailing_space,
|
|
} = self;
|
|
for segment in segments {
|
|
segment.into_spans(cx);
|
|
}
|
|
trailing_space.into_spans(cx);
|
|
}
|
|
|
|
fn into_pretty_spans(self, cx: &mut Context<'a>) -> PrettyTree<'a, Span<'a>> {
|
|
let ignore_start = cx.ignore_next_space;
|
|
|
|
let Self {
|
|
segments,
|
|
trailing_space,
|
|
} = self;
|
|
let mut res = PrettyTree::Nil;
|
|
for segment in segments {
|
|
res = res.append(segment.into_pretty_spans(cx)).group();
|
|
}
|
|
|
|
// if we ignore the first space, also ignore the last one.
|
|
if ignore_start {
|
|
cx.ignore_next_space = true;
|
|
}
|
|
res.append(trailing_space.into_pretty_spans(cx)).group()
|
|
}
|
|
}
|
|
|
|
fn prefix_kind(delimiter: Delimiter, space: &Space<'_>) -> SpanKind {
|
|
match delimiter {
|
|
Delimiter::Brace => SpanKind::Constructor,
|
|
Delimiter::Paren if space.0.is_empty() => SpanKind::Constructor,
|
|
Delimiter::Paren => SpanKind::Text,
|
|
Delimiter::Bracket => SpanKind::Text,
|
|
Delimiter::Angle if space.0.is_empty() => SpanKind::Constructor,
|
|
Delimiter::Angle => SpanKind::Text,
|
|
}
|
|
}
|
|
|
|
impl<'a> IntoSpansImpl<'a> for Delimited<'a> {
|
|
fn into_spans(self, cx: &mut Context<'a>) {
|
|
let Self {
|
|
prefix,
|
|
delimiter,
|
|
contents,
|
|
} = self;
|
|
|
|
match prefix {
|
|
Some((Atom::Text(text), space)) => {
|
|
cx.push(text, prefix_kind(delimiter, &space));
|
|
space.into_spans(cx);
|
|
}
|
|
None => {}
|
|
}
|
|
|
|
match delimiter {
|
|
Delimiter::Paren => cx.push("(", SpanKind::Delimiter(cx.depth)),
|
|
Delimiter::Bracket => cx.push("[", SpanKind::Delimiter(cx.depth)),
|
|
Delimiter::Brace => cx.push("{", SpanKind::Delimiter(cx.depth)),
|
|
Delimiter::Angle => cx.push("<", SpanKind::Delimiter(cx.depth)),
|
|
}
|
|
|
|
cx.depth += 1;
|
|
contents.into_spans(cx);
|
|
cx.depth -= 1;
|
|
|
|
match delimiter {
|
|
Delimiter::Paren => cx.push(")", SpanKind::Delimiter(cx.depth)),
|
|
Delimiter::Bracket => cx.push("]", SpanKind::Delimiter(cx.depth)),
|
|
Delimiter::Brace => cx.push("}", SpanKind::Delimiter(cx.depth)),
|
|
Delimiter::Angle => cx.push(">", SpanKind::Delimiter(cx.depth)),
|
|
}
|
|
}
|
|
|
|
fn into_pretty_spans(self, cx: &mut Context<'a>) -> PrettyTree<'a, Span<'a>> {
|
|
let Self {
|
|
prefix,
|
|
delimiter,
|
|
contents,
|
|
} = self;
|
|
|
|
let group = contents
|
|
.segments
|
|
.iter()
|
|
.filter(|i| !matches!(i.token, Token::Atom(..)))
|
|
.count()
|
|
<= 1;
|
|
|
|
let prefix = match prefix {
|
|
Some((Atom::Text(text), space)) => PrettyTree::text(Span {
|
|
text,
|
|
kind: prefix_kind(delimiter, &space),
|
|
})
|
|
.append(space.into_pretty_spans(cx))
|
|
.group(),
|
|
None => PrettyTree::Nil,
|
|
};
|
|
|
|
let open = match delimiter {
|
|
Delimiter::Paren => Span {
|
|
text: Cow::Borrowed("("),
|
|
kind: SpanKind::Delimiter(cx.depth),
|
|
},
|
|
Delimiter::Bracket => Span {
|
|
text: Cow::Borrowed("["),
|
|
kind: SpanKind::Delimiter(cx.depth),
|
|
},
|
|
Delimiter::Brace => Span {
|
|
text: Cow::Borrowed("{"),
|
|
kind: SpanKind::Delimiter(cx.depth),
|
|
},
|
|
Delimiter::Angle => Span {
|
|
text: Cow::Borrowed("<"),
|
|
kind: SpanKind::Delimiter(cx.depth),
|
|
},
|
|
};
|
|
|
|
let close = match delimiter {
|
|
Delimiter::Paren => Span {
|
|
text: Cow::Borrowed(")"),
|
|
kind: SpanKind::Delimiter(cx.depth),
|
|
},
|
|
Delimiter::Bracket => Span {
|
|
text: Cow::Borrowed("]"),
|
|
kind: SpanKind::Delimiter(cx.depth),
|
|
},
|
|
Delimiter::Brace => Span {
|
|
text: Cow::Borrowed("}"),
|
|
kind: SpanKind::Delimiter(cx.depth),
|
|
},
|
|
Delimiter::Angle => Span {
|
|
text: Cow::Borrowed(">"),
|
|
kind: SpanKind::Delimiter(cx.depth),
|
|
},
|
|
};
|
|
|
|
cx.depth += 1;
|
|
if !group {
|
|
cx.ignore_next_space = true;
|
|
}
|
|
let contents = contents.into_pretty_spans(cx);
|
|
cx.depth -= 1;
|
|
|
|
if group {
|
|
prefix
|
|
.append(PrettyTree::text(open))
|
|
.group()
|
|
.append(contents)
|
|
.group()
|
|
.append(PrettyTree::text(close))
|
|
} else {
|
|
prefix
|
|
.append(PrettyTree::text(open))
|
|
.group()
|
|
.append(PrettyTree::Hardline)
|
|
.group()
|
|
.append(contents)
|
|
.group()
|
|
.nest(4)
|
|
.group()
|
|
.append(PrettyTree::Hardline)
|
|
.group()
|
|
.append(PrettyTree::text(close))
|
|
.group()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use insta::{assert_debug_snapshot, assert_snapshot};
|
|
|
|
use super::SpanKind;
|
|
use crate::{Config, into_spans, parse_input};
|
|
|
|
fn spans(input: &str) -> Vec<(String, SpanKind)> {
|
|
let res = parse_input(input).unwrap();
|
|
into_spans(
|
|
res,
|
|
Config {
|
|
collapse_space: true,
|
|
..Default::default()
|
|
},
|
|
)
|
|
.into_iter()
|
|
.map(|i| (i.text.into_owned(), i.kind))
|
|
.collect()
|
|
}
|
|
|
|
fn pretty_print(input: &str, n: usize) -> String {
|
|
let res = parse_input(input).unwrap();
|
|
into_spans(
|
|
res,
|
|
Config {
|
|
pretty_print: Some(n),
|
|
..Default::default()
|
|
},
|
|
)
|
|
.into_iter()
|
|
.map(|i| i.text.into_owned())
|
|
.collect::<String>()
|
|
}
|
|
|
|
#[test]
|
|
fn pretty_print_ex1() {
|
|
assert_snapshot!(pretty_print(
|
|
r#"def_id=DefId(0:3 ~ unsized_coercion[10fa]::Trait)"#, 60
|
|
), @"
|
|
def_id=DefId(
|
|
0:3 ~ unsized_coercion[10fa]::Trait
|
|
)
|
|
");
|
|
assert_snapshot!(pretty_print(
|
|
r#"def_id=DefId(0:3 ~ unsized_coercion[10fa]::Trait)"#, 30
|
|
), @"
|
|
def_id=DefId(
|
|
0:3 ~
|
|
unsized_coercion[10fa]::Trait
|
|
)
|
|
");
|
|
assert_snapshot!(pretty_print(
|
|
r#"def_id=DefId(0:3 ~ unsized_coercion[10fa]::Trait)"#, 10
|
|
), @"
|
|
def_id=DefId(
|
|
0:3 ~
|
|
unsized_coercion[10fa]::Trait
|
|
)
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn pretty_print_ex2() {
|
|
assert_snapshot!(pretty_print(
|
|
r#"stability: inspecting def_id=DefId(3:662 ~ alloc[ef11]::boxed::Box) span=tests/ui/impl-trait/unsized_coercion.rs:16:16: 16:30 (#0) of stability=Some(Stability { level: Stable { since: Version(RustcVersion { major: 1, minor: 0, patch: 0 }), allowed_through_unstable_modules: None }, feature: "rust1" })"#, 60
|
|
), @r#"
|
|
stability: inspecting
|
|
def_id=DefId(
|
|
3:662 ~ alloc[ef11]::boxed::Box
|
|
) span=tests/ui/impl-trait/unsized_coercion.rs:16:16: 16:30
|
|
(#0) of
|
|
stability=Some(Stability {
|
|
|
|
level:
|
|
Stable {
|
|
|
|
since:
|
|
Version(RustcVersion {
|
|
major: 1, minor: 0, patch: 0
|
|
}), allowed_through_unstable_modules: None
|
|
|
|
}, feature: "rust1"
|
|
|
|
})
|
|
"#);
|
|
}
|
|
|
|
#[test]
|
|
fn spans_ex1() {
|
|
assert_debug_snapshot!(spans(
|
|
r#"def_id=DefId(0:3 ~ unsized_coercion[10fa]::Trait)"#
|
|
), @r#"
|
|
[
|
|
(
|
|
"def_id",
|
|
Text,
|
|
),
|
|
(
|
|
"=",
|
|
Separator,
|
|
),
|
|
(
|
|
"DefId",
|
|
Constructor,
|
|
),
|
|
(
|
|
"(",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
(
|
|
"0",
|
|
Number,
|
|
),
|
|
(
|
|
":",
|
|
Separator,
|
|
),
|
|
(
|
|
"3",
|
|
Number,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"~",
|
|
Text,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"unsized_coercion",
|
|
Text,
|
|
),
|
|
(
|
|
"[",
|
|
Delimiter(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"10fa",
|
|
Text,
|
|
),
|
|
(
|
|
"]",
|
|
Delimiter(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"::",
|
|
Separator,
|
|
),
|
|
(
|
|
"Trait",
|
|
Text,
|
|
),
|
|
(
|
|
")",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
]
|
|
"#)
|
|
}
|
|
|
|
#[test]
|
|
fn spans_ex2() {
|
|
assert_debug_snapshot!(spans(
|
|
r#"data=TypeNs("MetaSized") visible_parent=DefId(2:3984 ~ core[bcc4]::marker) actual_parent=Some(DefId(2:3984 ~ core[bcc4]::marker))"#
|
|
), @r#"
|
|
[
|
|
(
|
|
"data",
|
|
Text,
|
|
),
|
|
(
|
|
"=",
|
|
Separator,
|
|
),
|
|
(
|
|
"TypeNs",
|
|
Constructor,
|
|
),
|
|
(
|
|
"(",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
(
|
|
"",
|
|
Surroundings,
|
|
),
|
|
(
|
|
"\"",
|
|
Surroundings,
|
|
),
|
|
(
|
|
"MetaSized",
|
|
String,
|
|
),
|
|
(
|
|
"\"",
|
|
Surroundings,
|
|
),
|
|
(
|
|
"",
|
|
Surroundings,
|
|
),
|
|
(
|
|
")",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"visible_parent",
|
|
Text,
|
|
),
|
|
(
|
|
"=",
|
|
Separator,
|
|
),
|
|
(
|
|
"DefId",
|
|
Constructor,
|
|
),
|
|
(
|
|
"(",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
(
|
|
"2",
|
|
Number,
|
|
),
|
|
(
|
|
":",
|
|
Separator,
|
|
),
|
|
(
|
|
"3984",
|
|
Number,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"~",
|
|
Text,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"core",
|
|
Text,
|
|
),
|
|
(
|
|
"[",
|
|
Delimiter(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"bcc4",
|
|
Text,
|
|
),
|
|
(
|
|
"]",
|
|
Delimiter(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"::",
|
|
Separator,
|
|
),
|
|
(
|
|
"marker",
|
|
Text,
|
|
),
|
|
(
|
|
")",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"actual_parent",
|
|
Text,
|
|
),
|
|
(
|
|
"=",
|
|
Separator,
|
|
),
|
|
(
|
|
"Some",
|
|
Constructor,
|
|
),
|
|
(
|
|
"(",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
(
|
|
"DefId",
|
|
Constructor,
|
|
),
|
|
(
|
|
"(",
|
|
Delimiter(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"2",
|
|
Number,
|
|
),
|
|
(
|
|
":",
|
|
Separator,
|
|
),
|
|
(
|
|
"3984",
|
|
Number,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"~",
|
|
Text,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"core",
|
|
Text,
|
|
),
|
|
(
|
|
"[",
|
|
Delimiter(
|
|
2,
|
|
),
|
|
),
|
|
(
|
|
"bcc4",
|
|
Text,
|
|
),
|
|
(
|
|
"]",
|
|
Delimiter(
|
|
2,
|
|
),
|
|
),
|
|
(
|
|
"::",
|
|
Separator,
|
|
),
|
|
(
|
|
"marker",
|
|
Text,
|
|
),
|
|
(
|
|
")",
|
|
Delimiter(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
")",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
]
|
|
"#)
|
|
}
|
|
|
|
#[test]
|
|
fn spans_ex3() {
|
|
assert_debug_snapshot!(spans(
|
|
r#"insert(DefId(0:4 ~ unsized_coercion[10fa]::{impl#0})): inserting TraitRef <u32 as Trait> into specialization graph"#
|
|
), @r#"
|
|
[
|
|
(
|
|
"insert",
|
|
Constructor,
|
|
),
|
|
(
|
|
"(",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
(
|
|
"DefId",
|
|
Constructor,
|
|
),
|
|
(
|
|
"(",
|
|
Delimiter(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"0",
|
|
Number,
|
|
),
|
|
(
|
|
":",
|
|
Separator,
|
|
),
|
|
(
|
|
"4",
|
|
Number,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"~",
|
|
Text,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"unsized_coercion",
|
|
Text,
|
|
),
|
|
(
|
|
"[",
|
|
Delimiter(
|
|
2,
|
|
),
|
|
),
|
|
(
|
|
"10fa",
|
|
Text,
|
|
),
|
|
(
|
|
"]",
|
|
Delimiter(
|
|
2,
|
|
),
|
|
),
|
|
(
|
|
"::",
|
|
Separator,
|
|
),
|
|
(
|
|
"{",
|
|
Delimiter(
|
|
2,
|
|
),
|
|
),
|
|
(
|
|
"impl#0",
|
|
Text,
|
|
),
|
|
(
|
|
"}",
|
|
Delimiter(
|
|
2,
|
|
),
|
|
),
|
|
(
|
|
")",
|
|
Delimiter(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
")",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
(
|
|
":",
|
|
Separator,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"inserting",
|
|
Text,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"TraitRef",
|
|
Text,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"<",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
(
|
|
"u32",
|
|
Text,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"as",
|
|
Text,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"Trait",
|
|
Text,
|
|
),
|
|
(
|
|
">",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"into",
|
|
Text,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"specialization",
|
|
Text,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"graph",
|
|
Text,
|
|
),
|
|
]
|
|
"#)
|
|
}
|
|
|
|
#[test]
|
|
fn spans_ex4() {
|
|
assert_debug_snapshot!(spans(
|
|
r#"inspecting def_id=DefId(3:662 ~ alloc[ef11]::boxed::Box) span=tests/ui/impl-trait/unsized_coercion.rs:12:15: 12:30 (#0)"#
|
|
), @r##"
|
|
[
|
|
(
|
|
"inspecting",
|
|
Text,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"def_id",
|
|
Text,
|
|
),
|
|
(
|
|
"=",
|
|
Separator,
|
|
),
|
|
(
|
|
"DefId",
|
|
Constructor,
|
|
),
|
|
(
|
|
"(",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
(
|
|
"3",
|
|
Number,
|
|
),
|
|
(
|
|
":",
|
|
Separator,
|
|
),
|
|
(
|
|
"662",
|
|
Number,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"~",
|
|
Text,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"alloc",
|
|
Text,
|
|
),
|
|
(
|
|
"[",
|
|
Delimiter(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"ef11",
|
|
Text,
|
|
),
|
|
(
|
|
"]",
|
|
Delimiter(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"::",
|
|
Separator,
|
|
),
|
|
(
|
|
"boxed",
|
|
Text,
|
|
),
|
|
(
|
|
"::",
|
|
Separator,
|
|
),
|
|
(
|
|
"Box",
|
|
Text,
|
|
),
|
|
(
|
|
")",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"span",
|
|
Text,
|
|
),
|
|
(
|
|
"=",
|
|
Separator,
|
|
),
|
|
(
|
|
"tests/ui/impl-trait/unsized_coercion.rs:12:15",
|
|
Path,
|
|
),
|
|
(
|
|
":",
|
|
Separator,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"12",
|
|
Number,
|
|
),
|
|
(
|
|
":",
|
|
Separator,
|
|
),
|
|
(
|
|
"30",
|
|
Number,
|
|
),
|
|
(
|
|
" ",
|
|
Space(
|
|
1,
|
|
),
|
|
),
|
|
(
|
|
"(",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
(
|
|
"#0",
|
|
Text,
|
|
),
|
|
(
|
|
")",
|
|
Delimiter(
|
|
0,
|
|
),
|
|
),
|
|
]
|
|
"##)
|
|
}
|
|
}
|