Skip to content

Commit

Permalink
Change signature style and accept closure/closure type err
Browse files Browse the repository at this point in the history
 * Accept type errors where the closure was expected and/or found
 * Change closure presentation to `move |args| -> _`
 * Closure type error help and note don't point at span anymore
 * Update tests
  • Loading branch information
estebank committed Dec 3, 2017
1 parent 541cfb4 commit 9bfdbd9
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 31 deletions.
83 changes: 66 additions & 17 deletions src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,28 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
s.push_normal(format!("{}", tnm.ty));
}

fn push_closure<'tcx>(capture: &hir::CaptureClause,
fn_decl: &hir::FnDecl,
s: &mut DiagnosticStyledString) {
let args = fn_decl.inputs.iter()
.map(|arg| format!("{}", arg))
.collect::<Vec<String>>()
.join(", ");
s.push_highlighted(
format!("{}|{}| -> {}",
if capture == &hir::CaptureByValue {
"move "
} else {
""
},
args,
if let hir::Return(ref r_ty) = fn_decl.output {
format!("{}", r_ty)
} else {
"_".to_string()
}));
}

match (&t1.sty, &t2.sty) {
(&ty::TyAdt(def1, sub1), &ty::TyAdt(def2, sub2)) => {
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
Expand Down Expand Up @@ -728,29 +750,41 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
values
}
// When comparing against a closure, print its signature without location
(&ty::TyClosure(did1, _), &ty::TyClosure(did2, _)) => {
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
let mut success = false;
if let Some(node_id) = self.tcx.hir.as_local_node_id(did1) {
if let Some(hir::map::NodeExpr(expr)) = self.tcx.hir.find(node_id) {
if let hir::ExprClosure(capture, ref fn_decl, _, _, _) = expr.node {
push_closure(&capture, fn_decl, &mut values.0);
success = true;
}
}
}
if !success { // fallback
values.0.push_highlighted(format!("{}", t1));
}
success = false;
if let Some(node_id) = self.tcx.hir.as_local_node_id(did2) {
if let Some(hir::map::NodeExpr(expr)) = self.tcx.hir.find(node_id) {
if let hir::ExprClosure(capture, ref fn_decl, _, _, _) = expr.node {
push_closure(&capture, fn_decl, &mut values.1);
success = true;
}
}
}
if !success { // fallback
values.1.push_highlighted(format!("{}", t2));
}
values
}
(_, &ty::TyClosure(did, _)) => {
let mut values = (DiagnosticStyledString::highlighted(format!("{}", t1)),
DiagnosticStyledString::new());
if let Some(node_id) = self.tcx.hir.as_local_node_id(did) {
if let Some(hir::map::NodeExpr(expr)) = self.tcx.hir.find(node_id) {
if let hir::ExprClosure(capture, ref fn_decl, _, _, _) = expr.node {
let args = fn_decl.inputs.iter()
.map(|arg| format!("{}", arg))
.collect::<Vec<String>>()
.join(", ");
values.1.push_highlighted(
format!("{}fn({}) -> {}",
if capture == hir::CaptureByValue {
"move "
} else {
""
},
args,
if let hir::Return(ref r_ty) = fn_decl.output {
format!("{}", r_ty)
} else {
"_".to_string()
}));
push_closure(&capture, fn_decl, &mut values.1);
return values;
}
}
Expand All @@ -759,6 +793,21 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
values.1.push_highlighted(format!("{}", t2));
values
}
(&ty::TyClosure(did, _), _) => {
let mut values = (DiagnosticStyledString::new(),
DiagnosticStyledString::highlighted(format!("{}", t2)));
if let Some(node_id) = self.tcx.hir.as_local_node_id(did) {
if let Some(hir::map::NodeExpr(expr)) = self.tcx.hir.find(node_id) {
if let hir::ExprClosure(capture, ref fn_decl, _, _, _) = expr.node {
push_closure(&capture, fn_decl, &mut values.0);
return values;
}
}
}
// fallback
values.0.push_highlighted(format!("{}", t1));
values
}

_ => {
if t1 == t2 {
Expand Down
25 changes: 21 additions & 4 deletions src/librustc/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,22 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
ty::TyError => "type error".to_string(),
}
}

pub fn span(&self, tcx: &TyCtxt<'a, 'gcx, 'lcx>) -> Option<Span> {
match self.sty {
ty::TyClosure(def, _) => {
if let Some(node_id) = tcx.hir.as_local_node_id(def) {
if let Some(hir::map::NodeExpr(expr)) = tcx.hir.find(node_id) {
if let hir::ExprClosure(_, _, _, sp, _) = expr.node {
return Some(sp);
}
}
}
None
}
_ => None,
}
}
}

impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
Expand All @@ -260,10 +276,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
let expected_str = values.expected.sort_string(self);
let found_str = values.found.sort_string(self);
if expected_str == found_str && expected_str == "closure" {
db.span_note(sp,
"no two closures, even if identical, have the same type");
db.span_help(sp,
"consider boxing your closure and/or using it as a trait object");
db.note("no two closures, even if identical, have the same type");
if let Some(sp) = values.expected.span(&self) {
db.span_label(sp, "this closure was expected");
}
db.help("consider boxing your closure and/or using it as a trait object");
}
},
TyParamDefaultMismatch(values) => {
Expand Down
17 changes: 9 additions & 8 deletions src/test/compile-fail/issue-24036.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,29 @@

fn closure_to_loc() {
let mut x = |c| c + 1;
//~^ NOTE this closure was expected
x = |c| c + 1;
//~^ ERROR mismatched types
//~| NOTE no two closures, even if identical, have the same type
//~| HELP consider boxing your closure and/or using it as a trait object
//~| expected closure, found a different closure
//~| expected type `[closure
//~| found type `fn(_) -> _`
//~| expected type `|_| -> _`
//~| found type `|_| -> _`
}

fn closure_from_match() {
let x = match 1usize {
//~^ ERROR match arms have incompatible types
//~| NOTE no two closures, even if identical, have the same type
//~| HELP consider boxing your closure and/or using it as a trait object
//~| NOTE expected closure, found a different closure
//~| NOTE expected type `|_| -> _` (closure)
1 => |c| c + 1,
//~^ NOTE this closure was expected
2 => |c| c - 1,
//~^ NOTE match arm with an incompatible type
_ => |c| c - 1
};
//~^^^^^^ ERROR match arms have incompatible types
//~| NOTE no two closures, even if identical, have the same type
//~| HELP consider boxing your closure and/or using it as a trait object
//~| expected closure, found a different closure
//~| expected type `[closure
//~| found type `fn(_) -> _`
}

fn main() { }
2 changes: 1 addition & 1 deletion src/test/ui/block-result/issue-20862.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ error[E0308]: mismatched types
| ^^^^^^^^^ expected (), found closure
|
= note: expected type `()`
found type `fn(_) -> _`
found type `|_| -> _`

error[E0618]: expected function, found `()`
--> $DIR/issue-20862.rs:17:13
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/span/move-closure.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ error[E0308]: mismatched types
| ^^^^^^^^^^ expected (), found closure
|
= note: expected type `()`
found type `move fn() -> _`
found type `move || -> _`

error: aborting due to previous error

0 comments on commit 9bfdbd9

Please sign in to comment.