diff options
| author | Michael Goulet <michael@errs.io> | 2022-08-18 13:27:08 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2022-08-21 02:35:11 +0000 |
| commit | 5212ac9dac4c99714ca7379f7882109fb1f07405 (patch) | |
| tree | 9e3dfbb6d98fffb536621143361312a3961d8c36 | |
| parent | d2f54b1990c916c1af15124ce45dbdaa9758f7b2 (diff) | |
| download | rust-5212ac9dac4c99714ca7379f7882109fb1f07405.tar.gz rust-5212ac9dac4c99714ca7379f7882109fb1f07405.zip | |
Make check for overlapping closure span more accurate
6 files changed, 46 insertions, 56 deletions
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 41314644a81..3642b2ab03b 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -1669,6 +1669,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> bool { let (traits::ExprItemObligation(def_id, hir_id, idx) | traits::ExprBindingObligation(def_id, _, hir_id, idx)) = *error.obligation.cause.code().peel_derives() else { return false; }; + let hir = self.tcx.hir(); + let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; }; // Skip over mentioning async lang item if Some(def_id) == self.tcx.lang_items().from_generator_fn() @@ -1677,15 +1679,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { return false; } - // Skip over closure arg mismatch, which has a better heuristic - // to determine what span to point at. - if let traits::FulfillmentErrorCode::CodeSelectionError( - traits::SelectionError::OutputTypeParameterMismatch(_, expected, _), - ) = error.code - && let ty::Closure(..) | ty::Generator(..) = expected.skip_binder().self_ty().kind() - { - return false; - } let Some(unsubstituted_pred) = 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> { self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate); } - let hir = self.tcx.hir(); - match hir.get(hir_id) { - hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Path(qpath), hir_id, .. }) => { + if self.closure_span_overlaps_error(error, expr.span) { + return false; + } + + match &expr.kind { + hir::ExprKind::Path(qpath) => { if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Call(callee, args), hir_id: call_hir_id, + span: call_span, .. - }) = hir.get(hir.get_parent_node(*hir_id)) - && callee.hir_id == *hir_id + }) = hir.get(hir.get_parent_node(expr.hir_id)) + && callee.hir_id == expr.hir_id { + if self.closure_span_overlaps_error(error, *call_span) { + return false; + } + for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] .into_iter() @@ -1780,10 +1781,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::MethodCall(segment, args, ..), - .. - }) => { + hir::ExprKind::MethodCall(segment, args, ..) => { for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] .into_iter() .flatten() @@ -1805,9 +1803,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return true; } } - hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Struct(qpath, fields, ..), .. - }) => { + hir::ExprKind::Struct(qpath, fields, ..) => { if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) = self.typeck_results.borrow().qpath_res(qpath, hir_id) { @@ -1839,6 +1835,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } + fn closure_span_overlaps_error( + &self, + error: &traits::FulfillmentError<'tcx>, + span: Span, + ) -> bool { + if let traits::FulfillmentErrorCode::CodeSelectionError( + traits::SelectionError::OutputTypeParameterMismatch(_, expected, _), + ) = error.code + && let ty::Closure(def_id, _) | ty::Generator(def_id, ..) = expected.skip_binder().self_ty().kind() + && span.overlaps(self.tcx.def_span(*def_id)) + { + true + } else { + false + } + } + fn point_at_arg_if_possible( &self, error: &mut traits::FulfillmentError<'tcx>, diff --git a/src/test/ui/issues/issue-69683.stderr b/src/test/ui/issues/issue-69683.stderr index 248fb75b4c4..193de1a35cf 100644 --- a/src/test/ui/issues/issue-69683.stderr +++ b/src/test/ui/issues/issue-69683.stderr @@ -37,33 +37,7 @@ help: try using a fully qualified path to specify the expected types LL | <u16 as Foo<I>>::foo(0u16, b); | +++++++++++++++++++++ ~ -error[E0283]: type annotations needed - --> $DIR/issue-69683.rs:30:10 - | -LL | 0u16.foo(b); - | ---- ^^^ - | | - | type must be known at this point - | -note: multiple `impl`s satisfying `u8: Element<_>` found - --> $DIR/issue-69683.rs:5:1 - | -LL | impl<T> Element<()> for T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | impl<T: Element<S>, S> Element<[S; 3]> for T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: required for `u16` to implement `Foo<_>` - --> $DIR/issue-69683.rs:20:9 - | -LL | impl<I> Foo<I> for u16 - | ^^^^^^ ^^^ -help: try using a fully qualified path to specify the expected types - | -LL | <u16 as Foo<I>>::foo(0u16, b); - | +++++++++++++++++++++ ~ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0283, E0284. For more information about an error, try `rustc --explain E0283`. diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index a6ed22781e9..a02ec819838 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -133,12 +133,14 @@ LL | F: FnMut(Self::Item) -> B, | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map` error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments - --> $DIR/closure-arg-count.rs:27:53 + --> $DIR/closure-arg-count.rs:27:57 | LL | let bar = |i, x, y| i; | --------- takes 3 distinct arguments LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(bar); - | ^^^ expected closure that takes a single 2-tuple as argument + | --- ^^^ expected closure that takes a single 2-tuple as argument + | | + | required by a bound introduced by this call | note: required by a bound in `map` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs index 0d64ded215a..8dbe3472ea8 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs @@ -17,5 +17,6 @@ pub fn main() { //~^ ERROR type mismatch //~| NOTE expected due to this //~| NOTE expected closure signature `fn(isize, _) -> _` + //~| NOTE required by a bound introduced by this call println!("{}", z); } diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr index 0b0d9f10786..54b22006527 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr @@ -1,11 +1,13 @@ error[E0631]: type mismatch in closure arguments - --> $DIR/unboxed-closures-vtable-mismatch.rs:16:13 + --> $DIR/unboxed-closures-vtable-mismatch.rs:16:24 | LL | let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y }); | ----------------------------- found signature defined here LL | LL | let z = call_it(3, f); - | ^^^^^^^ expected due to this + | ------- ^ expected due to this + | | + | required by a bound introduced by this call | = note: expected closure signature `fn(isize, _) -> _` found closure signature `fn(usize, _) -> _` diff --git a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr index d8e9776bb00..9a24fb8c2be 100644 --- a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr +++ b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr @@ -1,10 +1,8 @@ error[E0308]: mismatched types - --> $DIR/non-tupled-arg-mismatch.rs:6:7 + --> $DIR/non-tupled-arg-mismatch.rs:6:5 | LL | a(|_: usize| {}); - | - ^^^^^^^^^^^^^ types differ - | | - | required by a bound introduced by this call + | ^ types differ | = note: expected trait `Fn<usize>` found trait `Fn<(usize,)>` |
