Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Rust edition 2024 #994

Merged
merged 2 commits into from
Nov 6, 2023
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
16 changes: 16 additions & 0 deletions compiler/base/modify-cargo-toml/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,22 @@ fn ensure_string_in_vec(values: &mut Vec<String>, 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<String>,
#[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")]
Expand Down
4 changes: 4 additions & 0 deletions compiler/base/modify-cargo-toml/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
29 changes: 26 additions & 3 deletions compiler/base/orchestrator/src/coordinator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
}
}

Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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)| {
Expand Down
21 changes: 21 additions & 0 deletions tests/spec/features/editions_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion ui/frontend/AdvancedOptionsMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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 (
<MenuGroup title="Advanced options">
<SelectConfig
Expand All @@ -30,6 +33,7 @@ const AdvancedOptionsMenu: React.FC = () => {
<option value={Edition.Rust2015}>2015</option>
<option value={Edition.Rust2018}>2018</option>
<option value={Edition.Rust2021}>2021</option>
<option value={Edition.Rust2024}>2024{switchText}</option>
</SelectConfig>

<EitherConfig
Expand Down
16 changes: 13 additions & 3 deletions ui/frontend/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,17 @@ export const changeChannel = (channel: Channel) =>
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 });

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -599,7 +609,7 @@ export function indexPageLoad({

dispatch(changeChannel(channel));
dispatch(changeMode(mode));
dispatch(changeEdition(edition));
dispatch(changeEditionRaw(edition));
};
}

Expand All @@ -622,7 +632,7 @@ export type Action =
| ReturnType<typeof changeBacktrace>
| ReturnType<typeof changeChannel>
| ReturnType<typeof changeDemangleAssembly>
| ReturnType<typeof changeEdition>
| ReturnType<typeof changeEditionRaw>
| ReturnType<typeof changeEditor>
| ReturnType<typeof changeFocus>
| ReturnType<typeof changeKeybinding>
Expand Down
1 change: 1 addition & 0 deletions ui/frontend/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export enum Edition {
Rust2015 = '2015',
Rust2018 = '2018',
Rust2021 = '2021',
Rust2024 = '2024',
}

export enum Backtrace {
Expand Down
1 change: 1 addition & 0 deletions ui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,7 @@ fn parse_edition(s: &str) -> Result<Option<sandbox::Edition>> {
"2015" => Some(sandbox::Edition::Rust2015),
"2018" => Some(sandbox::Edition::Rust2018),
"2021" => Some(sandbox::Edition::Rust2021),
"2024" => Some(sandbox::Edition::Rust2024),
value => InvalidEditionSnafu { value }.fail()?,
})
}
Expand Down
7 changes: 7 additions & 0 deletions ui/src/sandbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,7 @@ pub enum Edition {
Rust2015,
Rust2018,
Rust2021, // TODO - add parallel tests for 2021
Rust2024,
}

impl Edition {
Expand All @@ -575,6 +576,7 @@ impl Edition {
Rust2015 => "2015",
Rust2018 => "2018",
Rust2021 => "2021",
Rust2024 => "2024",
}
}
}
Expand Down Expand Up @@ -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()),
Expand Down Expand Up @@ -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,
}
}
}
Expand Down
1 change: 1 addition & 0 deletions ui/src/server_axum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
})
}
Expand Down
27 changes: 16 additions & 11 deletions ui/src/server_axum/websocket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<String>() {
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::<String>() {
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;
}
Expand Down