From ea606ca9302d97921045133ef74d0f355548d286 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Mon, 6 Nov 2023 09:44:38 -0500 Subject: [PATCH 1/2] Properly return lower-level error messages from the WebSocket These are not yet surfaced anywhere useful in the UI, but at least they show up in the WebSocket inspector. --- ui/src/server_axum/websocket.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/ui/src/server_axum/websocket.rs b/ui/src/server_axum/websocket.rs index 012ef5f46..8e6551030 100644 --- a/ui/src/server_axum/websocket.rs +++ b/ui/src/server_axum/websocket.rs @@ -343,20 +343,25 @@ async fn handle_core(mut socket: WebSocket, feature_flags: FeatureFlags) { // We don't care if there are no running tasks Some(task) = manager.join_next() => { - let Err(error) = task else { continue }; - // The task was cancelled; no need to report - let Ok(panic) = error.try_into_panic() else { continue }; - - let text = match panic.downcast::() { - Ok(text) => *text, - Err(panic) => match panic.downcast::<&str>() { - Ok(text) => text.to_string(), - _ => "An unknown panic occurred".into(), + let error = match task { + Ok(Ok(())) => continue, + Ok(Err(error)) => error, + Err(error) => { + // The task was cancelled; no need to report + let Ok(panic) = error.try_into_panic() else { continue }; + + let text = match panic.downcast::() { + Ok(text) => *text, + Err(panic) => match panic.downcast::<&str>() { + Ok(text) => text.to_string(), + _ => "An unknown panic occurred".into(), + } + }; + WebSocketTaskPanicSnafu { text }.build() } }; - let error = WebSocketTaskPanicSnafu { text }.fail(); - if tx.send(error).await.is_err() { + if tx.send(Err(error)).await.is_err() { // We can't send a response break; } From a24706ffc2438a0c01ba3c9cc5f4877f326024f1 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Mon, 6 Nov 2023 10:11:03 -0500 Subject: [PATCH 2/2] Support Rust edition 2024 It's nightly-only for now, but available. --- compiler/base/modify-cargo-toml/src/lib.rs | 16 ++++++++++ compiler/base/modify-cargo-toml/src/main.rs | 4 +++ compiler/base/orchestrator/src/coordinator.rs | 29 +++++++++++++++++-- tests/spec/features/editions_spec.rb | 21 ++++++++++++++ ui/frontend/AdvancedOptionsMenu.tsx | 6 +++- ui/frontend/actions.ts | 16 ++++++++-- ui/frontend/types.ts | 1 + ui/src/main.rs | 1 + ui/src/sandbox.rs | 7 +++++ ui/src/server_axum.rs | 1 + 10 files changed, 95 insertions(+), 7 deletions(-) diff --git a/compiler/base/modify-cargo-toml/src/lib.rs b/compiler/base/modify-cargo-toml/src/lib.rs index 8b886a0a5..73b8ba8dd 100644 --- a/compiler/base/modify-cargo-toml/src/lib.rs +++ b/compiler/base/modify-cargo-toml/src/lib.rs @@ -26,6 +26,22 @@ fn ensure_string_in_vec(values: &mut Vec, val: &str) { } } +pub fn set_feature_edition2024(cargo_toml: Value) -> Value { + #[derive(Debug, Serialize, Deserialize)] + #[serde(rename_all = "kebab-case")] + struct CargoToml { + #[serde(default)] + cargo_features: Vec, + #[serde(flatten)] + other: Other, + } + + modify(cargo_toml, |mut cargo_toml: CargoToml| { + ensure_string_in_vec(&mut cargo_toml.cargo_features, "edition2024"); + cargo_toml + }) +} + pub fn set_edition(cargo_toml: Value, edition: &str) -> Value { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] diff --git a/compiler/base/modify-cargo-toml/src/main.rs b/compiler/base/modify-cargo-toml/src/main.rs index 94177c884..c9f7f252b 100644 --- a/compiler/base/modify-cargo-toml/src/main.rs +++ b/compiler/base/modify-cargo-toml/src/main.rs @@ -19,6 +19,10 @@ fn main() { let mut cargo_toml: Value = toml::from_str(&input) .unwrap_or_else(|e| panic!("Cannot parse {} as TOML: {}", input_filename.display(), e)); + if env::var_os("PLAYGROUND_FEATURE_EDITION2024").is_some() { + cargo_toml = set_feature_edition2024(cargo_toml); + } + if let Ok(edition) = env::var("PLAYGROUND_EDITION") { cargo_toml = set_edition(cargo_toml, &edition); } diff --git a/compiler/base/orchestrator/src/coordinator.rs b/compiler/base/orchestrator/src/coordinator.rs index aac9f4d7d..e5380c9f3 100644 --- a/compiler/base/orchestrator/src/coordinator.rs +++ b/compiler/base/orchestrator/src/coordinator.rs @@ -91,17 +91,24 @@ pub enum Edition { Rust2015, Rust2018, Rust2021, + Rust2024, } impl Edition { #[cfg(test)] - pub(crate) const ALL: [Self; 3] = [Self::Rust2015, Self::Rust2018, Self::Rust2021]; + pub(crate) const ALL: [Self; 4] = [ + Self::Rust2015, + Self::Rust2018, + Self::Rust2021, + Self::Rust2024, + ]; pub(crate) fn to_str(self) -> &'static str { match self { Edition::Rust2015 => "2015", Edition::Rust2018 => "2018", Edition::Rust2021 => "2021", + Edition::Rust2024 => "2024", } } @@ -221,6 +228,10 @@ impl ExecuteRequest { impl CargoTomlModifier for ExecuteRequest { 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() { @@ -321,6 +332,10 @@ impl CompileRequest { impl CargoTomlModifier for CompileRequest { 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() { @@ -1526,8 +1541,16 @@ mod tests { #[snafu::report] async fn execute_edition() -> Result<()> { let params = [ - (r#"fn x() { let dyn = true; }"#, [true, false, false]), - (r#"fn x() { u16::try_from(1u8); }"#, [false, false, true]), + (r#"fn x() { let dyn = true; }"#, [true, false, false, false]), + ( + r#"fn x() { u16::try_from(1u8); }"#, + [false, false, true, true], + ), + ( + r#"#![feature(gen_blocks)] + fn x() { gen { yield 1u8 }; }"#, + [false, false, false, true], + ), ]; let tests = params.into_iter().flat_map(|(code, works_in)| { diff --git a/tests/spec/features/editions_spec.rb b/tests/spec/features/editions_spec.rb index e6bcc25f2..f828c3db7 100644 --- a/tests/spec/features/editions_spec.rb +++ b/tests/spec/features/editions_spec.rb @@ -37,6 +37,27 @@ end end + scenario "using the 2024 edition" do + editor.set <<-EOF + #![feature(gen_blocks)] + + fn main() { + let mut x = gen { yield 1 }; + + eprintln!("{:?}", x.next()); + eprintln!("{:?}", x.next()); + } + EOF + + in_advanced_options_menu { select '2024' } + click_on("Run") + + within(:output, :stderr) do + expect(page).to have_content 'Some(1)' + expect(page).to have_content 'None' + end + end + def editor Editor.new(page) end diff --git a/ui/frontend/AdvancedOptionsMenu.tsx b/ui/frontend/AdvancedOptionsMenu.tsx index 8c001734a..900f61fff 100644 --- a/ui/frontend/AdvancedOptionsMenu.tsx +++ b/ui/frontend/AdvancedOptionsMenu.tsx @@ -6,7 +6,7 @@ import { Either as EitherConfig, Select as SelectConfig } from './ConfigElement' import MenuGroup from './MenuGroup'; import { State } from './reducers'; import * as selectors from './selectors'; -import { Backtrace, Edition } from './types'; +import { Backtrace, Channel, Edition } from './types'; const AdvancedOptionsMenu: React.FC = () => { const isEditionDefault = useSelector(selectors.isEditionDefault); @@ -19,6 +19,9 @@ const AdvancedOptionsMenu: React.FC = () => { const changeEdition = useCallback((e: Edition) => dispatch(actions.changeEdition(e)), [dispatch]); const changeBacktrace = useCallback((b: Backtrace) => dispatch(actions.changeBacktrace(b)), [dispatch]); + const channel = useSelector((state: State) => state.configuration.channel); + const switchText = (channel !== Channel.Nightly) ? ' (will select nightly Rust)' : ''; + return ( { + export const changeMode = (mode: Mode) => createAction(ActionType.ChangeMode, { mode }); -export const changeEdition = (edition: Edition) => +const changeEditionRaw = (edition: Edition) => createAction(ActionType.ChangeEdition, { edition }); +export const changeEdition = (edition: Edition): ThunkAction => dispatch => { + if (edition === Edition.Rust2024) { + dispatch(changeChannel(Channel.Nightly)); + } + + dispatch(changeEditionRaw(edition)); +} + export const changeBacktrace = (backtrace: Backtrace) => createAction(ActionType.ChangeBacktrace, { backtrace }); @@ -561,6 +569,8 @@ function parseEdition(s?: string): Edition | null { return Edition.Rust2018; case '2021': return Edition.Rust2021; + case '2024': + return Edition.Rust2024; default: return null; } @@ -599,7 +609,7 @@ export function indexPageLoad({ dispatch(changeChannel(channel)); dispatch(changeMode(mode)); - dispatch(changeEdition(edition)); + dispatch(changeEditionRaw(edition)); }; } @@ -622,7 +632,7 @@ export type Action = | ReturnType | ReturnType | ReturnType - | ReturnType + | ReturnType | ReturnType | ReturnType | ReturnType diff --git a/ui/frontend/types.ts b/ui/frontend/types.ts index 8c27a5472..50beb8850 100644 --- a/ui/frontend/types.ts +++ b/ui/frontend/types.ts @@ -98,6 +98,7 @@ export enum Edition { Rust2015 = '2015', Rust2018 = '2018', Rust2021 = '2021', + Rust2024 = '2024', } export enum Backtrace { diff --git a/ui/src/main.rs b/ui/src/main.rs index b3f5f4793..b5eb6a5e8 100644 --- a/ui/src/main.rs +++ b/ui/src/main.rs @@ -548,6 +548,7 @@ fn parse_edition(s: &str) -> Result> { "2015" => Some(sandbox::Edition::Rust2015), "2018" => Some(sandbox::Edition::Rust2018), "2021" => Some(sandbox::Edition::Rust2021), + "2024" => Some(sandbox::Edition::Rust2024), value => InvalidEditionSnafu { value }.fail()?, }) } diff --git a/ui/src/sandbox.rs b/ui/src/sandbox.rs index fd77473fa..b618d9b54 100644 --- a/ui/src/sandbox.rs +++ b/ui/src/sandbox.rs @@ -565,6 +565,7 @@ pub enum Edition { Rust2015, Rust2018, Rust2021, // TODO - add parallel tests for 2021 + Rust2024, } impl Edition { @@ -575,6 +576,7 @@ impl Edition { Rust2015 => "2015", Rust2018 => "2018", Rust2021 => "2021", + Rust2024 => "2024", } } } @@ -639,6 +641,10 @@ impl DockerCommandExt for Command { fn apply_edition(&mut self, req: impl EditionRequest) { if let Some(edition) = req.edition() { + if edition == Edition::Rust2024 { + self.args(&["--env", &format!("PLAYGROUND_FEATURE_EDITION2024=true")]); + } + self.args(&[ "--env", &format!("PLAYGROUND_EDITION={}", edition.cargo_ident()), @@ -799,6 +805,7 @@ mod sandbox_orchestrator_integration_impls { coordinator::Edition::Rust2015 => super::Edition::Rust2015, coordinator::Edition::Rust2018 => super::Edition::Rust2018, coordinator::Edition::Rust2021 => super::Edition::Rust2021, + coordinator::Edition::Rust2024 => super::Edition::Rust2024, } } } diff --git a/ui/src/server_axum.rs b/ui/src/server_axum.rs index 8be8508be..bbf0dab8b 100644 --- a/ui/src/server_axum.rs +++ b/ui/src/server_axum.rs @@ -1127,6 +1127,7 @@ pub(crate) mod api_orchestrator_integration_impls { "2015" => Edition::Rust2015, "2018" => Edition::Rust2018, "2021" => Edition::Rust2021, + "2024" => Edition::Rust2024, value => return ParseEditionSnafu { value }.fail(), }) }