Skip to content

Commit ae0b81d

Browse files
authored
Merge pull request #1074 from GoldsteinE/aliasing-modes
Allow user to specify aliasing model for Miri
2 parents 7554bbd + 7c4f574 commit ae0b81d

17 files changed

+233
-76
lines changed

compiler/base/cargo-miri-playground

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
set -eu
44

55
export MIRI_SYSROOT=~/.cache/miri
6-
export MIRIFLAGS="-Zmiri-disable-isolation"
6+
export MIRIFLAGS="${MIRIFLAGS:-} -Zmiri-disable-isolation"
77
exec cargo miri run

compiler/base/orchestrator/src/coordinator.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,12 @@ pub enum Channel {
239239
Nightly,
240240
}
241241

242+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
243+
pub enum AliasingModel {
244+
Stacked,
245+
Tree,
246+
}
247+
242248
impl Channel {
243249
#[cfg(test)]
244250
pub(crate) const ALL: [Self; 3] = [Self::Stable, Self::Beta, Self::Nightly];
@@ -654,6 +660,7 @@ pub struct MiriRequest {
654660
pub channel: Channel,
655661
pub crate_type: CrateType,
656662
pub edition: Edition,
663+
pub aliasing_model: AliasingModel,
657664
pub code: String,
658665
}
659666

@@ -667,10 +674,18 @@ impl LowerRequest for MiriRequest {
667674
}
668675

669676
fn execute_cargo_request(&self) -> ExecuteCommandRequest {
677+
let mut miriflags = Vec::new();
678+
679+
if matches!(self.aliasing_model, AliasingModel::Tree) {
680+
miriflags.push("-Zmiri-tree-borrows");
681+
}
682+
683+
let miriflags = miriflags.join(" ");
684+
670685
ExecuteCommandRequest {
671686
cmd: "cargo".to_owned(),
672687
args: vec!["miri-playground".to_owned()],
673-
envs: Default::default(),
688+
envs: HashMap::from_iter([("MIRIFLAGS".to_owned(), miriflags)]),
674689
cwd: None,
675690
}
676691
}
@@ -3939,6 +3954,7 @@ mod tests {
39393954
channel: Channel::Nightly,
39403955
crate_type: CrateType::Binary,
39413956
edition: Edition::Rust2021,
3957+
aliasing_model: AliasingModel::Stacked,
39423958
code: String::new(),
39433959
};
39443960

compiler/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/bash
1+
#!/usr/bin/env bash
22

33
set -euv -o pipefail
44

compiler/fetch.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/bash
1+
#!/usr/bin/env bash
22

33
set -euv -o pipefail
44

tests/spec/features/backtrace_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
context "backtraces are enabled" do
1414
before do
15-
in_advanced_options_menu { choose 'enabled' }
15+
in_advanced_options_menu { within(:config_option, 'Backtrace') { choose 'On' } }
1616
within(:header) { click_on("Run") }
1717
end
1818

tests/spec/features/tools_spec.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,30 @@ def code_with_undefined_behavior
5454
EOF
5555
end
5656

57+
scenario "configure Miri for tree borrows" do
58+
editor.set code_valid_under_tree_borrows_but_not_stacked_borrows
59+
in_advanced_options_menu { choose("tree") }
60+
in_tools_menu { click_on("Miri") }
61+
62+
within(:output, :stdout) do
63+
expect(page).to have_content %r{[1, 2]}, wait: 10
64+
end
65+
66+
within(:output, :stderr) do
67+
expect(page).to_not have_content %r{Undefined Behavior}
68+
end
69+
end
70+
71+
def code_valid_under_tree_borrows_but_not_stacked_borrows
72+
<<~EOF
73+
fn main() {
74+
let val = [1u8, 2];
75+
let ptr = &val[0] as *const u8;
76+
let _val = unsafe { *ptr.add(1) };
77+
}
78+
EOF
79+
end
80+
5781
scenario "expand macros with the nightly compiler" do
5882
editor.set code_that_uses_macros
5983
in_tools_menu { click_on("Expand macros") }

tests/spec/spec_helper.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@
8888
css { '[data-test-id = "notification"]' }
8989
end
9090

91+
Capybara.add_selector(:config_option) do
92+
xpath do |label|
93+
".//div[span[contains(., '#{label}')]]"
94+
end
95+
end
96+
9197
RSpec.configure do |config|
9298
config.after(:example, :js) do
9399
page.execute_script <<~JS

ui/frontend/.prettierignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ node_modules
1212
*.scss
1313

1414
# Slowly migrate files that we've touched
15+
!AdvancedOptionsMenu.tsx
1516
!BuildMenu.tsx
1617
!ButtonSet.tsx
18+
!ConfigElement.tsx
1719
!Header.tsx
1820
!HelpExample.tsx
1921
!Notifications.tsx

ui/frontend/AdvancedOptionsMenu.tsx

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,83 @@
11
import React, { useCallback } from 'react';
22

3-
import * as config from './reducers/configuration';
43
import { Either as EitherConfig, Select as SelectConfig } from './ConfigElement';
4+
import MenuAside from './MenuAside';
55
import MenuGroup from './MenuGroup';
6-
import * as selectors from './selectors';
7-
import { Backtrace, Edition } from './types';
86
import { useAppDispatch, useAppSelector } from './hooks';
7+
import * as config from './reducers/configuration';
8+
import * as selectors from './selectors';
9+
import { AliasingModel, Backtrace, Edition } from './types';
10+
11+
const MIRI_TREE_BORROWS_URL = 'https://github.com/rust-lang/miri#user-content--zmiri-tree-borrows';
12+
13+
const TreeBorrowAside: React.FC = () => (
14+
<MenuAside>
15+
Code that is accepted by <a href={MIRI_TREE_BORROWS_URL}>Tree Borrows</a> may be declared
16+
undefined behavior in the future.
17+
</MenuAside>
18+
);
919

1020
const AdvancedOptionsMenu: React.FC = () => {
1121
const isEditionDefault = useAppSelector(selectors.isEditionDefault);
1222
const edition = useAppSelector((state) => state.configuration.edition);
13-
const isBacktraceSet = useAppSelector(selectors.getBacktraceSet);
23+
const isBacktraceDefault = useAppSelector(selectors.isBacktraceDefault);
1424
const backtrace = useAppSelector((state) => state.configuration.backtrace);
25+
const isAliasingModelDefault = useAppSelector(selectors.isAliasingModelDefault);
26+
const aliasingModel = useAppSelector((state) => state.configuration.aliasingModel);
1527

1628
const dispatch = useAppDispatch();
1729

1830
const changeEdition = useCallback((e: Edition) => dispatch(config.changeEdition(e)), [dispatch]);
19-
const changeBacktrace = useCallback((b: Backtrace) => dispatch(config.changeBacktrace(b)), [dispatch]);
31+
const changeBacktrace = useCallback(
32+
(b: Backtrace) => dispatch(config.changeBacktrace(b)),
33+
[dispatch],
34+
);
35+
const changeAliasingModel = useCallback(
36+
(b: AliasingModel) => dispatch(config.changeAliasingModel(b)),
37+
[dispatch],
38+
);
2039

2140
return (
22-
<MenuGroup title="Advanced options">
23-
<SelectConfig
24-
name="Edition"
25-
value={edition}
26-
isNotDefault={!isEditionDefault}
27-
onChange={changeEdition}
28-
>
29-
<option value={Edition.Rust2015}>2015</option>
30-
<option value={Edition.Rust2018}>2018</option>
31-
<option value={Edition.Rust2021}>2021</option>
32-
<option value={Edition.Rust2024}>2024</option>
33-
</SelectConfig>
34-
35-
<EitherConfig
36-
id="backtrace"
37-
name="Backtrace"
38-
a={Backtrace.Disabled}
39-
b={Backtrace.Enabled}
40-
value={backtrace}
41-
isNotDefault={isBacktraceSet}
42-
onChange={changeBacktrace} />
43-
</MenuGroup>
41+
<>
42+
<MenuGroup title="Advanced options">
43+
<SelectConfig
44+
name="Edition"
45+
value={edition}
46+
isDefault={isEditionDefault}
47+
onChange={changeEdition}
48+
>
49+
<option value={Edition.Rust2015}>2015</option>
50+
<option value={Edition.Rust2018}>2018</option>
51+
<option value={Edition.Rust2021}>2021</option>
52+
<option value={Edition.Rust2024}>2024</option>
53+
</SelectConfig>
54+
55+
<EitherConfig
56+
id="backtrace"
57+
name="Backtrace"
58+
a={Backtrace.Enabled}
59+
b={Backtrace.Disabled}
60+
aLabel="On"
61+
bLabel="Off"
62+
value={backtrace}
63+
isDefault={isBacktraceDefault}
64+
onChange={changeBacktrace}
65+
/>
66+
</MenuGroup>
67+
68+
<MenuGroup title="Miri">
69+
<EitherConfig
70+
id="aliasingModel"
71+
name="Aliasing model"
72+
a={AliasingModel.Stacked}
73+
b={AliasingModel.Tree}
74+
value={aliasingModel}
75+
isDefault={isAliasingModelDefault}
76+
onChange={changeAliasingModel}
77+
aside={<TreeBorrowAside />}
78+
/>
79+
</MenuGroup>
80+
</>
4481
);
4582
};
4683

ui/frontend/ConfigElement.tsx

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,37 +14,54 @@ interface EitherProps<T extends string> extends ConfigElementProps {
1414
onChange: (_: T) => void;
1515
}
1616

17-
export const Either =
18-
<T extends string,>({ id, a, b, aLabel = a, bLabel = b, value, onChange, ...rest }: EitherProps<T>) => (
19-
<ConfigElement {...rest}>
20-
<div className={styles.toggle}>
21-
<input id={`${id}-a`}
22-
name={id}
23-
value={a}
24-
type="radio"
25-
checked={value === a}
26-
onChange={() => onChange(a as T)} />
27-
<label htmlFor={`${id}-a`}>{aLabel}</label>
28-
<input id={`${id}-b`}
29-
name={id}
30-
value={b}
31-
type="radio"
32-
checked={value === b}
33-
onChange={() => onChange(b as T)} />
34-
<label htmlFor={`${id}-b`}>{bLabel}</label>
35-
</div>
36-
</ConfigElement>
37-
);
17+
export const Either = <T extends string>({
18+
id,
19+
a,
20+
b,
21+
aLabel = a,
22+
bLabel = b,
23+
value,
24+
onChange,
25+
...rest
26+
}: EitherProps<T>) => (
27+
<ConfigElement {...rest}>
28+
<div className={styles.toggle}>
29+
<input
30+
id={`${id}-a`}
31+
name={id}
32+
value={a}
33+
type="radio"
34+
checked={value === a}
35+
onChange={() => onChange(a as T)}
36+
/>
37+
<label htmlFor={`${id}-a`}>{aLabel}</label>
38+
<input
39+
id={`${id}-b`}
40+
name={id}
41+
value={b}
42+
type="radio"
43+
checked={value === b}
44+
onChange={() => onChange(b as T)}
45+
/>
46+
<label htmlFor={`${id}-b`}>{bLabel}</label>
47+
</div>
48+
</ConfigElement>
49+
);
3850

3951
interface SelectProps<T extends string> extends ConfigElementProps {
4052
children: React.ReactNode;
4153
value: T;
4254
onChange: (_: T) => void;
4355
}
4456

45-
export const Select = <T extends string,>({ value, onChange, children, ...rest }: SelectProps<T>) => (
57+
export const Select = <T extends string>({
58+
value,
59+
onChange,
60+
children,
61+
...rest
62+
}: SelectProps<T>) => (
4663
<ConfigElement {...rest}>
47-
<select className={styles.select} value={value} onChange={e => onChange(e.target.value as T)}>
64+
<select className={styles.select} value={value} onChange={(e) => onChange(e.target.value as T)}>
4865
{children}
4966
</select>
5067
</ConfigElement>
@@ -53,18 +70,21 @@ export const Select = <T extends string,>({ value, onChange, children, ...rest }
5370
interface ConfigElementProps {
5471
children?: React.ReactNode;
5572
name: string;
56-
isNotDefault?: boolean;
57-
aside?: JSX.Element,
73+
isDefault?: boolean;
74+
aside?: JSX.Element;
5875
}
5976

60-
const ConfigElement: React.FC<ConfigElementProps> = ({ name, isNotDefault, aside, children }) => (
61-
<MenuItem>
62-
<div className={styles.container}>
63-
<span className={isNotDefault ? styles.notDefault : styles.name}>{name}</span>
64-
<div className={styles.value}>
65-
{children}
77+
const ConfigElement: React.FC<ConfigElementProps> = ({ name, isDefault, aside, children }) => {
78+
const actuallyDefault = isDefault ?? true;
79+
const defaultStyle = actuallyDefault ? styles.name : styles.notDefault;
80+
81+
return (
82+
<MenuItem>
83+
<div className={styles.container}>
84+
<span className={defaultStyle}>{name}</span>
85+
<div className={styles.value}>{children}</div>
6686
</div>
67-
</div>
68-
{aside}
69-
</MenuItem>
70-
);
87+
{aside}
88+
</MenuItem>
89+
);
90+
};

ui/frontend/reducers/configuration.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
22

33
import {
4+
AliasingModel,
45
AssemblyFlavor,
56
Backtrace,
67
Channel,
@@ -36,6 +37,7 @@ interface State {
3637
mode: Mode;
3738
edition: Edition;
3839
backtrace: Backtrace;
40+
aliasingModel: AliasingModel;
3941
}
4042

4143
const initialState: State = {
@@ -58,6 +60,7 @@ const initialState: State = {
5860
mode: Mode.Debug,
5961
edition: Edition.Rust2024,
6062
backtrace: Backtrace.Disabled,
63+
aliasingModel: AliasingModel.Stacked,
6164
};
6265

6366
const slice = createSlice({
@@ -76,6 +79,10 @@ const slice = createSlice({
7679
state.backtrace = action.payload;
7780
},
7881

82+
changeAliasingModel: (state, action: PayloadAction<AliasingModel>) => {
83+
state.aliasingModel = action.payload;
84+
},
85+
7986
changeChannel: (state, action: PayloadAction<Channel>) => {
8087
state.channel = action.payload;
8188
},
@@ -146,6 +153,7 @@ export const {
146153
changeAceTheme,
147154
changeAssemblyFlavor,
148155
changeBacktrace,
156+
changeAliasingModel,
149157
changeChannel,
150158
changeDemangleAssembly,
151159
changeEdition,

0 commit comments

Comments
 (0)