about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs17
-rw-r--r--compiler/rustc_typeck/src/check/pat.rs32
-rw-r--r--src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.rs11
-rw-r--r--src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr8
-rw-r--r--src/test/ui/typeck/issue-87872-missing-inaccessible-field-pattern.rs11
-rw-r--r--src/test/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr18
6 files changed, 77 insertions, 20 deletions
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 831b573e156..a5362856511 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -1313,15 +1313,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .emit();
             }
         } else if check_completeness && !error_happened && !remaining_fields.is_empty() {
-            let no_accessible_remaining_fields = remaining_fields
-                .iter()
-                .find(|(_, (_, field))| {
-                    field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx)
-                })
-                .is_none();
+            let inaccessible_remaining_fields = remaining_fields.iter().any(|(_, (_, field))| {
+                !field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx)
+            });
 
-            if no_accessible_remaining_fields {
-                self.report_no_accessible_fields(adt_ty, span);
+            if inaccessible_remaining_fields {
+                self.report_inaccessible_fields(adt_ty, span);
             } else {
                 self.report_missing_fields(adt_ty, span, remaining_fields);
             }
@@ -1398,7 +1395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         .emit();
     }
 
-    /// Report an error for a struct field expression when there are no visible fields.
+    /// Report an error for a struct field expression when there are invisible fields.
     ///
     /// ```text
     /// error: cannot construct `Foo` with struct literal syntax due to inaccessible fields
@@ -1409,7 +1406,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ///
     /// error: aborting due to previous error
     /// ```
-    fn report_no_accessible_fields(&self, adt_ty: Ty<'tcx>, span: Span) {
+    fn report_inaccessible_fields(&self, adt_ty: Ty<'tcx>, span: Span) {
         self.tcx.sess.span_err(
             span,
             &format!(
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index db77d155a2b..dae574bb7bf 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -1250,15 +1250,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit();
             }
         } else if !etc && !unmentioned_fields.is_empty() {
-            let no_accessible_unmentioned_fields = !unmentioned_fields.iter().any(|(field, _)| {
-                field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx)
-            });
+            let accessible_unmentioned_fields: Vec<_> = unmentioned_fields
+                .iter()
+                .copied()
+                .filter(|(field, _)| {
+                    field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx)
+                })
+                .collect();
 
-            if no_accessible_unmentioned_fields {
+            if accessible_unmentioned_fields.is_empty() {
                 unmentioned_err = Some(self.error_no_accessible_fields(pat, &fields));
             } else {
-                unmentioned_err =
-                    Some(self.error_unmentioned_fields(pat, &unmentioned_fields, &fields));
+                unmentioned_err = Some(self.error_unmentioned_fields(
+                    pat,
+                    &accessible_unmentioned_fields,
+                    accessible_unmentioned_fields.len() != unmentioned_fields.len(),
+                    &fields,
+                ));
             }
         }
         match (inexistent_fields_err, unmentioned_err) {
@@ -1583,17 +1591,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         pat: &Pat<'_>,
         unmentioned_fields: &[(&ty::FieldDef, Ident)],
+        have_inaccessible_fields: bool,
         fields: &'tcx [hir::PatField<'tcx>],
     ) -> DiagnosticBuilder<'tcx> {
+        let inaccessible = if have_inaccessible_fields { " and inaccessible fields" } else { "" };
         let field_names = if unmentioned_fields.len() == 1 {
-            format!("field `{}`", unmentioned_fields[0].1)
+            format!("field `{}`{}", unmentioned_fields[0].1, inaccessible)
         } else {
             let fields = unmentioned_fields
                 .iter()
                 .map(|(_, name)| format!("`{}`", name))
                 .collect::<Vec<String>>()
                 .join(", ");
-            format!("fields {}", fields)
+            format!("fields {}{}", fields, inaccessible)
         };
         let mut err = struct_span_err!(
             self.tcx.sess,
@@ -1624,17 +1634,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err.span_suggestion(
             sp,
             &format!(
-                "include the missing field{} in the pattern",
+                "include the missing field{} in the pattern{}",
                 if len == 1 { "" } else { "s" },
+                if have_inaccessible_fields { " and ignore the inaccessible fields" } else { "" }
             ),
             format!(
-                "{}{}{}",
+                "{}{}{}{}",
                 prefix,
                 unmentioned_fields
                     .iter()
                     .map(|(_, name)| name.to_string())
                     .collect::<Vec<_>>()
                     .join(", "),
+                if have_inaccessible_fields { ", .." } else { "" },
                 postfix,
             ),
             Applicability::MachineApplicable,
diff --git a/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.rs b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.rs
new file mode 100644
index 00000000000..31761441337
--- /dev/null
+++ b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.rs
@@ -0,0 +1,11 @@
+pub mod foo {
+    pub struct Foo {
+        pub you_can_use_this_field: bool,
+        you_cant_use_this_field: bool,
+    }
+}
+
+fn main() {
+    foo::Foo {};
+    //~^ ERROR cannot construct `Foo` with struct literal syntax due to inaccessible fields
+}
diff --git a/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr
new file mode 100644
index 00000000000..81b73c00e86
--- /dev/null
+++ b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr
@@ -0,0 +1,8 @@
+error: cannot construct `Foo` with struct literal syntax due to inaccessible fields
+  --> $DIR/issue-87872-missing-inaccessible-field-literal.rs:9:5
+   |
+LL |     foo::Foo {};
+   |     ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/typeck/issue-87872-missing-inaccessible-field-pattern.rs b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-pattern.rs
new file mode 100644
index 00000000000..d28e17559d8
--- /dev/null
+++ b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-pattern.rs
@@ -0,0 +1,11 @@
+#![allow(dead_code, unused_variables)]
+
+pub mod foo {
+    #[derive(Default)]
+    pub struct Foo { pub visible: bool, invisible: bool, }
+}
+
+fn main() {
+    let foo::Foo {} = foo::Foo::default();
+    //~^ ERROR pattern does not mention field `visible` and inaccessible fields
+}
diff --git a/src/test/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr
new file mode 100644
index 00000000000..51b8e39b101
--- /dev/null
+++ b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr
@@ -0,0 +1,18 @@
+error[E0027]: pattern does not mention field `visible` and inaccessible fields
+  --> $DIR/issue-87872-missing-inaccessible-field-pattern.rs:9:9
+   |
+LL |     let foo::Foo {} = foo::Foo::default();
+   |         ^^^^^^^^^^^ missing field `visible` and inaccessible fields
+   |
+help: include the missing field in the pattern and ignore the inaccessible fields
+   |
+LL |     let foo::Foo { visible, .. } = foo::Foo::default();
+   |                  ^^^^^^^^^^^^^^^
+help: if you don't care about this missing field, you can explicitly ignore it
+   |
+LL |     let foo::Foo { .. } = foo::Foo::default();
+   |                  ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0027`.