Skip to content

Commit 5212ac9

Browse files
Make check for overlapping closure span more accurate
1 parent d2f54b1 commit 5212ac9

File tree

6 files changed

+46
-56
lines changed

6 files changed

+46
-56
lines changed

compiler/rustc_typeck/src/check/fn_ctxt/checks.rs

+34-21
Original file line numberDiff line numberDiff line change
@@ -1669,6 +1669,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16691669
) -> bool {
16701670
let (traits::ExprItemObligation(def_id, hir_id, idx) | traits::ExprBindingObligation(def_id, _, hir_id, idx))
16711671
= *error.obligation.cause.code().peel_derives() else { return false; };
1672+
let hir = self.tcx.hir();
1673+
let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; };
16721674

16731675
// Skip over mentioning async lang item
16741676
if Some(def_id) == self.tcx.lang_items().from_generator_fn()
@@ -1677,15 +1679,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16771679
{
16781680
return false;
16791681
}
1680-
// Skip over closure arg mismatch, which has a better heuristic
1681-
// to determine what span to point at.
1682-
if let traits::FulfillmentErrorCode::CodeSelectionError(
1683-
traits::SelectionError::OutputTypeParameterMismatch(_, expected, _),
1684-
) = error.code
1685-
&& let ty::Closure(..) | ty::Generator(..) = expected.skip_binder().self_ty().kind()
1686-
{
1687-
return false;
1688-
}
16891682

16901683
let Some(unsubstituted_pred) =
16911684
self.tcx.predicates_of(def_id).instantiate_identity(self.tcx).predicates.into_iter().nth(idx)
@@ -1741,16 +1734,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17411734
self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate);
17421735
}
17431736

1744-
let hir = self.tcx.hir();
1745-
match hir.get(hir_id) {
1746-
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Path(qpath), hir_id, .. }) => {
1737+
if self.closure_span_overlaps_error(error, expr.span) {
1738+
return false;
1739+
}
1740+
1741+
match &expr.kind {
1742+
hir::ExprKind::Path(qpath) => {
17471743
if let hir::Node::Expr(hir::Expr {
17481744
kind: hir::ExprKind::Call(callee, args),
17491745
hir_id: call_hir_id,
1746+
span: call_span,
17501747
..
1751-
}) = hir.get(hir.get_parent_node(*hir_id))
1752-
&& callee.hir_id == *hir_id
1748+
}) = hir.get(hir.get_parent_node(expr.hir_id))
1749+
&& callee.hir_id == expr.hir_id
17531750
{
1751+
if self.closure_span_overlaps_error(error, *call_span) {
1752+
return false;
1753+
}
1754+
17541755
for param in
17551756
[param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
17561757
.into_iter()
@@ -1780,10 +1781,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17801781
}
17811782
}
17821783
}
1783-
hir::Node::Expr(hir::Expr {
1784-
kind: hir::ExprKind::MethodCall(segment, args, ..),
1785-
..
1786-
}) => {
1784+
hir::ExprKind::MethodCall(segment, args, ..) => {
17871785
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
17881786
.into_iter()
17891787
.flatten()
@@ -1805,9 +1803,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18051803
return true;
18061804
}
18071805
}
1808-
hir::Node::Expr(hir::Expr {
1809-
kind: hir::ExprKind::Struct(qpath, fields, ..), ..
1810-
}) => {
1806+
hir::ExprKind::Struct(qpath, fields, ..) => {
18111807
if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) =
18121808
self.typeck_results.borrow().qpath_res(qpath, hir_id)
18131809
{
@@ -1839,6 +1835,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18391835
false
18401836
}
18411837

1838+
fn closure_span_overlaps_error(
1839+
&self,
1840+
error: &traits::FulfillmentError<'tcx>,
1841+
span: Span,
1842+
) -> bool {
1843+
if let traits::FulfillmentErrorCode::CodeSelectionError(
1844+
traits::SelectionError::OutputTypeParameterMismatch(_, expected, _),
1845+
) = error.code
1846+
&& let ty::Closure(def_id, _) | ty::Generator(def_id, ..) = expected.skip_binder().self_ty().kind()
1847+
&& span.overlaps(self.tcx.def_span(*def_id))
1848+
{
1849+
true
1850+
} else {
1851+
false
1852+
}
1853+
}
1854+
18421855
fn point_at_arg_if_possible(
18431856
&self,
18441857
error: &mut traits::FulfillmentError<'tcx>,

src/test/ui/issues/issue-69683.stderr

+1-27
Original file line numberDiff line numberDiff line change
@@ -37,33 +37,7 @@ help: try using a fully qualified path to specify the expected types
3737
LL | <u16 as Foo<I>>::foo(0u16, b);
3838
| +++++++++++++++++++++ ~
3939

40-
error[E0283]: type annotations needed
41-
--> $DIR/issue-69683.rs:30:10
42-
|
43-
LL | 0u16.foo(b);
44-
| ---- ^^^
45-
| |
46-
| type must be known at this point
47-
|
48-
note: multiple `impl`s satisfying `u8: Element<_>` found
49-
--> $DIR/issue-69683.rs:5:1
50-
|
51-
LL | impl<T> Element<()> for T {
52-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
53-
...
54-
LL | impl<T: Element<S>, S> Element<[S; 3]> for T {
55-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
56-
note: required for `u16` to implement `Foo<_>`
57-
--> $DIR/issue-69683.rs:20:9
58-
|
59-
LL | impl<I> Foo<I> for u16
60-
| ^^^^^^ ^^^
61-
help: try using a fully qualified path to specify the expected types
62-
|
63-
LL | <u16 as Foo<I>>::foo(0u16, b);
64-
| +++++++++++++++++++++ ~
65-
66-
error: aborting due to 3 previous errors
40+
error: aborting due to 2 previous errors
6741

6842
Some errors have detailed explanations: E0283, E0284.
6943
For more information about an error, try `rustc --explain E0283`.

src/test/ui/mismatched_types/closure-arg-count.stderr

+4-2
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,14 @@ LL | F: FnMut(Self::Item) -> B,
133133
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
134134

135135
error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
136-
--> $DIR/closure-arg-count.rs:27:53
136+
--> $DIR/closure-arg-count.rs:27:57
137137
|
138138
LL | let bar = |i, x, y| i;
139139
| --------- takes 3 distinct arguments
140140
LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
141-
| ^^^ expected closure that takes a single 2-tuple as argument
141+
| --- ^^^ expected closure that takes a single 2-tuple as argument
142+
| |
143+
| required by a bound introduced by this call
142144
|
143145
note: required by a bound in `map`
144146
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL

src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs

+1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ pub fn main() {
1717
//~^ ERROR type mismatch
1818
//~| NOTE expected due to this
1919
//~| NOTE expected closure signature `fn(isize, _) -> _`
20+
//~| NOTE required by a bound introduced by this call
2021
println!("{}", z);
2122
}

src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
error[E0631]: type mismatch in closure arguments
2-
--> $DIR/unboxed-closures-vtable-mismatch.rs:16:13
2+
--> $DIR/unboxed-closures-vtable-mismatch.rs:16:24
33
|
44
LL | let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
55
| ----------------------------- found signature defined here
66
LL |
77
LL | let z = call_it(3, f);
8-
| ^^^^^^^ expected due to this
8+
| ------- ^ expected due to this
9+
| |
10+
| required by a bound introduced by this call
911
|
1012
= note: expected closure signature `fn(isize, _) -> _`
1113
found closure signature `fn(usize, _) -> _`

src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
error[E0308]: mismatched types
2-
--> $DIR/non-tupled-arg-mismatch.rs:6:7
2+
--> $DIR/non-tupled-arg-mismatch.rs:6:5
33
|
44
LL | a(|_: usize| {});
5-
| - ^^^^^^^^^^^^^ types differ
6-
| |
7-
| required by a bound introduced by this call
5+
| ^ types differ
86
|
97
= note: expected trait `Fn<usize>`
108
found trait `Fn<(usize,)>`

0 commit comments

Comments
 (0)