1
Fork 0

Rollup merge of #60064 - estebank:issue-59980, r=varkor

Point at try `?` on errors affecting the err match arm of the desugared code

Fix #59980.
This commit is contained in:
Mazdak Farrokhzad 2019-04-19 06:03:23 +02:00 committed by GitHub
commit 37f835cd18
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 39 additions and 19 deletions

View file

@ -4685,6 +4685,14 @@ impl<'a> LoweringContext<'a> {
Symbol::intern("try_trait") Symbol::intern("try_trait")
].into()), ].into()),
); );
let try_span = self.sess.source_map().end_point(e.span);
let try_span = self.mark_span_with_reason(
CompilerDesugaringKind::QuestionMark,
try_span,
Some(vec![
Symbol::intern("try_trait")
].into()),
);
// `Try::into_result(<expr>)` // `Try::into_result(<expr>)`
let discr = { let discr = {
@ -4729,14 +4737,14 @@ impl<'a> LoweringContext<'a> {
// return Try::from_error(From::from(err)),` // return Try::from_error(From::from(err)),`
let err_arm = { let err_arm = {
let err_ident = self.str_to_ident("err"); let err_ident = self.str_to_ident("err");
let (err_local, err_local_nid) = self.pat_ident(e.span, err_ident); let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident);
let from_expr = { let from_expr = {
let path = &["convert", "From", "from"]; let path = &["convert", "From", "from"];
let from = P(self.expr_std_path( let from = P(self.expr_std_path(
e.span, path, None, ThinVec::new())); try_span, path, None, ThinVec::new()));
let err_expr = self.expr_ident(e.span, err_ident, err_local_nid); let err_expr = self.expr_ident(try_span, err_ident, err_local_nid);
self.expr_call(e.span, from, hir_vec![err_expr]) self.expr_call(try_span, from, hir_vec![err_expr])
}; };
let from_err_expr = let from_err_expr =
self.wrap_in_try_constructor("from_error", from_expr, unstable_span); self.wrap_in_try_constructor("from_error", from_expr, unstable_span);
@ -4745,7 +4753,7 @@ impl<'a> LoweringContext<'a> {
let ret_expr = if let Some(catch_node) = catch_scope { let ret_expr = if let Some(catch_node) = catch_scope {
let target_id = Ok(self.lower_node_id(catch_node).hir_id); let target_id = Ok(self.lower_node_id(catch_node).hir_id);
P(self.expr( P(self.expr(
e.span, try_span,
hir::ExprKind::Break( hir::ExprKind::Break(
hir::Destination { hir::Destination {
label: None, label: None,
@ -4756,10 +4764,10 @@ impl<'a> LoweringContext<'a> {
thin_attrs, thin_attrs,
)) ))
} else { } else {
P(self.expr(e.span, hir::ExprKind::Ret(Some(from_err_expr)), thin_attrs)) P(self.expr(try_span, hir::ExprKind::Ret(Some(from_err_expr)), thin_attrs))
}; };
let err_pat = self.pat_err(e.span, err_local); let err_pat = self.pat_err(try_span, err_local);
self.arm(hir_vec![err_pat], ret_expr) self.arm(hir_vec![err_pat], ret_expr)
}; };

View file

@ -638,6 +638,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
let OnUnimplementedNote { message, label, note } let OnUnimplementedNote { message, label, note }
= self.on_unimplemented_note(trait_ref, obligation); = self.on_unimplemented_note(trait_ref, obligation);
let have_alt_message = message.is_some() || label.is_some(); let have_alt_message = message.is_some() || label.is_some();
let is_try = self.tcx.sess.source_map().span_to_snippet(span)
.map(|s| &s == "?")
.unwrap_or(false);
let is_from = format!("{}", trait_ref).starts_with("std::convert::From<");
let message = if is_try && is_from {
Some(format!(
"`?` couldn't convert the error to `{}`",
trait_ref.self_ty(),
))
} else {
message
};
let mut err = struct_span_err!( let mut err = struct_span_err!(
self.tcx.sess, self.tcx.sess,

View file

@ -1,8 +1,8 @@
error[E0277]: the trait bound `(): std::convert::From<{integer}>` is not satisfied error[E0277]: `?` couldn't convert the error to `()`
--> $DIR/issue-32709.rs:4:5 --> $DIR/issue-32709.rs:4:11
| |
LL | Err(5)?; LL | Err(5)?;
| ^^^^^^^ the trait `std::convert::From<{integer}>` is not implemented for `()` | ^ the trait `std::convert::From<{integer}>` is not implemented for `()`
| |
= note: required by `std::convert::From::from` = note: required by `std::convert::From::from`

View file

@ -4,7 +4,7 @@
pub fn main() { pub fn main() {
let res: Result<u32, i32> = try { let res: Result<u32, i32> = try {
Err("")?; //~ ERROR the trait bound `i32: std::convert::From<&str>` is not satisfied Err("")?; //~ ERROR `?` couldn't convert the error
5 5
}; };

View file

@ -1,8 +1,8 @@
error[E0277]: the trait bound `i32: std::convert::From<&str>` is not satisfied error[E0277]: `?` couldn't convert the error to `i32`
--> $DIR/try-block-bad-type.rs:7:9 --> $DIR/try-block-bad-type.rs:7:16
| |
LL | Err("")?; LL | Err("")?;
| ^^^^^^^^ the trait `std::convert::From<&str>` is not implemented for `i32` | ^ the trait `std::convert::From<&str>` is not implemented for `i32`
| |
= help: the following implementations were found: = help: the following implementations were found:
<i32 as std::convert::From<bool>> <i32 as std::convert::From<bool>>

View file

@ -4,12 +4,12 @@ fn main() {}
fn foo() -> Result<u32, ()> { fn foo() -> Result<u32, ()> {
let x: Option<u32> = None; let x: Option<u32> = None;
x?; //~ the trait bound x?; //~ ERROR `?` couldn't convert the error
Ok(22) Ok(22)
} }
fn bar() -> u32 { fn bar() -> u32 {
let x: Option<u32> = None; let x: Option<u32> = None;
x?; //~ the `?` operator x?; //~ ERROR the `?` operator
22 22
} }

View file

@ -1,8 +1,8 @@
error[E0277]: the trait bound `(): std::convert::From<std::option::NoneError>` is not satisfied error[E0277]: `?` couldn't convert the error to `()`
--> $DIR/try-on-option.rs:7:5 --> $DIR/try-on-option.rs:7:6
| |
LL | x?; LL | x?;
| ^^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()` | ^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()`
| |
= note: required by `std::convert::From::from` = note: required by `std::convert::From::from`