Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 65 additions & 76 deletions compiler/rustc_ast/src/tokenstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,6 @@
//! `TokenStream`s represent syntactic objects before they are converted into ASTs.
//! A `TokenStream` is, roughly speaking, a sequence of [`TokenTree`]s,
//! which are themselves a single [`Token`] or a `Delimited` subsequence of tokens.
//!
//! ## Ownership
//!
//! `TokenStream`s are persistent data structures constructed as ropes with reference
//! counted-children. In general, this means that calling an operation on a `TokenStream`
//! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to
//! the original. This essentially coerces `TokenStream`s into "views" of their subparts,
//! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking
//! ownership of the original.

use std::borrow::Cow;
use std::ops::Range;
Expand Down Expand Up @@ -99,17 +90,6 @@ impl TokenTree {
}
}

impl<CTX> HashStable<CTX> for TokenStream
where
CTX: crate::HashStableContext,
{
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
for sub_tt in self.iter() {
sub_tt.hash_stable(hcx, hasher);
}
}
}

/// A lazy version of [`AttrTokenStream`], which defers creation of an actual
/// `AttrTokenStream` until it is needed.
#[derive(Clone)]
Expand Down Expand Up @@ -556,10 +536,6 @@ pub struct AttrsTarget {
pub tokens: LazyAttrTokenStream,
}

/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
#[derive(Clone, Debug, Default, Encodable, Decodable)]
pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>);

/// Indicates whether a token can join with the following token to form a
/// compound token. Used for conversions to `proc_macro::Spacing`. Also used to
/// guide pretty-printing, which is where the `JointHidden` value (which isn't
Expand Down Expand Up @@ -620,58 +596,9 @@ pub enum Spacing {
JointHidden,
}

impl TokenStream {
/// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
/// separating the two arguments with a comma for diagnostic suggestions.
pub fn add_comma(&self) -> Option<(TokenStream, Span)> {
// Used to suggest if a user writes `foo!(a b);`
let mut suggestion = None;
let mut iter = self.0.iter().enumerate().peekable();
while let Some((pos, ts)) = iter.next() {
if let Some((_, next)) = iter.peek() {
let sp = match (&ts, &next) {
(_, TokenTree::Token(Token { kind: token::Comma, .. }, _)) => continue,
(
TokenTree::Token(token_left, Spacing::Alone),
TokenTree::Token(token_right, _),
) if (token_left.is_non_reserved_ident() || token_left.is_lit())
&& (token_right.is_non_reserved_ident() || token_right.is_lit()) =>
{
token_left.span
}
(TokenTree::Delimited(sp, ..), _) => sp.entire(),
_ => continue,
};
let sp = sp.shrink_to_hi();
let comma = TokenTree::token_alone(token::Comma, sp);
suggestion = Some((pos, comma, sp));
}
}
if let Some((pos, comma, sp)) = suggestion {
let mut new_stream = Vec::with_capacity(self.0.len() + 1);
let parts = self.0.split_at(pos + 1);
new_stream.extend_from_slice(parts.0);
new_stream.push(comma);
new_stream.extend_from_slice(parts.1);
return Some((TokenStream::new(new_stream), sp));
}
None
}
}

impl FromIterator<TokenTree> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>())
}
}

impl Eq for TokenStream {}

impl PartialEq<TokenStream> for TokenStream {
fn eq(&self, other: &TokenStream) -> bool {
self.iter().eq(other.iter())
}
}
/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
#[derive(Clone, Debug, Default, Encodable, Decodable)]
pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>);

impl TokenStream {
pub fn new(tts: Vec<TokenTree>) -> TokenStream {
Expand Down Expand Up @@ -847,6 +774,68 @@ impl TokenStream {
}
}
}

/// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
/// separating the two arguments with a comma for diagnostic suggestions.
pub fn add_comma(&self) -> Option<(TokenStream, Span)> {
// Used to suggest if a user writes `foo!(a b);`
let mut suggestion = None;
let mut iter = self.0.iter().enumerate().peekable();
while let Some((pos, ts)) = iter.next() {
if let Some((_, next)) = iter.peek() {
let sp = match (&ts, &next) {
(_, TokenTree::Token(Token { kind: token::Comma, .. }, _)) => continue,
(
TokenTree::Token(token_left, Spacing::Alone),
TokenTree::Token(token_right, _),
) if (token_left.is_non_reserved_ident() || token_left.is_lit())
&& (token_right.is_non_reserved_ident() || token_right.is_lit()) =>
{
token_left.span
}
(TokenTree::Delimited(sp, ..), _) => sp.entire(),
_ => continue,
};
let sp = sp.shrink_to_hi();
let comma = TokenTree::token_alone(token::Comma, sp);
suggestion = Some((pos, comma, sp));
}
}
if let Some((pos, comma, sp)) = suggestion {
let mut new_stream = Vec::with_capacity(self.0.len() + 1);
let parts = self.0.split_at(pos + 1);
new_stream.extend_from_slice(parts.0);
new_stream.push(comma);
new_stream.extend_from_slice(parts.1);
return Some((TokenStream::new(new_stream), sp));
}
None
}
}

impl PartialEq<TokenStream> for TokenStream {
fn eq(&self, other: &TokenStream) -> bool {
self.iter().eq(other.iter())
}
}

impl Eq for TokenStream {}

impl FromIterator<TokenTree> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>())
}
}

impl<CTX> HashStable<CTX> for TokenStream
where
CTX: crate::HashStableContext,
{
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
for sub_tt in self.iter() {
sub_tt.hash_stable(hcx, hasher);
}
}
}

#[derive(Clone)]
Expand Down
3 changes: 1 addition & 2 deletions src/tools/compiletest/src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::env;
use std::io::IsTerminal;
use std::sync::Arc;

use compiletest::{early_config_check, log_config, parse_config, run_tests};
use compiletest::{early_config_check, parse_config, run_tests};

fn main() {
tracing_subscriber::fmt::init();
Expand All @@ -19,6 +19,5 @@ fn main() {

early_config_check(&config);

log_config(&config);
run_tests(config);
}
49 changes: 2 additions & 47 deletions src/tools/compiletest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
mod tests;

pub mod common;
pub mod compute_diff;
mod debuggers;
pub mod diagnostics;
pub mod directives;
Expand Down Expand Up @@ -44,7 +43,6 @@ use crate::common::{
};
use crate::directives::DirectivesCache;
use crate::executor::{CollectedTest, ColorConfig};
use crate::util::logv;

/// Creates the `Config` instance for this invocation of compiletest.
///
Expand Down Expand Up @@ -477,51 +475,6 @@ pub fn parse_config(args: Vec<String>) -> Config {
}
}

pub fn log_config(config: &Config) {
let c = config;
logv(c, "configuration:".to_string());
logv(c, format!("compile_lib_path: {}", config.compile_lib_path));
logv(c, format!("run_lib_path: {}", config.run_lib_path));
logv(c, format!("rustc_path: {}", config.rustc_path));
logv(c, format!("cargo_path: {:?}", config.cargo_path));
logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path));

logv(c, format!("src_root: {}", config.src_root));
logv(c, format!("src_test_suite_root: {}", config.src_test_suite_root));

logv(c, format!("build_root: {}", config.build_root));
logv(c, format!("build_test_suite_root: {}", config.build_test_suite_root));

logv(c, format!("sysroot_base: {}", config.sysroot_base));

logv(c, format!("stage: {}", config.stage));
logv(c, format!("stage_id: {}", config.stage_id));
logv(c, format!("mode: {}", config.mode));
logv(c, format!("run_ignored: {}", config.run_ignored));
logv(c, format!("filters: {:?}", config.filters));
logv(c, format!("skip: {:?}", config.skip));
logv(c, format!("filter_exact: {}", config.filter_exact));
logv(
c,
format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),),
);
logv(c, format!("runner: {}", opt_str(&config.runner)));
logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags));
logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags));
logv(c, format!("target: {}", config.target));
logv(c, format!("host: {}", config.host));
logv(c, format!("android-cross-path: {}", config.android_cross_path));
logv(c, format!("adb_path: {}", config.adb_path));
logv(c, format!("adb_test_dir: {}", config.adb_test_dir));
logv(c, format!("adb_device_status: {}", config.adb_device_status));
logv(c, format!("ar: {}", config.ar));
logv(c, format!("target-linker: {:?}", config.target_linker));
logv(c, format!("host-linker: {:?}", config.host_linker));
logv(c, format!("verbose: {}", config.verbose));
logv(c, format!("minicore_path: {}", config.minicore_path));
logv(c, "\n".to_string());
}

pub fn opt_str(maybestr: &Option<String>) -> &str {
match *maybestr {
None => "(none)",
Expand All @@ -538,6 +491,8 @@ pub fn opt_str2(maybestr: Option<String>) -> String {

/// Called by `main` after the config has been parsed.
pub fn run_tests(config: Arc<Config>) {
debug!(?config, "run_tests");

// If we want to collect rustfix coverage information,
// we first make sure that the coverage file does not exist.
// It will be created later on.
Expand Down
35 changes: 22 additions & 13 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::io::prelude::*;
use std::io::{self, BufReader};
use std::process::{Child, Command, ExitStatus, Output, Stdio};
use std::sync::Arc;
use std::{env, iter, str};
use std::{env, fmt, iter, str};

use build_helper::fs::remove_and_create_dir_all;
use camino::{Utf8Path, Utf8PathBuf};
Expand All @@ -21,15 +21,13 @@ use crate::common::{
UI_WINDOWS_SVG, expected_output_path, incremental_dir, output_base_dir, output_base_name,
output_testname_unique,
};
use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff};
use crate::directives::TestProps;
use crate::errors::{Error, ErrorKind, load_errors};
use crate::read2::{Truncated, read2_abbreviated};
use crate::util::{Utf8PathBufExt, add_dylib_path, logv, static_regex};
use crate::runtest::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff};
use crate::util::{Utf8PathBufExt, add_dylib_path, static_regex};
use crate::{ColorConfig, help, json, stamp_file_path, warning};

mod debugger;

// Helper modules that implement test running logic for each test suite.
// tidy-alphabetical-start
mod assembly;
Expand All @@ -48,6 +46,8 @@ mod rustdoc_json;
mod ui;
// tidy-alphabetical-end

mod compute_diff;
mod debugger;
#[cfg(test)]
mod tests;

Expand Down Expand Up @@ -1459,7 +1459,7 @@ impl<'test> TestCx<'test> {
) -> ProcRes {
let cmdline = {
let cmdline = self.make_cmdline(&command, lib_path);
logv(self.config, format!("executing {}", cmdline));
self.logv(format_args!("executing {cmdline}"));
cmdline
};

Expand Down Expand Up @@ -2006,6 +2006,18 @@ impl<'test> TestCx<'test> {
output_base_name(self.config, self.testpaths, self.safe_revision())
}

/// Prints a message to (captured) stdout if `config.verbose` is true.
/// The message is also logged to `tracing::debug!` regardles of verbosity.
///
/// Use `format_args!` as the argument to perform formatting if required.
fn logv(&self, message: impl fmt::Display) {
debug!("{message}");
if self.config.verbose {
// Note: `./x test ... --verbose --no-capture` is needed to see this print.
println!("{message}");
}
}

/// Prefix to print before error messages. Normally just `error`, but also
/// includes the revision name for tests that use revisions.
#[must_use]
Expand Down Expand Up @@ -2666,20 +2678,17 @@ impl<'test> TestCx<'test> {
//
// It's not possible to detect paths in the error messages generally, but this is a
// decent enough heuristic.
static_regex!(
r#"(?x)
let re = static_regex!(
r#"(?x)
(?:
# Match paths that don't include spaces.
(?:\\[\pL\pN\.\-_']+)+\.\pL+
|
# If the path starts with a well-known root, then allow spaces and no file extension.
\$(?:DIR|SRC_DIR|TEST_BUILD_DIR|BUILD_DIR|LIB_DIR)(?:\\[\pL\pN\.\-_'\ ]+)+
)"#
)
.replace_all(&output, |caps: &Captures<'_>| {
println!("{}", &caps[0]);
caps[0].replace(r"\", "/")
})
);
re.replace_all(&output, |caps: &Captures<'_>| caps[0].replace(r"\", "/"))
.replace("\r\n", "\n")
}

Expand Down
3 changes: 1 addition & 2 deletions src/tools/compiletest/src/runtest/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use super::debugger::DebuggerCommands;
use super::{Debugger, Emit, ProcRes, TestCx, Truncated, WillExecute};
use crate::common::Config;
use crate::debuggers::{extract_gdb_version, is_android_gdb_target};
use crate::util::logv;

impl TestCx<'_> {
pub(super) fn run_debuginfo_test(&self) {
Expand Down Expand Up @@ -234,7 +233,7 @@ impl TestCx<'_> {
gdb.args(debugger_opts);
// FIXME(jieyouxu): don't pass an empty Path
let cmdline = self.make_cmdline(&gdb, Utf8Path::new(""));
logv(self.config, format!("executing {}", cmdline));
self.logv(format_args!("executing {cmdline}"));
cmdline
};

Expand Down
2 changes: 1 addition & 1 deletion src/tools/compiletest/src/runtest/mir_opt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use miropt_test_tools::{MiroptTest, MiroptTestFile, files_for_miropt_test};
use tracing::debug;

use super::{Emit, TestCx, WillExecute};
use crate::compute_diff::write_diff;
use crate::runtest::compute_diff::write_diff;

impl TestCx<'_> {
pub(super) fn run_mir_opt_test(&self) {
Expand Down
Loading
Loading