Skip to content

Commit c4445e4

Browse files
committed
Auto merge of #13165 - Veykril:breakables, r=Veykril
Properly handle break resolution inside non-breakable expressions We now diagnose invalid `continue` expressions and properly handle things like `async` blocks which prevent labels from resolving further. Cleaned this up since `label_break_value` is on the way to stabilization in rust (🎉 finally) and we weren't handling breaks for blocks properly yet.
2 parents 643c3a5 + c6b7f45 commit c4445e4

File tree

6 files changed

+312
-147
lines changed

6 files changed

+312
-147
lines changed

.github/workflows/ci.yaml

Lines changed: 78 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ on:
66
pull_request:
77
push:
88
branches:
9-
- auto
10-
- try
9+
- auto
10+
- try
1111

1212
env:
1313
CARGO_INCREMENTAL: 0
1414
CARGO_NET_RETRY: 10
1515
CI: 1
1616
RUST_BACKTRACE: short
17-
RUSTFLAGS: "-D warnings -W unreachable-pub -W rust-2021-compatibility"
17+
RUSTFLAGS: "-D warnings -W unreachable-pub -W bare-trait-objects"
1818
RUSTUP_MAX_RETRIES: 10
1919

2020
jobs:
@@ -31,25 +31,25 @@ jobs:
3131
os: [ubuntu-latest, windows-latest, macos-latest]
3232

3333
steps:
34-
- name: Checkout repository
35-
uses: actions/checkout@v3
36-
with:
37-
ref: ${{ github.event.pull_request.head.sha }}
38-
fetch-depth: 20
34+
- name: Checkout repository
35+
uses: actions/checkout@v3
36+
with:
37+
ref: ${{ github.event.pull_request.head.sha }}
38+
fetch-depth: 20
3939

40-
- name: Install Rust toolchain
41-
run: |
42-
rustup update --no-self-update stable
43-
rustup component add rustfmt rust-src
40+
- name: Install Rust toolchain
41+
run: |
42+
rustup update --no-self-update stable
43+
rustup component add rustfmt rust-src
4444
45-
- name: Cache Dependencies
46-
uses: Swatinem/rust-cache@ce325b60658c1b38465c06cc965b79baf32c1e72
45+
- name: Cache Dependencies
46+
uses: Swatinem/rust-cache@ce325b60658c1b38465c06cc965b79baf32c1e72
4747

48-
- name: Compile
49-
run: cargo test --no-run --locked
48+
- name: Compile
49+
run: cargo test --no-run --locked
5050

51-
- name: Test
52-
run: cargo test -- --nocapture --quiet
51+
- name: Test
52+
run: cargo test -- --nocapture --quiet
5353

5454
# Weird targets to catch non-portable code
5555
rust-cross:
@@ -64,25 +64,25 @@ jobs:
6464
targets_ide: "wasm32-unknown-unknown"
6565

6666
steps:
67-
- name: Checkout repository
68-
uses: actions/checkout@v3
69-
70-
- name: Install Rust toolchain
71-
run: |
72-
rustup update --no-self-update stable
73-
rustup target add ${{ env.targets }} ${{ env.targets_ide }}
74-
75-
- name: Cache Dependencies
76-
uses: Swatinem/rust-cache@ce325b60658c1b38465c06cc965b79baf32c1e72
77-
78-
- name: Check
79-
run: |
80-
for target in ${{ env.targets }}; do
81-
cargo check --target=$target --all-targets
82-
done
83-
for target in ${{ env.targets_ide }}; do
84-
cargo check -p ide --target=$target --all-targets
85-
done
67+
- name: Checkout repository
68+
uses: actions/checkout@v3
69+
70+
- name: Install Rust toolchain
71+
run: |
72+
rustup update --no-self-update stable
73+
rustup target add ${{ env.targets }} ${{ env.targets_ide }}
74+
75+
- name: Cache Dependencies
76+
uses: Swatinem/rust-cache@ce325b60658c1b38465c06cc965b79baf32c1e72
77+
78+
- name: Check
79+
run: |
80+
for target in ${{ env.targets }}; do
81+
cargo check --target=$target --all-targets
82+
done
83+
for target in ${{ env.targets_ide }}; do
84+
cargo check -p ide --target=$target --all-targets
85+
done
8686
8787
typescript:
8888
if: github.repository == 'rust-lang/rust-analyzer'
@@ -95,47 +95,47 @@ jobs:
9595
runs-on: ${{ matrix.os }}
9696

9797
steps:
98-
- name: Checkout repository
99-
uses: actions/checkout@v3
100-
101-
- name: Install Nodejs
102-
uses: actions/setup-node@v1
103-
with:
104-
node-version: 16.x
105-
106-
- name: Install xvfb
107-
if: matrix.os == 'ubuntu-latest'
108-
run: sudo apt-get install -y xvfb
109-
110-
- run: npm ci
111-
working-directory: ./editors/code
112-
113-
# - run: npm audit || { sleep 10 && npm audit; } || { sleep 30 && npm audit; }
114-
# if: runner.os == 'Linux'
115-
# working-directory: ./editors/code
116-
117-
- run: npm run lint
118-
working-directory: ./editors/code
119-
120-
- name: Run VS Code tests (Linux)
121-
if: matrix.os == 'ubuntu-latest'
122-
env:
123-
VSCODE_CLI: 1
124-
run: xvfb-run npm test
125-
working-directory: ./editors/code
126-
127-
- name: Run VS Code tests (Windows)
128-
if: matrix.os == 'windows-latest'
129-
env:
130-
VSCODE_CLI: 1
131-
run: npm test
132-
working-directory: ./editors/code
133-
134-
- run: npm run pretest
135-
working-directory: ./editors/code
136-
137-
- run: npm run package --scripts-prepend-node-path
138-
working-directory: ./editors/code
98+
- name: Checkout repository
99+
uses: actions/checkout@v3
100+
101+
- name: Install Nodejs
102+
uses: actions/setup-node@v1
103+
with:
104+
node-version: 16.x
105+
106+
- name: Install xvfb
107+
if: matrix.os == 'ubuntu-latest'
108+
run: sudo apt-get install -y xvfb
109+
110+
- run: npm ci
111+
working-directory: ./editors/code
112+
113+
# - run: npm audit || { sleep 10 && npm audit; } || { sleep 30 && npm audit; }
114+
# if: runner.os == 'Linux'
115+
# working-directory: ./editors/code
116+
117+
- run: npm run lint
118+
working-directory: ./editors/code
119+
120+
- name: Run VS Code tests (Linux)
121+
if: matrix.os == 'ubuntu-latest'
122+
env:
123+
VSCODE_CLI: 1
124+
run: xvfb-run npm test
125+
working-directory: ./editors/code
126+
127+
- name: Run VS Code tests (Windows)
128+
if: matrix.os == 'windows-latest'
129+
env:
130+
VSCODE_CLI: 1
131+
run: npm test
132+
working-directory: ./editors/code
133+
134+
- run: npm run pretest
135+
working-directory: ./editors/code
136+
137+
- run: npm run package --scripts-prepend-node-path
138+
working-directory: ./editors/code
139139

140140
end-success:
141141
name: bors build finished

crates/hir-ty/src/infer.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ pub(crate) type InferResult<T> = Result<InferOk<T>, TypeError>;
182182
#[derive(Debug, PartialEq, Eq, Clone)]
183183
pub enum InferenceDiagnostic {
184184
NoSuchField { expr: ExprId },
185-
BreakOutsideOfLoop { expr: ExprId },
185+
BreakOutsideOfLoop { expr: ExprId, is_break: bool },
186186
MismatchedArgCount { call_expr: ExprId, expected: usize, found: usize },
187187
}
188188

@@ -418,18 +418,45 @@ pub(crate) struct InferenceContext<'a> {
418418

419419
#[derive(Clone, Debug)]
420420
struct BreakableContext {
421+
/// Whether this context contains at least one break expression.
421422
may_break: bool,
423+
/// The coercion target of the context.
422424
coerce: CoerceMany,
425+
/// The optional label of the context.
423426
label: Option<name::Name>,
427+
kind: BreakableKind,
428+
}
429+
430+
#[derive(Clone, Debug)]
431+
enum BreakableKind {
432+
Block,
433+
Loop,
434+
/// A border is something like an async block, closure etc. Anything that prevents
435+
/// breaking/continuing through
436+
Border,
424437
}
425438

426439
fn find_breakable<'c>(
427440
ctxs: &'c mut [BreakableContext],
428441
label: Option<&name::Name>,
442+
) -> Option<&'c mut BreakableContext> {
443+
let mut ctxs = ctxs
444+
.iter_mut()
445+
.rev()
446+
.take_while(|it| matches!(it.kind, BreakableKind::Block | BreakableKind::Loop));
447+
match label {
448+
Some(_) => ctxs.find(|ctx| ctx.label.as_ref() == label),
449+
None => ctxs.find(|ctx| matches!(ctx.kind, BreakableKind::Loop)),
450+
}
451+
}
452+
453+
fn find_continuable<'c>(
454+
ctxs: &'c mut [BreakableContext],
455+
label: Option<&name::Name>,
429456
) -> Option<&'c mut BreakableContext> {
430457
match label {
431-
Some(_) => ctxs.iter_mut().rev().find(|ctx| ctx.label.as_ref() == label),
432-
None => ctxs.last_mut(),
458+
Some(_) => find_breakable(ctxs, label).filter(|it| matches!(it.kind, BreakableKind::Loop)),
459+
None => find_breakable(ctxs, label),
433460
}
434461
}
435462

0 commit comments

Comments
 (0)