From 87dc85d3222743aeb82848537ad77c2ece746ef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 17 Oct 2023 19:29:43 +0000 Subject: [PATCH] Suggest assoc fn `new` when trying to build tuple struct with private fields Fix #22488. --- .../rustc_resolve/src/late/diagnostics.rs | 21 ++++++++++++++++++- tests/ui/privacy/suggest-box-new.fixed | 15 +++++++++++++ tests/ui/privacy/suggest-box-new.rs | 15 +++++++++++++ tests/ui/privacy/suggest-box-new.stderr | 20 ++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 tests/ui/privacy/suggest-box-new.fixed create mode 100644 tests/ui/privacy/suggest-box-new.rs create mode 100644 tests/ui/privacy/suggest-box-new.stderr diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a5f8f61f3db50..fd5d6fabf021d 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1570,7 +1570,26 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err.set_primary_message( "cannot initialize a tuple struct which contains private fields", ); - + if !def_id.is_local() + && self + .r + .tcx + .inherent_impls(def_id) + .iter() + .flat_map(|impl_def_id| { + self.r.tcx.provided_trait_methods(*impl_def_id) + }) + .any(|assoc| !assoc.fn_has_self_parameter && assoc.name == sym::new) + { + // FIXME: look for associated functions with Self return type, + // instead of relying only on the name and lack of self receiver. + err.span_suggestion_verbose( + span.shrink_to_hi(), + "you might have meant to use the `new` associated function", + "::new".to_string(), + Applicability::MaybeIncorrect, + ); + } // Use spans of the tuple struct definition. self.r.field_def_ids(def_id).map(|field_ids| { field_ids diff --git a/tests/ui/privacy/suggest-box-new.fixed b/tests/ui/privacy/suggest-box-new.fixed new file mode 100644 index 0000000000000..f5ae5c2abfd99 --- /dev/null +++ b/tests/ui/privacy/suggest-box-new.fixed @@ -0,0 +1,15 @@ +// run-rustfix +#![allow(dead_code)] +struct U { + wtf: Option>>, + x: T, +} +fn main() { + U { + wtf: Some(Box::new(U { //~ ERROR cannot initialize a tuple struct which contains private fields + wtf: None, + x: (), + })), + x: () + }; +} diff --git a/tests/ui/privacy/suggest-box-new.rs b/tests/ui/privacy/suggest-box-new.rs new file mode 100644 index 0000000000000..2e18dba8b9fb2 --- /dev/null +++ b/tests/ui/privacy/suggest-box-new.rs @@ -0,0 +1,15 @@ +// run-rustfix +#![allow(dead_code)] +struct U { + wtf: Option>>, + x: T, +} +fn main() { + U { + wtf: Some(Box(U { //~ ERROR cannot initialize a tuple struct which contains private fields + wtf: None, + x: (), + })), + x: () + }; +} diff --git a/tests/ui/privacy/suggest-box-new.stderr b/tests/ui/privacy/suggest-box-new.stderr new file mode 100644 index 0000000000000..ed7fa036408a4 --- /dev/null +++ b/tests/ui/privacy/suggest-box-new.stderr @@ -0,0 +1,20 @@ +error[E0423]: cannot initialize a tuple struct which contains private fields + --> $DIR/suggest-box-new.rs:9:19 + | +LL | wtf: Some(Box(U { + | ^^^ + | +note: constructor is not visible here due to private fields + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + | + = note: private field + | + = note: private field +help: you might have meant to use the `new` associated function + | +LL | wtf: Some(Box::new(U { + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`.