about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-06-19 20:49:07 -0700
committerMichael Goulet <michael@errs.io>2022-06-28 21:42:52 +0000
commit6c0a591deef190ab9bf12836467079367a366c35 (patch)
treeaec1d5352d45ac7e65ccdfbbb654f0adc3d2aef4
parent830880640304ba8699c5f9a0c4665c38a3271963 (diff)
downloadrust-6c0a591deef190ab9bf12836467079367a366c35.tar.gz
rust-6c0a591deef190ab9bf12836467079367a366c35.zip
Fix trait object reborrow suggestion
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs6
-rw-r--r--src/test/ui/suggestions/suggest-borrow-to-dyn-object.rs16
-rw-r--r--src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr19
6 files changed, 43 insertions, 9 deletions
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index ed8de24a65e..7f913faf860 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -253,7 +253,7 @@ pub enum ObligationCauseCode<'tcx> {
     ObjectTypeBound(Ty<'tcx>, ty::Region<'tcx>),
 
     /// Obligation incurred due to an object cast.
-    ObjectCastObligation(/* Object type */ Ty<'tcx>),
+    ObjectCastObligation(/* Concrete type */ Ty<'tcx>, /* Object type */ Ty<'tcx>),
 
     /// Obligation incurred due to a coercion.
     Coercion {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index af0803fbd54..debb9e82951 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -484,10 +484,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                             err.span_label(span, explanation);
                         }
 
-                        if let ObligationCauseCode::ObjectCastObligation(obj_ty) = obligation.cause.code().peel_derives() &&
-                           let Some(self_ty) = trait_predicate.self_ty().no_bound_vars() &&
+                        if let ObligationCauseCode::ObjectCastObligation(concrete_ty, obj_ty) = obligation.cause.code().peel_derives() &&
                            Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
-                            self.suggest_borrowing_for_object_cast(&mut err, &obligation, self_ty, *obj_ty);
+                            self.suggest_borrowing_for_object_cast(&mut err, &root_obligation, *concrete_ty, *obj_ty);
                         }
 
                         if trait_predicate.is_const_if_const() && obligation.param_env.is_const() {
@@ -1560,7 +1559,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                     obligation.cause.code().peel_derives(),
                     ObligationCauseCode::ItemObligation(_)
                         | ObligationCauseCode::BindingObligation(_, _)
-                        | ObligationCauseCode::ObjectCastObligation(_)
+                        | ObligationCauseCode::ObjectCastObligation(..)
                         | ObligationCauseCode::OpaqueType
                 );
                 if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index fbe66d7dcdd..166c7a4110b 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2217,7 +2217,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     err.span_note(tcx.def_span(item_def_id), &descr);
                 }
             }
-            ObligationCauseCode::ObjectCastObligation(object_ty) => {
+            ObligationCauseCode::ObjectCastObligation(_, object_ty) => {
                 err.note(&format!(
                     "required for the cast to the object type `{}`",
                     self.ty_to_string(object_ty)
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 5942bb79d69..e1131140c39 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -813,7 +813,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 let cause = ObligationCause::new(
                     obligation.cause.span,
                     obligation.cause.body_id,
-                    ObjectCastObligation(target),
+                    ObjectCastObligation(source, target),
                 );
                 let outlives = ty::OutlivesPredicate(r_a, r_b);
                 nested.push(Obligation::with_depth(
@@ -910,7 +910,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 let cause = ObligationCause::new(
                     obligation.cause.span,
                     obligation.cause.body_id,
-                    ObjectCastObligation(target),
+                    ObjectCastObligation(source, target),
                 );
                 let outlives = ty::OutlivesPredicate(r_a, r_b);
                 nested.push(Obligation::with_depth(
@@ -931,7 +931,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 let cause = ObligationCause::new(
                     obligation.cause.span,
                     obligation.cause.body_id,
-                    ObjectCastObligation(target),
+                    ObjectCastObligation(source, target),
                 );
 
                 let predicate_to_obligation = |predicate| {
diff --git a/src/test/ui/suggestions/suggest-borrow-to-dyn-object.rs b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.rs
new file mode 100644
index 00000000000..120fc538307
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.rs
@@ -0,0 +1,16 @@
+use std::ffi::{OsStr, OsString};
+use std::path::Path;
+
+fn check(p: &dyn AsRef<Path>) {
+    let m = std::fs::metadata(&p);
+    println!("{:?}", &m);
+}
+
+fn main() {
+    let s: OsString = ".".into();
+    let s: &OsStr = &s;
+    check(s);
+    //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
+    //~| HELP within `OsStr`, the trait `Sized` is not implemented for `[u8]`
+    //~| HELP consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef<Path>`
+}
diff --git a/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr
new file mode 100644
index 00000000000..8961f4275a2
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/suggest-borrow-to-dyn-object.rs:12:11
+   |
+LL |     check(s);
+   |     ----- ^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: within `OsStr`, the trait `Sized` is not implemented for `[u8]`
+   = note: required because it appears within the type `OsStr`
+   = note: required for the cast to the object type `dyn AsRef<Path>`
+help: consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef<Path>`
+   |
+LL |     check(&s);
+   |           +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.