Skip to content

Commit 0bd2437

Browse files
authored
Rollup merge of #147478 - Jamesbarford:fix/tuple-private-fields-constructor, r=davidtwco
More intuitive error when using self to instantiate tuple struct with private field Fixes #147343
2 parents 537a778 + 7af72e7 commit 0bd2437

File tree

3 files changed

+84
-44
lines changed

3 files changed

+84
-44
lines changed

compiler/rustc_resolve/src/late/diagnostics.rs

Lines changed: 57 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
180180
let mut expected = source.descr_expected();
181181
let path_str = Segment::names_to_string(path);
182182
let item_str = path.last().unwrap().ident;
183+
183184
if let Some(res) = res {
184185
BaseError {
185186
msg: format!("expected {}, found {} `{}`", expected, res.descr(), path_str),
@@ -821,12 +822,18 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
821822
args_snippet = snippet;
822823
}
823824

824-
err.span_suggestion(
825-
call_span,
826-
format!("try calling `{ident}` as a method"),
827-
format!("self.{path_str}({args_snippet})"),
828-
Applicability::MachineApplicable,
829-
);
825+
if let Some(Res::Def(DefKind::Struct, def_id)) = res {
826+
self.update_err_for_private_tuple_struct_fields(err, &source, def_id);
827+
err.note("constructor is not visible here due to private fields");
828+
} else {
829+
err.span_suggestion(
830+
call_span,
831+
format!("try calling `{ident}` as a method"),
832+
format!("self.{path_str}({args_snippet})"),
833+
Applicability::MachineApplicable,
834+
);
835+
}
836+
830837
return (true, suggested_candidates, candidates);
831838
}
832839
}
@@ -1611,6 +1618,47 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
16111618
}
16121619
}
16131620

1621+
fn update_err_for_private_tuple_struct_fields(
1622+
&mut self,
1623+
err: &mut Diag<'_>,
1624+
source: &PathSource<'_, '_, '_>,
1625+
def_id: DefId,
1626+
) -> Option<Vec<Span>> {
1627+
match source {
1628+
// e.g. `if let Enum::TupleVariant(field1, field2) = _`
1629+
PathSource::TupleStruct(_, pattern_spans) => {
1630+
err.primary_message(
1631+
"cannot match against a tuple struct which contains private fields",
1632+
);
1633+
1634+
// Use spans of the tuple struct pattern.
1635+
Some(Vec::from(*pattern_spans))
1636+
}
1637+
// e.g. `let _ = Enum::TupleVariant(field1, field2);`
1638+
PathSource::Expr(Some(Expr {
1639+
kind: ExprKind::Call(path, args),
1640+
span: call_span,
1641+
..
1642+
})) => {
1643+
err.primary_message(
1644+
"cannot initialize a tuple struct which contains private fields",
1645+
);
1646+
self.suggest_alternative_construction_methods(
1647+
def_id,
1648+
err,
1649+
path.span,
1650+
*call_span,
1651+
&args[..],
1652+
);
1653+
// Use spans of the tuple struct definition.
1654+
self.r
1655+
.field_idents(def_id)
1656+
.map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
1657+
}
1658+
_ => None,
1659+
}
1660+
}
1661+
16141662
/// Provides context-dependent help for errors reported by the `smart_resolve_path_fragment`
16151663
/// function.
16161664
/// Returns `true` if able to provide context-dependent help.
@@ -1942,42 +1990,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
19421990
return true;
19431991
};
19441992

1945-
let update_message =
1946-
|this: &mut Self, err: &mut Diag<'_>, source: &PathSource<'_, '_, '_>| {
1947-
match source {
1948-
// e.g. `if let Enum::TupleVariant(field1, field2) = _`
1949-
PathSource::TupleStruct(_, pattern_spans) => {
1950-
err.primary_message(
1951-
"cannot match against a tuple struct which contains private fields",
1952-
);
1953-
1954-
// Use spans of the tuple struct pattern.
1955-
Some(Vec::from(*pattern_spans))
1956-
}
1957-
// e.g. `let _ = Enum::TupleVariant(field1, field2);`
1958-
PathSource::Expr(Some(Expr {
1959-
kind: ExprKind::Call(path, args),
1960-
span: call_span,
1961-
..
1962-
})) => {
1963-
err.primary_message(
1964-
"cannot initialize a tuple struct which contains private fields",
1965-
);
1966-
this.suggest_alternative_construction_methods(
1967-
def_id,
1968-
err,
1969-
path.span,
1970-
*call_span,
1971-
&args[..],
1972-
);
1973-
// Use spans of the tuple struct definition.
1974-
this.r
1975-
.field_idents(def_id)
1976-
.map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
1977-
}
1978-
_ => None,
1979-
}
1980-
};
19811993
let is_accessible = self.r.is_accessible_from(ctor_vis, self.parent_scope.module);
19821994
if let Some(use_span) = self.r.inaccessible_ctor_reexport.get(&span)
19831995
&& is_accessible
@@ -2006,13 +2018,14 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
20062018
Applicability::MachineApplicable,
20072019
);
20082020
}
2009-
update_message(self, err, &source);
2021+
self.update_err_for_private_tuple_struct_fields(err, &source, def_id);
20102022
}
20112023
if !is_expected(ctor_def) || is_accessible {
20122024
return true;
20132025
}
20142026

2015-
let field_spans = update_message(self, err, &source);
2027+
let field_spans =
2028+
self.update_err_for_private_tuple_struct_fields(err, &source, def_id);
20162029

20172030
if let Some(spans) =
20182031
field_spans.filter(|spans| spans.len() > 0 && fields.len() == spans.len())
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
mod m {
2+
pub struct S(crate::P);
3+
}
4+
5+
use m::S;
6+
7+
struct P;
8+
9+
impl P {
10+
fn foo(self) {
11+
S(self);
12+
//~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
13+
}
14+
}
15+
16+
fn main() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0423]: cannot initialize a tuple struct which contains private fields
2+
--> $DIR/private-constructor-self-issue-147343.rs:11:9
3+
|
4+
LL | S(self);
5+
| ^
6+
|
7+
= note: constructor is not visible here due to private fields
8+
9+
error: aborting due to 1 previous error
10+
11+
For more information about this error, try `rustc --explain E0423`.

0 commit comments

Comments
 (0)