Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit c4b6521

Browse files
committed
Add ok-wrapping to catch blocks, per RFC
1 parent 0b72d48 commit c4b6521

File tree

11 files changed

+80
-39
lines changed

11 files changed

+80
-39
lines changed

src/librustc/hir/lowering.rs

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3010,7 +3010,27 @@ impl<'a> LoweringContext<'a> {
30103010
)
30113011
}),
30123012
ExprKind::Catch(ref body) => {
3013-
self.with_catch_scope(body.id, |this| hir::ExprBlock(this.lower_block(body, true)))
3013+
self.with_catch_scope(body.id, |this| {
3014+
let unstable_span =
3015+
this.allow_internal_unstable(CompilerDesugaringKind::Catch, body.span);
3016+
let mut block = this.lower_block(body, true).into_inner();
3017+
let tail = block.expr.take().map_or_else(
3018+
|| {
3019+
let LoweredNodeId { node_id, hir_id } = this.next_id();
3020+
hir::Expr {
3021+
id: node_id,
3022+
span: unstable_span,
3023+
node: hir::ExprTup(hir_vec![]),
3024+
attrs: ThinVec::new(),
3025+
hir_id,
3026+
}
3027+
},
3028+
|x: P<hir::Expr>| x.into_inner(),
3029+
);
3030+
block.expr = Some(this.wrap_in_try_constructor(
3031+
"from_ok", tail, unstable_span));
3032+
hir::ExprBlock(P(block))
3033+
})
30143034
}
30153035
ExprKind::Match(ref expr, ref arms) => hir::ExprMatch(
30163036
P(self.lower_expr(expr)),
@@ -3539,12 +3559,8 @@ impl<'a> LoweringContext<'a> {
35393559

35403560
self.expr_call(e.span, from, hir_vec![err_expr])
35413561
};
3542-
let from_err_expr = {
3543-
let path = &["ops", "Try", "from_error"];
3544-
let from_err = P(self.expr_std_path(unstable_span, path, ThinVec::new()));
3545-
P(self.expr_call(e.span, from_err, hir_vec![from_expr]))
3546-
};
3547-
3562+
let from_err_expr =
3563+
self.wrap_in_try_constructor("from_error", from_expr, unstable_span);
35483564
let thin_attrs = ThinVec::from(attrs);
35493565
let catch_scope = self.catch_scopes.last().map(|x| *x);
35503566
let ret_expr = if let Some(catch_node) = catch_scope {
@@ -4079,6 +4095,18 @@ impl<'a> LoweringContext<'a> {
40794095
)
40804096
}
40814097
}
4098+
4099+
fn wrap_in_try_constructor(
4100+
&mut self,
4101+
method: &'static str,
4102+
e: hir::Expr,
4103+
unstable_span: Span,
4104+
) -> P<hir::Expr> {
4105+
let path = &["ops", "Try", method];
4106+
let from_err = P(self.expr_std_path(unstable_span, path,
4107+
ThinVec::new()));
4108+
P(self.expr_call(e.span, from_err, hir_vec![e]))
4109+
}
40824110
}
40834111

40844112
fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body>) -> Vec<hir::BodyId> {

src/librustc/ich/impls_syntax.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,8 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
372372

373373
impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
374374
DotFill,
375-
QuestionMark
375+
QuestionMark,
376+
Catch
376377
});
377378

378379
impl_stable_hash_for!(enum ::syntax_pos::FileName {

src/librustc_mir/borrow_check/nll/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,11 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
202202
});
203203

204204
// Also dump the inference graph constraints as a graphviz file.
205-
let _: io::Result<()> = do catch {
205+
let _: io::Result<()> = do_catch! {{
206206
let mut file =
207207
pretty::create_dump_file(infcx.tcx, "regioncx.dot", None, "nll", &0, source)?;
208-
regioncx.dump_graphviz(&mut file)
209-
};
208+
regioncx.dump_graphviz(&mut file)?;
209+
}};
210210
}
211211

212212
fn dump_annotation<'a, 'gcx, 'tcx>(

src/librustc_mir/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
3333
#![feature(nonzero)]
3434
#![feature(inclusive_range_fields)]
3535
#![feature(crate_visibility_modifier)]
36+
#![cfg_attr(stage0, feature(try_trait))]
3637

3738
extern crate arena;
3839
#[macro_use]
@@ -54,6 +55,16 @@ extern crate log_settings;
5455
extern crate rustc_apfloat;
5556
extern crate byteorder;
5657

58+
#[cfg(stage0)]
59+
macro_rules! do_catch {
60+
($t:expr) => { (|| ::std::ops::Try::from_ok($t) )() }
61+
}
62+
63+
#[cfg(not(stage0))]
64+
macro_rules! do_catch {
65+
($t:expr) => { do catch { $t } }
66+
}
67+
5768
mod diagnostics;
5869

5970
mod borrow_check;

src/librustc_mir/util/pretty.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(
137137
) where
138138
F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
139139
{
140-
let _: io::Result<()> = do catch {
140+
let _: io::Result<()> = do_catch! {{
141141
let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?;
142142
writeln!(file, "// MIR for `{}`", node_path)?;
143143
writeln!(file, "// source = {:?}", source)?;
@@ -150,16 +150,14 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(
150150
extra_data(PassWhere::BeforeCFG, &mut file)?;
151151
write_mir_fn(tcx, source, mir, &mut extra_data, &mut file)?;
152152
extra_data(PassWhere::AfterCFG, &mut file)?;
153-
Ok(())
154-
};
153+
}};
155154

156155
if tcx.sess.opts.debugging_opts.dump_mir_graphviz {
157-
let _: io::Result<()> = do catch {
156+
let _: io::Result<()> = do_catch! {{
158157
let mut file =
159158
create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, source)?;
160159
write_mir_fn_graphviz(tcx, source.def_id, mir, &mut file)?;
161-
Ok(())
162-
};
160+
}};
163161
}
164162
}
165163

src/libsyntax_pos/hygiene.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ pub enum ExpnFormat {
432432
pub enum CompilerDesugaringKind {
433433
DotFill,
434434
QuestionMark,
435+
Catch,
435436
}
436437

437438
impl CompilerDesugaringKind {
@@ -440,6 +441,7 @@ impl CompilerDesugaringKind {
440441
let s = match *self {
441442
DotFill => "...",
442443
QuestionMark => "?",
444+
Catch => "do catch",
443445
};
444446
Symbol::intern(s)
445447
}

src/test/compile-fail/catch-bad-lifetime.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ pub fn main() {
2121
//~^ ERROR `my_string` does not live long enough
2222
Err(my_str) ?;
2323
Err("") ?;
24-
Ok(())
2524
};
2625
}
2726

@@ -32,7 +31,6 @@ pub fn main() {
3231
let mut j: Result<(), &mut i32> = do catch {
3332
Err(k) ?;
3433
i = 10; //~ ERROR cannot assign to `i` because it is borrowed
35-
Ok(())
3634
};
3735
::std::mem::drop(k); //~ ERROR use of moved value: `k`
3836
i = 40; //~ ERROR cannot assign to `i` because it is borrowed

src/test/compile-fail/catch-bad-type.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,18 @@
1111
#![feature(catch_expr)]
1212

1313
pub fn main() {
14-
let res: Result<i32, i32> = do catch {
14+
let res: Result<u32, i32> = do catch {
1515
Err("")?; //~ ERROR the trait bound `i32: std::convert::From<&str>` is not satisfied
16-
Ok(5)
16+
5
1717
};
18+
1819
let res: Result<i32, i32> = do catch {
19-
Ok("") //~ mismatched types
20+
"" //~ ERROR type mismatch
2021
};
22+
23+
let res: Result<i32, i32> = do catch { }; //~ ERROR type mismatch
24+
25+
let res: () = do catch { }; //~ the trait bound `(): std::ops::Try` is not satisfied
26+
27+
let res: i32 = do catch { 5 }; //~ ERROR the trait bound `i32: std::ops::Try` is not satisfied
2128
}

src/test/compile-fail/catch-maybe-bad-lifetime.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub fn main() {
1717
let mut i = 222;
1818
let x: Result<&i32, ()> = do catch {
1919
Err(())?;
20-
Ok(&i)
20+
&i
2121
};
2222
x.ok().cloned();
2323
i = 0; //~ ERROR cannot assign to `i` because it is borrowed
@@ -29,7 +29,6 @@ pub fn main() {
2929
let _y: Result<(), ()> = do catch {
3030
Err(())?;
3131
::std::mem::drop(x);
32-
Ok(())
3332
};
3433
println!("{}", x); //~ ERROR use of moved value: `x`
3534
}
@@ -42,7 +41,6 @@ pub fn main() {
4241
let x: Result<(), ()> = do catch {
4342
Err(())?;
4443
j = &i;
45-
Ok(())
4644
};
4745
i = 0; //~ ERROR cannot assign to `i` because it is borrowed
4846
let _ = i;

src/test/compile-fail/catch-opt-init.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ pub fn main() {
1919
cfg_res = 5;
2020
Ok::<(), ()>(())?;
2121
use_val(cfg_res);
22-
Ok(())
2322
};
2423
assert_eq!(cfg_res, 5); //~ ERROR use of possibly uninitialized variable
2524
}

src/test/run-pass/catch-expr.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
struct catch {}
1414

1515
pub fn main() {
16-
let catch_result = do catch {
16+
let catch_result: Option<_> = do catch {
1717
let x = 5;
1818
x
1919
};
20-
assert_eq!(catch_result, 5);
20+
assert_eq!(catch_result, Some(5));
2121

2222
let mut catch = true;
2323
while catch { catch = false; }
@@ -30,51 +30,50 @@ pub fn main() {
3030
_ => {}
3131
};
3232

33-
let catch_err = do catch {
33+
let catch_err: Result<_, i32> = do catch {
3434
Err(22)?;
35-
Ok(1)
35+
1
3636
};
3737
assert_eq!(catch_err, Err(22));
3838

3939
let catch_okay: Result<i32, i32> = do catch {
4040
if false { Err(25)?; }
4141
Ok::<(), i32>(())?;
42-
Ok(28)
42+
28
4343
};
4444
assert_eq!(catch_okay, Ok(28));
4545

4646
let catch_from_loop: Result<i32, i32> = do catch {
4747
for i in 0..10 {
4848
if i < 5 { Ok::<i32, i32>(i)?; } else { Err(i)?; }
4949
}
50-
Ok(22)
50+
22
5151
};
5252
assert_eq!(catch_from_loop, Err(5));
5353

5454
let cfg_init;
5555
let _res: Result<(), ()> = do catch {
5656
cfg_init = 5;
57-
Ok(())
5857
};
5958
assert_eq!(cfg_init, 5);
6059

6160
let cfg_init_2;
6261
let _res: Result<(), ()> = do catch {
6362
cfg_init_2 = 6;
6463
Err(())?;
65-
Ok(())
6664
};
6765
assert_eq!(cfg_init_2, 6);
6866

6967
let my_string = "test".to_string();
7068
let res: Result<&str, ()> = do catch {
71-
Ok(&my_string)
69+
// Unfortunately, deref doesn't fire here (#49356)
70+
&my_string[..]
7271
};
7372
assert_eq!(res, Ok("test"));
7473

75-
do catch {
76-
()
77-
}
74+
let my_opt: Option<_> = do catch { () };
75+
assert_eq!(my_opt, Some(()));
7876

79-
();
77+
let my_opt: Option<_> = do catch { };
78+
assert_eq!(my_opt, Some(()));
8079
}

0 commit comments

Comments
 (0)