Skip to content

Commit

Permalink
Merge pull request #1003 from rust-lang/macro-expansion
Browse files Browse the repository at this point in the history
Migrate macro expansion to the orchestrator
  • Loading branch information
shepmaster authored Nov 29, 2023
2 parents dde4408 + ed60203 commit 047e5b7
Show file tree
Hide file tree
Showing 5 changed files with 324 additions and 305 deletions.
226 changes: 226 additions & 0 deletions compiler/base/orchestrator/src/coordinator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,56 @@ pub struct MiriResponse {
pub exit_detail: String,
}

#[derive(Debug, Clone)]
pub struct MacroExpansionRequest {
pub channel: Channel,
pub crate_type: CrateType,
pub edition: Edition,
pub code: String,
}

impl MacroExpansionRequest {
pub(crate) fn delete_previous_main_request(&self) -> DeleteFileRequest {
delete_previous_primary_file_request(self.crate_type)
}

pub(crate) fn write_main_request(&self) -> WriteFileRequest {
write_primary_file_request(self.crate_type, &self.code)
}

pub(crate) fn execute_cargo_request(&self) -> ExecuteCommandRequest {
ExecuteCommandRequest {
cmd: "cargo".to_owned(),
args: ["rustc", "--", "-Zunpretty=expanded"]
.map(str::to_owned)
.to_vec(),
envs: Default::default(),
cwd: None,
}
}
}

impl CargoTomlModifier for MacroExpansionRequest {
fn modify_cargo_toml(&self, mut cargo_toml: toml::Value) -> toml::Value {
if self.edition == Edition::Rust2024 {
cargo_toml = modify_cargo_toml::set_feature_edition2024(cargo_toml);
}

cargo_toml = modify_cargo_toml::set_edition(cargo_toml, self.edition.to_cargo_toml_key());

if let Some(crate_type) = self.crate_type.to_library_cargo_toml_key() {
cargo_toml = modify_cargo_toml::set_crate_type(cargo_toml, crate_type);
}
cargo_toml
}
}

#[derive(Debug, Clone)]
pub struct MacroExpansionResponse {
pub success: bool,
pub exit_detail: String,
}

#[derive(Debug, Clone)]
pub struct WithOutput<T> {
pub response: T,
Expand Down Expand Up @@ -721,6 +771,33 @@ where
.await
}

pub async fn macro_expansion(
&self,
request: MacroExpansionRequest,
) -> Result<WithOutput<MacroExpansionResponse>, MacroExpansionError> {
use macro_expansion_error::*;

self.select_channel(request.channel)
.await
.context(CouldNotStartContainerSnafu)?
.macro_expansion(request)
.await
}

pub async fn begin_macro_expansion(
&self,
token: CancellationToken,
request: MacroExpansionRequest,
) -> Result<ActiveMacroExpansion, MacroExpansionError> {
use macro_expansion_error::*;

self.select_channel(request.channel)
.await
.context(CouldNotStartContainerSnafu)?
.begin_macro_expansion(token, request)
.await
}

pub async fn idle(&mut self) -> Result<()> {
let Self {
stable,
Expand Down Expand Up @@ -1217,6 +1294,78 @@ impl Container {
})
}

async fn macro_expansion(
&self,
request: MacroExpansionRequest,
) -> Result<WithOutput<MacroExpansionResponse>, MacroExpansionError> {
let token = Default::default();

let ActiveMacroExpansion {
task,
stdout_rx,
stderr_rx,
} = self.begin_macro_expansion(token, request).await?;

WithOutput::try_absorb(task, stdout_rx, stderr_rx).await
}

async fn begin_macro_expansion(
&self,
token: CancellationToken,
request: MacroExpansionRequest,
) -> Result<ActiveMacroExpansion, MacroExpansionError> {
use macro_expansion_error::*;

let delete_previous_main = request.delete_previous_main_request();
let write_main = request.write_main_request();
let execute_cargo = request.execute_cargo_request();

let delete_previous_main = self.commander.one(delete_previous_main);
let write_main = self.commander.one(write_main);
let modify_cargo_toml = self.modify_cargo_toml.modify_for(&request);

let (delete_previous_main, write_main, modify_cargo_toml) =
join!(delete_previous_main, write_main, modify_cargo_toml);

delete_previous_main.context(CouldNotDeletePreviousCodeSnafu)?;
write_main.context(CouldNotWriteCodeSnafu)?;
modify_cargo_toml.context(CouldNotModifyCargoTomlSnafu)?;

let SpawnCargo {
task,
stdin_tx,
stdout_rx,
stderr_rx,
} = self
.spawn_cargo_task(token, execute_cargo)
.await
.context(CouldNotStartCargoSnafu)?;

drop(stdin_tx);

let task = async move {
let ExecuteCommandResponse {
success,
exit_detail,
} = task
.await
.context(CargoTaskPanickedSnafu)?
.context(CargoFailedSnafu)?;

Ok(MacroExpansionResponse {
success,
exit_detail,
})
}
.boxed();

Ok(ActiveMacroExpansion {
task,
stdout_rx,
stderr_rx,
})
}

async fn spawn_cargo_task(
&self,
token: CancellationToken,
Expand Down Expand Up @@ -1528,6 +1677,47 @@ pub enum MiriError {
CargoFailed { source: SpawnCargoError },
}

pub struct ActiveMacroExpansion {
pub task: BoxFuture<'static, Result<MacroExpansionResponse, MacroExpansionError>>,
pub stdout_rx: mpsc::Receiver<String>,
pub stderr_rx: mpsc::Receiver<String>,
}

impl fmt::Debug for ActiveMacroExpansion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ActiveMacroExpansion")
.field("task", &"<future>")
.field("stdout_rx", &self.stdout_rx)
.field("stderr_rx", &self.stderr_rx)
.finish()
}
}

#[derive(Debug, Snafu)]
#[snafu(module)]
pub enum MacroExpansionError {
#[snafu(display("Could not start the container"))]
CouldNotStartContainer { source: Error },

#[snafu(display("Could not modify Cargo.toml"))]
CouldNotModifyCargoToml { source: ModifyCargoTomlError },

#[snafu(display("Could not delete previous source code"))]
CouldNotDeletePreviousCode { source: CommanderError },

#[snafu(display("Could not write source code"))]
CouldNotWriteCode { source: CommanderError },

#[snafu(display("Could not start Cargo task"))]
CouldNotStartCargo { source: SpawnCargoError },

#[snafu(display("The Cargo task panicked"))]
CargoTaskPanicked { source: tokio::task::JoinError },

#[snafu(display("Cargo task failed"))]
CargoFailed { source: SpawnCargoError },
}

struct SpawnCargo {
task: JoinHandle<Result<ExecuteCommandResponse, SpawnCargoError>>,
stdin_tx: mpsc::Sender<String>,
Expand Down Expand Up @@ -3129,6 +3319,42 @@ mod tests {
Ok(())
}

const ARBITRARY_MACRO_EXPANSION_REQUEST: MacroExpansionRequest = MacroExpansionRequest {
channel: Channel::Nightly,
crate_type: CrateType::Library(LibraryType::Cdylib),
edition: Edition::Rust2018,
code: String::new(),
};

#[tokio::test]
#[snafu::report]
async fn macro_expansion() -> Result<()> {
let coordinator = new_coordinator().await;

let req = MacroExpansionRequest {
code: r#"
#[derive(Debug)]
struct Dummy;
fn main() { println!("Hello!"); }
"#
.into(),
..ARBITRARY_MACRO_EXPANSION_REQUEST
};

let response = coordinator
.macro_expansion(req)
.with_timeout()
.await
.unwrap();

assert!(response.success, "stderr: {}", response.stderr);
assert_contains!(response.stdout, "impl ::core::fmt::Debug for Dummy");
assert_contains!(response.stdout, "Formatter::write_str");

Ok(())
}

// The next set of tests are broader than the functionality of a
// single operation.

Expand Down
50 changes: 11 additions & 39 deletions ui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::env::{PLAYGROUND_GITHUB_TOKEN, PLAYGROUND_UI_ROOT};
use serde::{Deserialize, Serialize};
use snafu::prelude::*;
use std::{
convert::TryFrom,
net::SocketAddr,
path::{Path, PathBuf},
sync::Arc,
Expand Down Expand Up @@ -165,8 +164,6 @@ impl MetricsToken {
enum Error {
#[snafu(display("Sandbox creation failed: {}", source))]
SandboxCreation { source: sandbox::Error },
#[snafu(display("Expansion operation failed: {}", source))]
Expansion { source: sandbox::Error },
#[snafu(display("Caching operation failed: {}", source))]
Caching { source: sandbox::Error },
#[snafu(display("Gist creation failed: {}", source))]
Expand Down Expand Up @@ -210,10 +207,11 @@ enum Error {
source: server_axum::api_orchestrator_integration_impls::ParseMiriRequestError,
},

// Remove at a later point. From here ...
#[snafu(display("The value {:?} is not a valid edition", value))]
InvalidEdition { value: String },
// ... to here
#[snafu(context(false))]
MacroExpansionRequest {
source: server_axum::api_orchestrator_integration_impls::ParseMacroExpansionRequestError,
},

#[snafu(display("No request was provided"))]
RequestMissing,
#[snafu(display("The cache has been poisoned"))]
Expand Down Expand Up @@ -256,6 +254,11 @@ enum Error {
source: orchestrator::coordinator::MiriError,
},

#[snafu(display("Unable to convert the macro expansion request"))]
MacroExpansion {
source: orchestrator::coordinator::MacroExpansionError,
},

#[snafu(display("The operation timed out"))]
Timeout { source: tokio::time::error::Elapsed },

Expand Down Expand Up @@ -400,6 +403,7 @@ struct MacroExpansionRequest {
#[derive(Debug, Clone, Serialize)]
struct MacroExpansionResponse {
success: bool,
exit_detail: String,
stdout: String,
stderr: String,
}
Expand Down Expand Up @@ -452,27 +456,6 @@ struct EvaluateResponse {
error: Option<String>,
}

impl TryFrom<MacroExpansionRequest> for sandbox::MacroExpansionRequest {
type Error = Error;

fn try_from(me: MacroExpansionRequest) -> Result<Self> {
Ok(sandbox::MacroExpansionRequest {
code: me.code,
edition: parse_edition(&me.edition)?,
})
}
}

impl From<sandbox::MacroExpansionResponse> for MacroExpansionResponse {
fn from(me: sandbox::MacroExpansionResponse) -> Self {
MacroExpansionResponse {
success: me.success,
stdout: me.stdout,
stderr: me.stderr,
}
}
}

impl From<Vec<sandbox::CrateInformation>> for MetaCratesResponse {
fn from(me: Vec<sandbox::CrateInformation>) -> Self {
let crates = me
Expand Down Expand Up @@ -508,17 +491,6 @@ impl From<gist::Gist> for MetaGistResponse {
}
}

fn parse_edition(s: &str) -> Result<Option<sandbox::Edition>> {
Ok(match s {
"" => None,
"2015" => Some(sandbox::Edition::Rust2015),
"2018" => Some(sandbox::Edition::Rust2018),
"2021" => Some(sandbox::Edition::Rust2021),
"2024" => Some(sandbox::Edition::Rust2024),
value => InvalidEditionSnafu { value }.fail()?,
})
}

fn default_crate_type() -> String {
"bin".into()
}
Loading

0 comments on commit 047e5b7

Please sign in to comment.