about summary refs log tree commit diff
path: root/compiler/rustc_resolve/src/ident.rs
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2025-01-21 21:07:20 +0000
committerEsteban Küber <esteban@kuber.com.ar>2025-08-10 19:15:18 +0000
commit464a6b1b4af28f7b2d1adf051bad3f182e23b88e (patch)
tree33f8b9d8e302ee705b99b74923c63c20bc96b97e /compiler/rustc_resolve/src/ident.rs
parent18eeac04fc5c2a4c4a8020dbdf1c652077ad0e4e (diff)
downloadrust-464a6b1b4af28f7b2d1adf051bad3f182e23b88e.tar.gz
rust-464a6b1b4af28f7b2d1adf051bad3f182e23b88e.zip
Detect struct construction with private field in field with default
When trying to construct a struct that has a public field of a private type, suggest using `..` if that field has a default value.

```
error[E0603]: struct `Priv1` is private
  --> $DIR/non-exhaustive-ctor.rs:25:39
   |
LL |     let _ = S { field: (), field1: m::Priv1 {} };
   |                            ------     ^^^^^ private struct
   |                            |
   |                            while setting this field
   |
note: the struct `Priv1` is defined here
  --> $DIR/non-exhaustive-ctor.rs:14:4
   |
LL |    struct Priv1 {}
   |    ^^^^^^^^^^^^
help: the field `field1` you're trying to set has a default value, you can use `..` to use it
   |
LL |     let _ = S { field: (), .. };
   |                            ~~
```
Diffstat (limited to 'compiler/rustc_resolve/src/ident.rs')
-rw-r--r--compiler/rustc_resolve/src/ident.rs19
1 files changed, 18 insertions, 1 deletions
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 092bb6fc4f9..9efcef695b7 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -1029,6 +1029,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     binding,
                     dedup_span: path_span,
                     outermost_res: None,
+                    source: None,
                     parent_scope: *parent_scope,
                     single_nested: path_span != root_span,
                 });
@@ -1435,7 +1436,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         parent_scope: &ParentScope<'ra>,
         ignore_import: Option<Import<'ra>>,
     ) -> PathResult<'ra> {
-        self.resolve_path_with_ribs(path, opt_ns, parent_scope, None, None, None, ignore_import)
+        self.resolve_path_with_ribs(
+            path,
+            opt_ns,
+            parent_scope,
+            None,
+            None,
+            None,
+            None,
+            ignore_import,
+        )
     }
     #[instrument(level = "debug", skip(self))]
     pub(crate) fn resolve_path<'r>(
@@ -1451,6 +1461,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             path,
             opt_ns,
             parent_scope,
+            None,
             finalize,
             None,
             ignore_binding,
@@ -1463,6 +1474,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         path: &[Segment],
         opt_ns: Option<Namespace>, // `None` indicates a module path in import
         parent_scope: &ParentScope<'ra>,
+        source: Option<PathSource<'_, '_, '_>>,
         finalize: Option<Finalize>,
         ribs: Option<&PerNS<Vec<Rib<'ra>>>>,
         ignore_binding: Option<NameBinding<'ra>>,
@@ -1645,6 +1657,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     if finalize.is_some() {
                         for error in &mut self.get_mut().privacy_errors[privacy_errors_len..] {
                             error.outermost_res = Some((res, ident));
+                            error.source = match source {
+                                Some(PathSource::Struct(Some(expr)))
+                                | Some(PathSource::Expr(Some(expr))) => Some(expr.clone()),
+                                _ => None,
+                            };
                         }
                     }