about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMaybe Waffle <waffle.lapkin@gmail.com>2022-07-19 01:16:25 +0400
committerMaybe Waffle <waffle.lapkin@gmail.com>2022-07-19 01:16:25 +0400
commitda2752e00f0139fb13282b2bd97aa0f8c665aee9 (patch)
tree1f43ad0c535a11270645ede3480ecbc224aab587
parent7163e7ff6542b200971a783dc2a720a0ff676e70 (diff)
downloadrust-da2752e00f0139fb13282b2bd97aa0f8c665aee9.tar.gz
rust-da2752e00f0139fb13282b2bd97aa0f8c665aee9.zip
check accessibility before suggesting wrapping expressions
-rw-r--r--compiler/rustc_typeck/src/check/demand.rs18
-rw-r--r--src/test/ui/mismatched_types/wrap-suggestion-privacy.rs24
-rw-r--r--src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr59
3 files changed, 93 insertions, 8 deletions
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 31da5cfe7fa..30d7cc2e5fc 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -19,7 +19,6 @@ use rustc_span::{BytePos, Span};
 use super::method::probe;
 
 use std::iter;
-use std::ops::Bound;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn emit_coerce_suggestions(
@@ -349,13 +348,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
 
-            // Avoid suggesting wrapping in `NonZeroU64` and alike
-            if self.tcx.layout_scalar_valid_range(expected_adt.did())
-                != (Bound::Unbounded, Bound::Unbounded)
-            {
-                return;
-            }
-
             let compatible_variants: Vec<String> = expected_adt
                 .variants()
                 .iter()
@@ -364,6 +356,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 })
                 .filter_map(|variant| {
                     let sole_field = &variant.fields[0];
+
+                    if !sole_field.did.is_local()
+                        && !sole_field.vis.is_accessible_from(
+                            self.tcx.parent_module(expr.hir_id).to_def_id(),
+                            self.tcx,
+                        )
+                    {
+                        return None;
+                    }
+
                     let sole_field_ty = sole_field.ty(self.tcx, substs);
                     if self.can_coerce(expr_ty, sole_field_ty) {
                         let variant_path =
diff --git a/src/test/ui/mismatched_types/wrap-suggestion-privacy.rs b/src/test/ui/mismatched_types/wrap-suggestion-privacy.rs
new file mode 100644
index 00000000000..63cb1a12991
--- /dev/null
+++ b/src/test/ui/mismatched_types/wrap-suggestion-privacy.rs
@@ -0,0 +1,24 @@
+mod inner {
+    pub struct Wrapper<T>(T);
+}
+
+fn needs_wrapper(t: inner::Wrapper<i32>) {}
+fn needs_wrapping(t: std::num::Wrapping<i32>) {}
+fn needs_ready(t: std::future::Ready<i32>) {}
+
+fn main() {
+    // Suggest wrapping expression because type is local
+    // and its privacy can be easily changed
+    needs_wrapper(0);
+    //~^ ERROR mismatched types
+    //~| HELP  try wrapping the expression in `inner::Wrapper`
+
+    // Suggest wrapping expression because field is accessible
+    needs_wrapping(0);
+    //~^ ERROR mismatched types
+    //~| HELP  try wrapping the expression in `std::num::Wrapping`
+
+    // Do not suggest wrapping expression
+    needs_ready(Some(0));
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr b/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr
new file mode 100644
index 00000000000..536638632de
--- /dev/null
+++ b/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr
@@ -0,0 +1,59 @@
+error[E0308]: mismatched types
+  --> $DIR/wrap-suggestion-privacy.rs:12:19
+   |
+LL |     needs_wrapper(0);
+   |     ------------- ^ expected struct `Wrapper`, found integer
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected struct `Wrapper<i32>`
+                found type `{integer}`
+note: function defined here
+  --> $DIR/wrap-suggestion-privacy.rs:5:4
+   |
+LL | fn needs_wrapper(t: inner::Wrapper<i32>) {}
+   |    ^^^^^^^^^^^^^ ----------------------
+help: try wrapping the expression in `inner::Wrapper`
+   |
+LL |     needs_wrapper(inner::Wrapper(0));
+   |                   +++++++++++++++ +
+
+error[E0308]: mismatched types
+  --> $DIR/wrap-suggestion-privacy.rs:17:20
+   |
+LL |     needs_wrapping(0);
+   |     -------------- ^ expected struct `Wrapping`, found integer
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected struct `Wrapping<i32>`
+                found type `{integer}`
+note: function defined here
+  --> $DIR/wrap-suggestion-privacy.rs:6:4
+   |
+LL | fn needs_wrapping(t: std::num::Wrapping<i32>) {}
+   |    ^^^^^^^^^^^^^^ --------------------------
+help: try wrapping the expression in `std::num::Wrapping`
+   |
+LL |     needs_wrapping(std::num::Wrapping(0));
+   |                    +++++++++++++++++++ +
+
+error[E0308]: mismatched types
+  --> $DIR/wrap-suggestion-privacy.rs:22:17
+   |
+LL |     needs_ready(Some(0));
+   |     ----------- ^^^^^^^ expected struct `std::future::Ready`, found enum `Option`
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected struct `std::future::Ready<i32>`
+                found enum `Option<{integer}>`
+note: function defined here
+  --> $DIR/wrap-suggestion-privacy.rs:7:4
+   |
+LL | fn needs_ready(t: std::future::Ready<i32>) {}
+   |    ^^^^^^^^^^^ --------------------------
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.