From 822caa8b800f54c414b692fee64cd844bb6c0f25 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Aug 2023 02:23:49 +0000 Subject: [PATCH] Avoid side-effects from try_coerce when suggesting borrowing LHS of cast --- compiler/rustc_hir_typeck/src/cast.rs | 24 ++---------- .../type-checking-test-1.current.stderr | 20 ++-------- .../trait-upcasting/type-checking-test-1.rs | 1 - .../trait-upcasting/type-checking-test-2.rs | 2 - .../type-checking-test-2.stderr | 37 +++---------------- 5 files changed, 12 insertions(+), 72 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 5bc0e2ee86c8..0f1456882fa3 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -389,34 +389,26 @@ impl<'a, 'tcx> CastCheck<'tcx> { if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() { if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind() && fcx - .try_coerce( - self.expr, + .can_coerce( Ty::new_ref(fcx.tcx, fcx.tcx.lifetimes.re_erased, TypeAndMut { ty: expr_ty, mutbl }, ), self.cast_ty, - AllowTwoPhase::No, - None, ) - .is_ok() { sugg = Some((format!("&{}*", mutbl.prefix_str()), cast_ty == expr_ty)); } else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind() && expr_mutbl == Mutability::Not && mutbl == Mutability::Mut && fcx - .try_coerce( - self.expr, + .can_coerce( Ty::new_ref(fcx.tcx, expr_reg, TypeAndMut { ty: expr_ty, mutbl: Mutability::Mut }, ), self.cast_ty, - AllowTwoPhase::No, - None, ) - .is_ok() { sugg_mutref = true; } @@ -424,30 +416,22 @@ impl<'a, 'tcx> CastCheck<'tcx> { if !sugg_mutref && sugg == None && fcx - .try_coerce( - self.expr, + .can_coerce( Ty::new_ref(fcx.tcx,reg, TypeAndMut { ty: self.expr_ty, mutbl }), self.cast_ty, - AllowTwoPhase::No, - None, ) - .is_ok() { sugg = Some((format!("&{}", mutbl.prefix_str()), false)); } } else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind() && fcx - .try_coerce( - self.expr, + .can_coerce( Ty::new_ref(fcx.tcx, fcx.tcx.lifetimes.re_erased, TypeAndMut { ty: self.expr_ty, mutbl }, ), self.cast_ty, - AllowTwoPhase::No, - None, ) - .is_ok() { sugg = Some((format!("&{}", mutbl.prefix_str()), false)); } diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr index d48d9b89d1da..b612005fcb05 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr +++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr @@ -2,22 +2,8 @@ error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>` --> $DIR/type-checking-test-1.rs:19:13 | LL | let _ = x as &dyn Bar<_>; // Ambiguous - | ^^^^^^^^^^^^^^^^ invalid cast - | -help: consider borrowing the value - | -LL | let _ = &x as &dyn Bar<_>; // Ambiguous - | + + | ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object -error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied - --> $DIR/type-checking-test-1.rs:19:13 - | -LL | let _ = x as &dyn Bar<_>; // Ambiguous - | ^ the trait `Bar<_>` is not implemented for `&dyn Foo` - | - = note: required for the cast from `&&dyn Foo` to `&dyn Bar<_>` +error: aborting due to previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0277, E0605. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs index 7c7beec0809d..afea8521e87d 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs +++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs @@ -18,7 +18,6 @@ fn test_specific(x: &dyn Foo) { fn test_unknown_version(x: &dyn Foo) { let _ = x as &dyn Bar<_>; // Ambiguous //~^ ERROR non-primitive cast - //[current]~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied } fn test_infer_version(x: &dyn Foo) { diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs index 36b11dffdb15..b024b27750bc 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs +++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs @@ -18,13 +18,11 @@ fn test_specific2(x: &dyn Foo) { fn test_specific3(x: &dyn Foo) { let _ = x as &dyn Bar; // Error //~^ ERROR non-primitive cast - //~^^ ERROR the trait bound `&dyn Foo: Bar` is not satisfied } fn test_infer_arg(x: &dyn Foo) { let a = x as &dyn Bar<_>; // Ambiguous //~^ ERROR non-primitive cast - //~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied let _ = a.bar(); } diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr index 856303ef4dd4..3e59b9d33634 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr +++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr @@ -2,41 +2,14 @@ error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar` --> $DIR/type-checking-test-2.rs:19:13 | LL | let _ = x as &dyn Bar; // Error - | ^^^^^^^^^^^^^^^^^^ invalid cast - | -help: consider borrowing the value - | -LL | let _ = &x as &dyn Bar; // Error - | + - -error[E0277]: the trait bound `&dyn Foo: Bar` is not satisfied - --> $DIR/type-checking-test-2.rs:19:13 - | -LL | let _ = x as &dyn Bar; // Error - | ^ the trait `Bar` is not implemented for `&dyn Foo` - | - = note: required for the cast from `&&dyn Foo` to `&dyn Bar` + | ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>` - --> $DIR/type-checking-test-2.rs:25:13 + --> $DIR/type-checking-test-2.rs:24:13 | LL | let a = x as &dyn Bar<_>; // Ambiguous - | ^^^^^^^^^^^^^^^^ invalid cast - | -help: consider borrowing the value - | -LL | let a = &x as &dyn Bar<_>; // Ambiguous - | + + | ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object -error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied - --> $DIR/type-checking-test-2.rs:25:13 - | -LL | let a = x as &dyn Bar<_>; // Ambiguous - | ^ the trait `Bar<_>` is not implemented for `&dyn Foo` - | - = note: required for the cast from `&&dyn Foo` to `&dyn Bar<_>` +error: aborting due to 2 previous errors -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0277, E0605. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0605`.