Skip to content

Commit 9bfdbd9

Browse files
committed
Change signature style and accept closure/closure type err
* 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
1 parent 541cfb4 commit 9bfdbd9

File tree

5 files changed

+98
-31
lines changed

5 files changed

+98
-31
lines changed

src/librustc/infer/error_reporting/mod.rs

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,28 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
588588
s.push_normal(format!("{}", tnm.ty));
589589
}
590590

591+
fn push_closure<'tcx>(capture: &hir::CaptureClause,
592+
fn_decl: &hir::FnDecl,
593+
s: &mut DiagnosticStyledString) {
594+
let args = fn_decl.inputs.iter()
595+
.map(|arg| format!("{}", arg))
596+
.collect::<Vec<String>>()
597+
.join(", ");
598+
s.push_highlighted(
599+
format!("{}|{}| -> {}",
600+
if capture == &hir::CaptureByValue {
601+
"move "
602+
} else {
603+
""
604+
},
605+
args,
606+
if let hir::Return(ref r_ty) = fn_decl.output {
607+
format!("{}", r_ty)
608+
} else {
609+
"_".to_string()
610+
}));
611+
}
612+
591613
match (&t1.sty, &t2.sty) {
592614
(&ty::TyAdt(def1, sub1), &ty::TyAdt(def2, sub2)) => {
593615
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
@@ -728,29 +750,41 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
728750
values
729751
}
730752
// When comparing against a closure, print its signature without location
753+
(&ty::TyClosure(did1, _), &ty::TyClosure(did2, _)) => {
754+
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
755+
let mut success = false;
756+
if let Some(node_id) = self.tcx.hir.as_local_node_id(did1) {
757+
if let Some(hir::map::NodeExpr(expr)) = self.tcx.hir.find(node_id) {
758+
if let hir::ExprClosure(capture, ref fn_decl, _, _, _) = expr.node {
759+
push_closure(&capture, fn_decl, &mut values.0);
760+
success = true;
761+
}
762+
}
763+
}
764+
if !success { // fallback
765+
values.0.push_highlighted(format!("{}", t1));
766+
}
767+
success = false;
768+
if let Some(node_id) = self.tcx.hir.as_local_node_id(did2) {
769+
if let Some(hir::map::NodeExpr(expr)) = self.tcx.hir.find(node_id) {
770+
if let hir::ExprClosure(capture, ref fn_decl, _, _, _) = expr.node {
771+
push_closure(&capture, fn_decl, &mut values.1);
772+
success = true;
773+
}
774+
}
775+
}
776+
if !success { // fallback
777+
values.1.push_highlighted(format!("{}", t2));
778+
}
779+
values
780+
}
731781
(_, &ty::TyClosure(did, _)) => {
732782
let mut values = (DiagnosticStyledString::highlighted(format!("{}", t1)),
733783
DiagnosticStyledString::new());
734784
if let Some(node_id) = self.tcx.hir.as_local_node_id(did) {
735785
if let Some(hir::map::NodeExpr(expr)) = self.tcx.hir.find(node_id) {
736786
if let hir::ExprClosure(capture, ref fn_decl, _, _, _) = expr.node {
737-
let args = fn_decl.inputs.iter()
738-
.map(|arg| format!("{}", arg))
739-
.collect::<Vec<String>>()
740-
.join(", ");
741-
values.1.push_highlighted(
742-
format!("{}fn({}) -> {}",
743-
if capture == hir::CaptureByValue {
744-
"move "
745-
} else {
746-
""
747-
},
748-
args,
749-
if let hir::Return(ref r_ty) = fn_decl.output {
750-
format!("{}", r_ty)
751-
} else {
752-
"_".to_string()
753-
}));
787+
push_closure(&capture, fn_decl, &mut values.1);
754788
return values;
755789
}
756790
}
@@ -759,6 +793,21 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
759793
values.1.push_highlighted(format!("{}", t2));
760794
values
761795
}
796+
(&ty::TyClosure(did, _), _) => {
797+
let mut values = (DiagnosticStyledString::new(),
798+
DiagnosticStyledString::highlighted(format!("{}", t2)));
799+
if let Some(node_id) = self.tcx.hir.as_local_node_id(did) {
800+
if let Some(hir::map::NodeExpr(expr)) = self.tcx.hir.find(node_id) {
801+
if let hir::ExprClosure(capture, ref fn_decl, _, _, _) = expr.node {
802+
push_closure(&capture, fn_decl, &mut values.0);
803+
return values;
804+
}
805+
}
806+
}
807+
// fallback
808+
values.0.push_highlighted(format!("{}", t1));
809+
values
810+
}
762811

763812
_ => {
764813
if t1 == t2 {

src/librustc/ty/error.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,22 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
246246
ty::TyError => "type error".to_string(),
247247
}
248248
}
249+
250+
pub fn span(&self, tcx: &TyCtxt<'a, 'gcx, 'lcx>) -> Option<Span> {
251+
match self.sty {
252+
ty::TyClosure(def, _) => {
253+
if let Some(node_id) = tcx.hir.as_local_node_id(def) {
254+
if let Some(hir::map::NodeExpr(expr)) = tcx.hir.find(node_id) {
255+
if let hir::ExprClosure(_, _, _, sp, _) = expr.node {
256+
return Some(sp);
257+
}
258+
}
259+
}
260+
None
261+
}
262+
_ => None,
263+
}
264+
}
249265
}
250266

251267
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
@@ -260,10 +276,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
260276
let expected_str = values.expected.sort_string(self);
261277
let found_str = values.found.sort_string(self);
262278
if expected_str == found_str && expected_str == "closure" {
263-
db.span_note(sp,
264-
"no two closures, even if identical, have the same type");
265-
db.span_help(sp,
266-
"consider boxing your closure and/or using it as a trait object");
279+
db.note("no two closures, even if identical, have the same type");
280+
if let Some(sp) = values.expected.span(&self) {
281+
db.span_label(sp, "this closure was expected");
282+
}
283+
db.help("consider boxing your closure and/or using it as a trait object");
267284
}
268285
},
269286
TyParamDefaultMismatch(values) => {

src/test/compile-fail/issue-24036.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,29 @@
1010

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

2223
fn closure_from_match() {
2324
let x = match 1usize {
25+
//~^ ERROR match arms have incompatible types
26+
//~| NOTE no two closures, even if identical, have the same type
27+
//~| HELP consider boxing your closure and/or using it as a trait object
28+
//~| NOTE expected closure, found a different closure
29+
//~| NOTE expected type `|_| -> _` (closure)
2430
1 => |c| c + 1,
31+
//~^ NOTE this closure was expected
2532
2 => |c| c - 1,
2633
//~^ NOTE match arm with an incompatible type
2734
_ => |c| c - 1
2835
};
29-
//~^^^^^^ ERROR match arms have incompatible types
30-
//~| NOTE no two closures, even if identical, have the same type
31-
//~| HELP consider boxing your closure and/or using it as a trait object
32-
//~| expected closure, found a different closure
33-
//~| expected type `[closure
34-
//~| found type `fn(_) -> _`
3536
}
3637

3738
fn main() { }

src/test/ui/block-result/issue-20862.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ error[E0308]: mismatched types
77
| ^^^^^^^^^ expected (), found closure
88
|
99
= note: expected type `()`
10-
found type `fn(_) -> _`
10+
found type `|_| -> _`
1111

1212
error[E0618]: expected function, found `()`
1313
--> $DIR/issue-20862.rs:17:13

src/test/ui/span/move-closure.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ error[E0308]: mismatched types
55
| ^^^^^^^^^^ expected (), found closure
66
|
77
= note: expected type `()`
8-
found type `move fn() -> _`
8+
found type `move || -> _`
99

1010
error: aborting due to previous error
1111

0 commit comments

Comments
 (0)