Skip to content

Commit c6ff90b

Browse files
committed
Auto merge of rust-lang#98785 - compiler-errors:no-check-expr-in-check-compatible, r=estebank
Do not call `check_expr` in `check_compatible`, since it has side-effects Fixes a weird suggestion in rust-lang#98784 found later: Fixes rust-lang#98894 Fixes rust-lang#98897
2 parents 29554c0 + 6858fbc commit c6ff90b

File tree

4 files changed

+24
-45
lines changed

4 files changed

+24
-45
lines changed

Diff for: compiler/rustc_typeck/src/check/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
271271
}
272272

273273
#[instrument(skip(self, expr), level = "debug")]
274-
pub(super) fn check_expr_kind(
274+
fn check_expr_kind(
275275
&self,
276276
expr: &'tcx hir::Expr<'tcx>,
277277
expected: Expectation<'tcx>,

Diff for: compiler/rustc_typeck/src/check/fn_ctxt/checks.rs

+18-26
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
483483
self.set_tainted_by_errors();
484484
let tcx = self.tcx;
485485

486+
// Precompute the provided types and spans, since that's all we typically need for below
487+
let provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> = provided_args
488+
.iter()
489+
.map(|expr| {
490+
let ty = self
491+
.typeck_results
492+
.borrow()
493+
.expr_ty_adjusted_opt(*expr)
494+
.unwrap_or_else(|| tcx.ty_error());
495+
(self.resolve_vars_if_possible(ty), expr.span)
496+
})
497+
.collect();
498+
486499
// A "softer" version of the `demand_compatible`, which checks types without persisting them,
487500
// and treats error types differently
488501
// This will allow us to "probe" for other argument orders that would likely have been correct
@@ -499,31 +512,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
499512
return Compatibility::Incompatible(None);
500513
}
501514

502-
let provided_arg: &hir::Expr<'tcx> = &provided_args[provided_idx];
503-
let expectation = Expectation::rvalue_hint(self, expected_input_ty);
504-
// FIXME: check that this is safe; I don't believe this commits any of the obligations, but I can't be sure.
505-
//
506-
// I had another method of "soft" type checking before,
507-
// but it was failing to find the type of some expressions (like "")
508-
// so I prodded this method and made it pub(super) so I could call it, and it seems to work well.
509-
let checked_ty = self.check_expr_kind(provided_arg, expectation);
515+
let (arg_ty, arg_span) = provided_arg_tys[provided_idx];
510516

517+
let expectation = Expectation::rvalue_hint(self, expected_input_ty);
511518
let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
512-
let can_coerce = self.can_coerce(checked_ty, coerced_ty);
519+
let can_coerce = self.can_coerce(arg_ty, coerced_ty);
513520
if !can_coerce {
514521
return Compatibility::Incompatible(None);
515522
}
516523

517524
// Using probe here, since we don't want this subtyping to affect inference.
518525
let subtyping_error = self.probe(|_| {
519-
self.at(&self.misc(provided_arg.span), self.param_env)
520-
.sup(formal_input_ty, coerced_ty)
521-
.err()
526+
self.at(&self.misc(arg_span), self.param_env).sup(formal_input_ty, coerced_ty).err()
522527
});
523528

524529
// Same as above: if either the coerce type or the checked type is an error type,
525530
// consider them *not* compatible.
526-
let references_error = (coerced_ty, checked_ty).references_error();
531+
let references_error = (coerced_ty, arg_ty).references_error();
527532
match (references_error, subtyping_error) {
528533
(false, None) => Compatibility::Compatible,
529534
(_, subtyping_error) => Compatibility::Incompatible(subtyping_error),
@@ -542,19 +547,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
542547
ArgMatrix::new(provided_args.len(), formal_and_expected_inputs.len(), check_compatible)
543548
.find_errors();
544549

545-
// Precompute the provided types and spans, since that's all we typically need for below
546-
let provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> = provided_args
547-
.iter()
548-
.map(|expr| {
549-
let ty = self
550-
.typeck_results
551-
.borrow()
552-
.expr_ty_adjusted_opt(*expr)
553-
.unwrap_or_else(|| tcx.ty_error());
554-
(self.resolve_vars_if_possible(ty), expr.span)
555-
})
556-
.collect();
557-
558550
// First, check if we just need to wrap some arguments in a tuple.
559551
if let Some((mismatch_idx, terr)) =
560552
compatibility_diagonal.iter().enumerate().find_map(|(i, c)| {

Diff for: src/test/ui/issues/issue-3044.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
fn main() {
22
let needlesArr: Vec<char> = vec!['a', 'f'];
33
needlesArr.iter().fold(|x, y| {
4+
//~^ ERROR this function takes 2 arguments but 1 argument was supplied
45
});
5-
//~^^ ERROR mismatched types
6-
//~| ERROR this function takes 2 arguments but 1 argument was supplied
76
}

Diff for: src/test/ui/issues/issue-3044.stderr

+4-16
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,9 @@
1-
error[E0308]: mismatched types
2-
--> $DIR/issue-3044.rs:3:35
3-
|
4-
LL | needlesArr.iter().fold(|x, y| {
5-
| ____________________________------_^
6-
| | |
7-
| | the expected closure
8-
LL | | });
9-
| |_____^ expected closure, found `()`
10-
|
11-
= note: expected closure `[closure@$DIR/issue-3044.rs:3:28: 3:34]`
12-
found unit type `()`
13-
141
error[E0061]: this function takes 2 arguments but 1 argument was supplied
152
--> $DIR/issue-3044.rs:3:23
163
|
174
LL | needlesArr.iter().fold(|x, y| {
185
| _______________________^^^^-
6+
LL | |
197
LL | | });
208
| |______- an argument is missing
219
|
@@ -27,10 +15,10 @@ LL | fn fold<B, F>(mut self, init: B, mut f: F) -> B
2715
help: provide the argument
2816
|
2917
LL ~ needlesArr.iter().fold(|x, y| {
18+
LL +
3019
LL ~ }, /* value */);
3120
|
3221

33-
error: aborting due to 2 previous errors
22+
error: aborting due to previous error
3423

35-
Some errors have detailed explanations: E0061, E0308.
36-
For more information about an error, try `rustc --explain E0061`.
24+
For more information about this error, try `rustc --explain E0061`.

0 commit comments

Comments
 (0)