Skip to content

Commit 252a459

Browse files
committed
Auto merge of #49371 - scottmcm:catch-wrapping, r=nikomatsakis
Add ok-wrapping to catch blocks, per RFC Updates the `catch{}` lowering to wrap the result in `Try::from_ok`. r? @nikomatsakis Fixes #41414 Fixes #43818
2 parents 4777881 + 311ff5b commit 252a459

File tree

14 files changed

+132
-43
lines changed

14 files changed

+132
-43
lines changed

src/doc/unstable-book/src/language-features/catch-expr.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ expression creates a new scope one can use the `?` operator in.
1515
use std::num::ParseIntError;
1616

1717
let result: Result<i32, ParseIntError> = do catch {
18-
Ok("1".parse::<i32>()?
18+
"1".parse::<i32>()?
1919
+ "2".parse::<i32>()?
20-
+ "3".parse::<i32>()?)
20+
+ "3".parse::<i32>()?
2121
};
2222
assert_eq!(result, Ok(6));
2323

2424
let result: Result<i32, ParseIntError> = do catch {
25-
Ok("1".parse::<i32>()?
25+
"1".parse::<i32>()?
2626
+ "foo".parse::<i32>()?
27-
+ "3".parse::<i32>()?)
27+
+ "3".parse::<i32>()?
2828
};
2929
assert!(result.is_err());
3030
```

src/librustc/hir/lowering.rs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3010,7 +3010,28 @@ 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+
let span = this.sess.codemap().end_point(unstable_span);
3021+
hir::Expr {
3022+
id: node_id,
3023+
span,
3024+
node: hir::ExprTup(hir_vec![]),
3025+
attrs: ThinVec::new(),
3026+
hir_id,
3027+
}
3028+
},
3029+
|x: P<hir::Expr>| x.into_inner(),
3030+
);
3031+
block.expr = Some(this.wrap_in_try_constructor(
3032+
"from_ok", tail, unstable_span));
3033+
hir::ExprBlock(P(block))
3034+
})
30143035
}
30153036
ExprKind::Match(ref expr, ref arms) => hir::ExprMatch(
30163037
P(self.lower_expr(expr)),
@@ -3539,12 +3560,8 @@ impl<'a> LoweringContext<'a> {
35393560

35403561
self.expr_call(e.span, from, hir_vec![err_expr])
35413562
};
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-
3563+
let from_err_expr =
3564+
self.wrap_in_try_constructor("from_error", from_expr, unstable_span);
35483565
let thin_attrs = ThinVec::from(attrs);
35493566
let catch_scope = self.catch_scopes.last().map(|x| *x);
35503567
let ret_expr = if let Some(catch_node) = catch_scope {
@@ -4079,6 +4096,18 @@ impl<'a> LoweringContext<'a> {
40794096
)
40804097
}
40814098
}
4099+
4100+
fn wrap_in_try_constructor(
4101+
&mut self,
4102+
method: &'static str,
4103+
e: hir::Expr,
4104+
unstable_span: Span,
4105+
) -> P<hir::Expr> {
4106+
let path = &["ops", "Try", method];
4107+
let from_err = P(self.expr_std_path(unstable_span, path,
4108+
ThinVec::new()));
4109+
P(self.expr_call(e.span, from_err, hir_vec![e]))
4110+
}
40824111
}
40834112

40844113
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
@@ -32,6 +32,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
3232
#![feature(nonzero)]
3333
#![feature(inclusive_range_fields)]
3434
#![feature(crate_visibility_modifier)]
35+
#![cfg_attr(stage0, feature(try_trait))]
3536

3637
extern crate arena;
3738
#[macro_use]
@@ -53,6 +54,16 @@ extern crate log_settings;
5354
extern crate rustc_apfloat;
5455
extern crate byteorder;
5556

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

5869
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;

0 commit comments

Comments
 (0)