about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs105
-rw-r--r--src/test/ui/issues/issue-38412.rs2
-rw-r--r--src/test/ui/issues/issue-38412.stderr2
-rw-r--r--src/test/ui/issues/issue-42944.rs2
-rw-r--r--src/test/ui/issues/issue-42944.stderr10
-rw-r--r--src/test/ui/issues/issue-75906.rs13
-rw-r--r--src/test/ui/issues/issue-75906.stderr15
-rw-r--r--src/test/ui/issues/issue-75907.rs4
-rw-r--r--src/test/ui/issues/issue-75907.stderr4
-rw-r--r--src/test/ui/issues/issue-75907_b.rs2
-rw-r--r--src/test/ui/issues/issue-75907_b.stderr2
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/struct.rs2
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/struct.stderr2
13 files changed, 108 insertions, 57 deletions
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index c24b383f3b8..cafceff4f29 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -917,54 +917,71 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                 self.suggest_using_enum_variant(err, source, def_id, span);
             }
             (Res::Def(DefKind::Struct, def_id), _) if ns == ValueNS => {
-                if let Some((ctor_def, ctor_vis, fields)) =
-                    self.r.struct_constructors.get(&def_id).cloned()
+                let (ctor_def, ctor_vis, fields) =
+                    if let Some(struct_ctor) = self.r.struct_constructors.get(&def_id).cloned() {
+                        struct_ctor
+                    } else {
+                        bad_struct_syntax_suggestion(def_id);
+                        return true;
+                    };
+
+                let is_accessible = self.r.is_accessible_from(ctor_vis, self.parent_scope.module);
+                if !is_expected(ctor_def) || is_accessible {
+                    return true;
+                }
+
+                let field_spans = match source {
+                    // e.g. `if let Enum::TupleVariant(field1, field2) = _`
+                    PathSource::TupleStruct(_, pattern_spans) => {
+                        err.set_primary_message(
+                            "cannot match against a tuple struct which contains private fields",
+                        );
+
+                        // Use spans of the tuple struct pattern.
+                        Some(Vec::from(pattern_spans))
+                    }
+                    // e.g. `let _ = Enum::TupleVariant(field1, field2);`
+                    _ if source.is_call() => {
+                        err.set_primary_message(
+                            "cannot initialize a tuple struct which contains private fields",
+                        );
+
+                        // Use spans of the tuple struct definition.
+                        self.r
+                            .field_names
+                            .get(&def_id)
+                            .map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
+                    }
+                    _ => None,
+                };
+
+                if let Some(spans) =
+                    field_spans.filter(|spans| spans.len() > 0 && fields.len() == spans.len())
                 {
-                    let accessible_ctor =
-                        self.r.is_accessible_from(ctor_vis, self.parent_scope.module);
-                    if is_expected(ctor_def) && !accessible_ctor {
-                        let mut better_diag = false;
-                        if let PathSource::TupleStruct(_, pattern_spans) = source {
-                            if pattern_spans.len() > 0 && fields.len() == pattern_spans.len() {
-                                let non_visible_spans: Vec<Span> = fields
-                                    .iter()
-                                    .zip(pattern_spans.iter())
-                                    .filter_map(|(vis, span)| {
-                                        match self
-                                            .r
-                                            .is_accessible_from(*vis, self.parent_scope.module)
-                                        {
-                                            true => None,
-                                            false => Some(*span),
-                                        }
-                                    })
-                                    .collect();
-                                // Extra check to be sure
-                                if non_visible_spans.len() > 0 {
-                                    let mut m: rustc_span::MultiSpan =
-                                        non_visible_spans.clone().into();
-                                    non_visible_spans.into_iter().for_each(|s| {
-                                        m.push_span_label(s, "private field".to_string())
-                                    });
-                                    err.span_note(
-                                        m,
-                                        "constructor is not visible here due to private fields",
-                                    );
-                                    better_diag = true;
-                                }
-                            }
-                        }
+                    let non_visible_spans: Vec<Span> = fields
+                        .iter()
+                        .zip(spans.iter())
+                        .filter(|(vis, _)| {
+                            !self.r.is_accessible_from(**vis, self.parent_scope.module)
+                        })
+                        .map(|(_, span)| *span)
+                        .collect();
 
-                        if !better_diag {
-                            err.span_label(
-                                span,
-                                "constructor is not visible here due to private fields".to_string(),
-                            );
-                        }
+                    if non_visible_spans.len() > 0 {
+                        let mut m: rustc_span::MultiSpan = non_visible_spans.clone().into();
+                        non_visible_spans
+                            .into_iter()
+                            .for_each(|s| m.push_span_label(s, "private field".to_string()));
+                        err.span_note(m, "constructor is not visible here due to private fields");
                     }
-                } else {
-                    bad_struct_syntax_suggestion(def_id);
+
+                    return true;
                 }
+
+                err.span_label(
+                    span,
+                    "constructor is not visible here due to private fields".to_string(),
+                );
             }
             (
                 Res::Def(
diff --git a/src/test/ui/issues/issue-38412.rs b/src/test/ui/issues/issue-38412.rs
index 058e1be7565..96bd93af514 100644
--- a/src/test/ui/issues/issue-38412.rs
+++ b/src/test/ui/issues/issue-38412.rs
@@ -1,6 +1,6 @@
 fn main() {
     let Box(a) = loop { };
-    //~^ ERROR expected tuple struct or tuple variant, found struct `Box`
+    //~^ ERROR cannot match against a tuple struct which contains private fields
 
     // (The below is a trick to allow compiler to infer a type for
     // variable `a` without attempting to ascribe a type to the
diff --git a/src/test/ui/issues/issue-38412.stderr b/src/test/ui/issues/issue-38412.stderr
index 318c92ad35f..610696f84d5 100644
--- a/src/test/ui/issues/issue-38412.stderr
+++ b/src/test/ui/issues/issue-38412.stderr
@@ -1,4 +1,4 @@
-error[E0532]: expected tuple struct or tuple variant, found struct `Box`
+error[E0532]: cannot match against a tuple struct which contains private fields
   --> $DIR/issue-38412.rs:2:9
    |
 LL |     let Box(a) = loop { };
diff --git a/src/test/ui/issues/issue-42944.rs b/src/test/ui/issues/issue-42944.rs
index a088f91554d..a4404857a56 100644
--- a/src/test/ui/issues/issue-42944.rs
+++ b/src/test/ui/issues/issue-42944.rs
@@ -7,7 +7,7 @@ mod bar {
 
     fn foo() {
         Bx(());
-        //~^ ERROR expected function, tuple struct or tuple variant, found struct `Bx` [E0423]
+        //~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
     }
 }
 
diff --git a/src/test/ui/issues/issue-42944.stderr b/src/test/ui/issues/issue-42944.stderr
index 9fad43757ba..008492529d1 100644
--- a/src/test/ui/issues/issue-42944.stderr
+++ b/src/test/ui/issues/issue-42944.stderr
@@ -1,8 +1,14 @@
-error[E0423]: expected function, tuple struct or tuple variant, found struct `Bx`
+error[E0423]: cannot initialize a tuple struct which contains private fields
   --> $DIR/issue-42944.rs:9:9
    |
 LL |         Bx(());
-   |         ^^ constructor is not visible here due to private fields
+   |         ^^
+   |
+note: constructor is not visible here due to private fields
+  --> $DIR/issue-42944.rs:2:19
+   |
+LL |     pub struct Bx(());
+   |                   ^^ private field
 
 error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this scope
   --> $DIR/issue-42944.rs:16:9
diff --git a/src/test/ui/issues/issue-75906.rs b/src/test/ui/issues/issue-75906.rs
new file mode 100644
index 00000000000..710039d79e7
--- /dev/null
+++ b/src/test/ui/issues/issue-75906.rs
@@ -0,0 +1,13 @@
+mod m {
+    pub struct Foo { x: u8 }
+
+    pub struct Bar(u8);
+}
+
+use m::{Foo, Bar};
+
+fn main() {
+    let x = Foo { x: 12 };
+    let y = Bar(12);
+    //~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
+}
diff --git a/src/test/ui/issues/issue-75906.stderr b/src/test/ui/issues/issue-75906.stderr
new file mode 100644
index 00000000000..4c6a68646ad
--- /dev/null
+++ b/src/test/ui/issues/issue-75906.stderr
@@ -0,0 +1,15 @@
+error[E0423]: cannot initialize a tuple struct which contains private fields
+  --> $DIR/issue-75906.rs:11:13
+   |
+LL |     let y = Bar(12);
+   |             ^^^
+   |
+note: constructor is not visible here due to private fields
+  --> $DIR/issue-75906.rs:4:20
+   |
+LL |     pub struct Bar(u8);
+   |                    ^^ private field
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/issues/issue-75907.rs b/src/test/ui/issues/issue-75907.rs
index 8c155d9be35..1534b6d07de 100644
--- a/src/test/ui/issues/issue-75907.rs
+++ b/src/test/ui/issues/issue-75907.rs
@@ -13,6 +13,6 @@ use foo::{make_bar, Bar, Foo};
 
 fn main() {
     let Bar(x, y, Foo(z)) = make_bar();
-    //~^ ERROR expected tuple struct
-    //~| ERROR expected tuple struct
+    //~^ ERROR cannot match against a tuple struct which contains private fields
+    //~| ERROR cannot match against a tuple struct which contains private fields
 }
diff --git a/src/test/ui/issues/issue-75907.stderr b/src/test/ui/issues/issue-75907.stderr
index 65b9a51e01d..2f89e31a31a 100644
--- a/src/test/ui/issues/issue-75907.stderr
+++ b/src/test/ui/issues/issue-75907.stderr
@@ -1,4 +1,4 @@
-error[E0532]: expected tuple struct or tuple variant, found struct `Bar`
+error[E0532]: cannot match against a tuple struct which contains private fields
   --> $DIR/issue-75907.rs:15:9
    |
 LL |     let Bar(x, y, Foo(z)) = make_bar();
@@ -12,7 +12,7 @@ LL |     let Bar(x, y, Foo(z)) = make_bar();
    |                |
    |                private field
 
-error[E0532]: expected tuple struct or tuple variant, found struct `Foo`
+error[E0532]: cannot match against a tuple struct which contains private fields
   --> $DIR/issue-75907.rs:15:19
    |
 LL |     let Bar(x, y, Foo(z)) = make_bar();
diff --git a/src/test/ui/issues/issue-75907_b.rs b/src/test/ui/issues/issue-75907_b.rs
index fdd3bc6d724..a775845279e 100644
--- a/src/test/ui/issues/issue-75907_b.rs
+++ b/src/test/ui/issues/issue-75907_b.rs
@@ -7,5 +7,5 @@ use a::{make_bar, Bar};
 
 fn main() {
     let Bar(x, y, z) = make_bar();
-    //~^ ERROR expected tuple struct
+    //~^ ERROR cannot match against a tuple struct which contains private fields
 }
diff --git a/src/test/ui/issues/issue-75907_b.stderr b/src/test/ui/issues/issue-75907_b.stderr
index cdd21de6c33..8884484e18d 100644
--- a/src/test/ui/issues/issue-75907_b.stderr
+++ b/src/test/ui/issues/issue-75907_b.stderr
@@ -1,4 +1,4 @@
-error[E0532]: expected tuple struct or tuple variant, found struct `Bar`
+error[E0532]: cannot match against a tuple struct which contains private fields
   --> $DIR/issue-75907_b.rs:9:9
    |
 LL |     let Bar(x, y, z) = make_bar();
diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.rs b/src/test/ui/rfc-2008-non-exhaustive/struct.rs
index 8cff35c4bc5..07e093c152d 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/struct.rs
+++ b/src/test/ui/rfc-2008-non-exhaustive/struct.rs
@@ -18,7 +18,7 @@ fn main() {
     //~^ ERROR `..` required with struct marked as non-exhaustive
 
     let ts = TupleStruct(640, 480);
-    //~^ ERROR expected function, tuple struct or tuple variant, found struct `TupleStruct` [E0423]
+    //~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
 
     let ts_explicit = structs::TupleStruct(640, 480);
     //~^ ERROR tuple struct constructor `TupleStruct` is private [E0603]
diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
index 3bc38830537..e2ee8d6a6fe 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
@@ -1,4 +1,4 @@
-error[E0423]: expected function, tuple struct or tuple variant, found struct `TupleStruct`
+error[E0423]: cannot initialize a tuple struct which contains private fields
   --> $DIR/struct.rs:20:14
    |
 LL |     let ts = TupleStruct(640, 480);