Skip to content

Commit 42ed69c

Browse files
authored
Rollup merge of #141236 - jagunter:issue-140823, r=compiler-errors
Resolved issue with mismatched types triggering ICE in certain scenarios ## Background The function `annotate_mut_binding_to_immutable_binding` called in `emit_coerce_suggestions` performs a type comparison between the `expected` and `found` types from `ExpectedFound` in the `TypeError`. This can fail if the `found` type contains a region variable that's been rolled back. ## What is being changed? This updates `annotate_mut_binding_to_immutable_binding` to use `expr_ty` and `expected` from the parent function instead of the types from the `TypeError`. This sidesteps the issue of using `found` from `TypeError` which may leak lingering inference region variables. This does change the diagnostic behavior to _only_ support cases where the expected outermost type is `&T`, but that seems to be the intended functionality. Also fixed the example in the `annotate_mut_binding_to_immutable_binding` rustdocs. r? rust-lang/types Fixes #140823
2 parents 7e3af74 + db1ac98 commit 42ed69c

File tree

4 files changed

+46
-15
lines changed

4 files changed

+46
-15
lines changed

compiler/rustc_hir_typeck/src/demand.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8484

8585
self.annotate_expected_due_to_let_ty(err, expr, error);
8686
self.annotate_loop_expected_due_to_inference(err, expr, error);
87-
if self.annotate_mut_binding_to_immutable_binding(err, expr, error) {
87+
if self.annotate_mut_binding_to_immutable_binding(err, expr, expr_ty, expected, error) {
8888
return;
8989
}
9090

@@ -799,17 +799,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
799799
/// Detect the following case
800800
///
801801
/// ```text
802-
/// fn change_object(mut a: &Ty) {
802+
/// fn change_object(mut b: &Ty) {
803803
/// let a = Ty::new();
804804
/// b = a;
805805
/// }
806806
/// ```
807807
///
808-
/// where the user likely meant to modify the value behind there reference, use `a` as an out
808+
/// where the user likely meant to modify the value behind there reference, use `b` as an out
809809
/// parameter, instead of mutating the local binding. When encountering this we suggest:
810810
///
811811
/// ```text
812-
/// fn change_object(a: &'_ mut Ty) {
812+
/// fn change_object(b: &'_ mut Ty) {
813813
/// let a = Ty::new();
814814
/// *b = a;
815815
/// }
@@ -818,13 +818,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
818818
&self,
819819
err: &mut Diag<'_>,
820820
expr: &hir::Expr<'_>,
821+
expr_ty: Ty<'tcx>,
822+
expected: Ty<'tcx>,
821823
error: Option<TypeError<'tcx>>,
822824
) -> bool {
823-
if let Some(TypeError::Sorts(ExpectedFound { expected, found })) = error
825+
if let Some(TypeError::Sorts(ExpectedFound { .. })) = error
824826
&& let ty::Ref(_, inner, hir::Mutability::Not) = expected.kind()
825827

826828
// The difference between the expected and found values is one level of borrowing.
827-
&& self.can_eq(self.param_env, *inner, found)
829+
&& self.can_eq(self.param_env, *inner, expr_ty)
828830

829831
// We have an `ident = expr;` assignment.
830832
&& let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) =

tests/crashes/140823.rs

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//! Functions with a mismatch between the expected and found type where the difference is a
2+
//! reference may trigger analysis for additional help. In this test the expected type will be
3+
//! &'a Container<&'a u8> and the found type will be Container<&'?0 u8>.
4+
//!
5+
//! This test exercises a scenario where the found type being analyzed contains an inference region
6+
//! variable ('?0). This cannot be used in comparisons because the variable no longer exists by the
7+
//! time the later analysis is performed.
8+
//!
9+
//! This is a regression test of #140823
10+
11+
trait MyFn<P> {}
12+
13+
struct Container<T> {
14+
data: T,
15+
}
16+
17+
struct Desugared {
18+
callback: Box<dyn for<'a> MyFn<&'a Container<&'a u8>>>,
19+
}
20+
21+
fn test(callback: Box<dyn for<'a> MyFn<Container<&'a u8>>>) -> Desugared {
22+
Desugared { callback }
23+
//~^ ERROR mismatched types
24+
}
25+
26+
fn main() {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/coerce-suggestion-infer-region.rs:22:17
3+
|
4+
LL | Desugared { callback }
5+
| ^^^^^^^^ expected `Box<dyn MyFn<&Container<&u8>>>`, found `Box<dyn MyFn<Container<&u8>>>`
6+
|
7+
= note: expected struct `Box<(dyn for<'a> MyFn<&'a Container<&'a u8>> + 'static)>`
8+
found struct `Box<(dyn for<'a> MyFn<Container<&'a u8>> + 'static)>`
9+
10+
error: aborting due to 1 previous error
11+
12+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)