From e5b278b702afc0fa26eda0517fd6907712790b5a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 5 Dec 2022 01:42:22 +0000 Subject: [PATCH 1/3] Deduplicate check_expr in builtin calls with error --- compiler/rustc_hir_typeck/src/callee.rs | 10 ++++- .../suggestions/fn-to-method-deeply-nested.rs | 13 +++++++ .../fn-to-method-deeply-nested.stderr | 39 +++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/suggestions/fn-to-method-deeply-nested.rs create mode 100644 src/test/ui/suggestions/fn-to-method-deeply-nested.stderr diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 4ec71a78a0031..c543527791379 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -399,6 +399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::FnPtr(sig) => (sig, None), _ => { + let mut skip_first_expr = false; if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &callee_expr.kind && let [segment] = path.segments && let Some(mut diag) = self @@ -421,11 +422,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return ty; } else { diag.emit(); + skip_first_expr = true; } } let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs); + for arg in arg_exprs.iter().skip(skip_first_expr as usize) { + self.check_expr(arg); + } + return self.tcx.ty_error_with_guaranteed(err); } }; @@ -486,7 +492,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Expectation<'tcx>, ) -> Option> { if let [callee_expr, rest @ ..] = arg_exprs { - let callee_ty = self.check_expr(callee_expr); + // This may happen recursively -- if so, avoid repeatedly checking the expr. + let callee_ty = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr); + let callee_ty = callee_ty.unwrap_or_else(|| self.check_expr(callee_expr)); // First, do a probe with `IsSuggestion(true)` to avoid emitting // any strange errors. If it's successful, then we'll do a true // method lookup. diff --git a/src/test/ui/suggestions/fn-to-method-deeply-nested.rs b/src/test/ui/suggestions/fn-to-method-deeply-nested.rs new file mode 100644 index 0000000000000..58ee3d6409a7e --- /dev/null +++ b/src/test/ui/suggestions/fn-to-method-deeply-nested.rs @@ -0,0 +1,13 @@ +fn main() -> Result<(), ()> { + a(b(c(d(e( + //~^ ERROR cannot find function `a` in this scope + //~| ERROR cannot find function `b` in this scope + //~| ERROR cannot find function `c` in this scope + //~| ERROR cannot find function `d` in this scope + //~| ERROR cannot find function `e` in this scope + z???????????????????????????????????????????????????????????????????????????????????????? + ????????????????????????????????????????????????????????????????????????????????????????? + ?????????????????????????????????????????????????????????????????? + //~^^^ ERROR cannot find value `z` in this scope + ))))) +} diff --git a/src/test/ui/suggestions/fn-to-method-deeply-nested.stderr b/src/test/ui/suggestions/fn-to-method-deeply-nested.stderr new file mode 100644 index 0000000000000..ce813ea7abae8 --- /dev/null +++ b/src/test/ui/suggestions/fn-to-method-deeply-nested.stderr @@ -0,0 +1,39 @@ +error[E0425]: cannot find value `z` in this scope + --> $DIR/fn-to-method-deeply-nested.rs:8:9 + | +LL | z???????????????????????????????????????????????????????????????????????????????????????? + | ^ not found in this scope + +error[E0425]: cannot find function `e` in this scope + --> $DIR/fn-to-method-deeply-nested.rs:2:13 + | +LL | a(b(c(d(e( + | ^ not found in this scope + +error[E0425]: cannot find function `d` in this scope + --> $DIR/fn-to-method-deeply-nested.rs:2:11 + | +LL | a(b(c(d(e( + | ^ not found in this scope + +error[E0425]: cannot find function `c` in this scope + --> $DIR/fn-to-method-deeply-nested.rs:2:9 + | +LL | a(b(c(d(e( + | ^ not found in this scope + +error[E0425]: cannot find function `b` in this scope + --> $DIR/fn-to-method-deeply-nested.rs:2:7 + | +LL | a(b(c(d(e( + | ^ not found in this scope + +error[E0425]: cannot find function `a` in this scope + --> $DIR/fn-to-method-deeply-nested.rs:2:5 + | +LL | a(b(c(d(e( + | ^ not found in this scope + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0425`. From 81cde69a2ff7ef24de9e28917936cc60c3482127 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 22 Dec 2022 18:17:22 +0000 Subject: [PATCH 2/3] Eagerly evaluate args --- compiler/rustc_hir_typeck/src/callee.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index c543527791379..af14ee08a9981 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -399,7 +399,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::FnPtr(sig) => (sig, None), _ => { - let mut skip_first_expr = false; + for arg in arg_exprs { + self.check_expr(arg); + } + if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &callee_expr.kind && let [segment] = path.segments && let Some(mut diag) = self @@ -422,16 +425,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return ty; } else { diag.emit(); - skip_first_expr = true; } } let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs); - for arg in arg_exprs.iter().skip(skip_first_expr as usize) { - self.check_expr(arg); - } - return self.tcx.ty_error_with_guaranteed(err); } }; @@ -492,9 +490,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Expectation<'tcx>, ) -> Option> { if let [callee_expr, rest @ ..] = arg_exprs { - // This may happen recursively -- if so, avoid repeatedly checking the expr. - let callee_ty = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr); - let callee_ty = callee_ty.unwrap_or_else(|| self.check_expr(callee_expr)); + let callee_ty = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)?; + // First, do a probe with `IsSuggestion(true)` to avoid emitting // any strange errors. If it's successful, then we'll do a true // method lookup. From 69abe4458e9c2f348933e8ecf939e9b38ff79625 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 22 Dec 2022 18:36:46 +0000 Subject: [PATCH 3/3] Add tests --- src/test/ui/typeck/check-args-on-fn-err-2.rs | 5 ++++ .../ui/typeck/check-args-on-fn-err-2.stderr | 23 +++++++++++++++++++ src/test/ui/typeck/check-args-on-fn-err.rs | 6 +++++ .../ui/typeck/check-args-on-fn-err.stderr | 9 ++++++++ 4 files changed, 43 insertions(+) create mode 100644 src/test/ui/typeck/check-args-on-fn-err-2.rs create mode 100644 src/test/ui/typeck/check-args-on-fn-err-2.stderr create mode 100644 src/test/ui/typeck/check-args-on-fn-err.rs create mode 100644 src/test/ui/typeck/check-args-on-fn-err.stderr diff --git a/src/test/ui/typeck/check-args-on-fn-err-2.rs b/src/test/ui/typeck/check-args-on-fn-err-2.rs new file mode 100644 index 0000000000000..af57dbe33177d --- /dev/null +++ b/src/test/ui/typeck/check-args-on-fn-err-2.rs @@ -0,0 +1,5 @@ +fn main() { + a((), 1i32 == 2u32); + //~^ ERROR cannot find function `a` in this scope + //~| ERROR mismatched types +} diff --git a/src/test/ui/typeck/check-args-on-fn-err-2.stderr b/src/test/ui/typeck/check-args-on-fn-err-2.stderr new file mode 100644 index 0000000000000..301bb88dbacf6 --- /dev/null +++ b/src/test/ui/typeck/check-args-on-fn-err-2.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/check-args-on-fn-err-2.rs:2:19 + | +LL | a((), 1i32 == 2u32); + | ---- ^^^^ expected `i32`, found `u32` + | | + | expected because this is `i32` + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | a((), 1i32 == 2i32); + | ~~~ + +error[E0425]: cannot find function `a` in this scope + --> $DIR/check-args-on-fn-err-2.rs:2:5 + | +LL | a((), 1i32 == 2u32); + | ^ not found in this scope + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/typeck/check-args-on-fn-err.rs b/src/test/ui/typeck/check-args-on-fn-err.rs new file mode 100644 index 0000000000000..04b98ddd95295 --- /dev/null +++ b/src/test/ui/typeck/check-args-on-fn-err.rs @@ -0,0 +1,6 @@ +fn main() { + unknown(1, |glyf| { + //~^ ERROR: cannot find function `unknown` in this scope + let actual = glyf; + }); +} diff --git a/src/test/ui/typeck/check-args-on-fn-err.stderr b/src/test/ui/typeck/check-args-on-fn-err.stderr new file mode 100644 index 0000000000000..864d33e0e93bb --- /dev/null +++ b/src/test/ui/typeck/check-args-on-fn-err.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `unknown` in this scope + --> $DIR/check-args-on-fn-err.rs:2:5 + | +LL | unknown(1, |glyf| { + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`.