about summary refs log tree commit diff
path: root/compiler/rustc_resolve/src/ident.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_resolve/src/ident.rs')
-rw-r--r--compiler/rustc_resolve/src/ident.rs44
1 files changed, 39 insertions, 5 deletions
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 35051675fd8..4415300777f 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -492,14 +492,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         _ => Err(Determinacy::Determined),
                     },
                     Scope::Module(module, derive_fallback_lint_id) => {
-                        // FIXME: use `finalize_scope` here.
                         let (adjusted_parent_scope, adjusted_finalize) =
                             if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) {
-                                (parent_scope, finalize)
+                                (parent_scope, finalize_scope!())
                             } else {
                                 (
                                     &ParentScope { module, ..*parent_scope },
-                                    finalize.map(|f| Finalize { used: Used::Scope, ..f }),
+                                    finalize_scope!().map(|f| Finalize { used: Used::Scope, ..f }),
                                 )
                             };
                         let binding = this.reborrow().resolve_ident_in_module_unadjusted(
@@ -557,8 +556,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         None => Err(Determinacy::Determined),
                     },
                     Scope::ExternPreludeItems => {
-                        // FIXME: use `finalize_scope` here.
-                        match this.reborrow().extern_prelude_get_item(ident, finalize.is_some()) {
+                        match this
+                            .reborrow()
+                            .extern_prelude_get_item(ident, finalize_scope!().is_some())
+                        {
                             Some(binding) => {
                                 extern_prelude_item_binding = Some(binding);
                                 Ok((binding, Flags::empty()))
@@ -900,6 +901,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 binding,
                 if resolution.non_glob_binding.is_some() { resolution.glob_binding } else { None },
                 parent_scope,
+                module,
                 finalize,
                 shadowing,
             );
@@ -1024,6 +1026,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         binding: Option<NameBinding<'ra>>,
         shadowed_glob: Option<NameBinding<'ra>>,
         parent_scope: &ParentScope<'ra>,
+        module: Module<'ra>,
         finalize: Finalize,
         shadowing: Shadowing,
     ) -> Result<NameBinding<'ra>, (Determinacy, Weak)> {
@@ -1075,6 +1078,37 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
         }
 
+        // If we encounter a re-export for a type with private fields, it will not be able to
+        // be constructed through this re-export. We track that case here to expand later
+        // privacy errors with appropriate information.
+        if let Res::Def(_, def_id) = binding.res() {
+            let struct_ctor = match def_id.as_local() {
+                Some(def_id) => self.struct_constructors.get(&def_id).cloned(),
+                None => {
+                    let ctor = self.cstore().ctor_untracked(def_id);
+                    ctor.map(|(ctor_kind, ctor_def_id)| {
+                        let ctor_res = Res::Def(
+                            DefKind::Ctor(rustc_hir::def::CtorOf::Struct, ctor_kind),
+                            ctor_def_id,
+                        );
+                        let ctor_vis = self.tcx.visibility(ctor_def_id);
+                        let field_visibilities = self
+                            .tcx
+                            .associated_item_def_ids(def_id)
+                            .iter()
+                            .map(|field_id| self.tcx.visibility(field_id))
+                            .collect();
+                        (ctor_res, ctor_vis, field_visibilities)
+                    })
+                }
+            };
+            if let Some((_, _, fields)) = struct_ctor
+                && fields.iter().any(|vis| !self.is_accessible_from(*vis, module))
+            {
+                self.inaccessible_ctor_reexport.insert(path_span, binding.span);
+            }
+        }
+
         self.record_use(ident, binding, used);
         return Ok(binding);
     }