Skip to content

Commit c9279c8

Browse files
authored
Rollup merge of #78401 - davidtwco:issue-75906-tuple-construct-private-field, r=estebank
resolve: private fields in tuple struct ctor diag Fixes #75906. This PR improves the diagnostic emitted when a tuple struct is being constructed which has private fields so that private fields are labelled and the message is improved. r? @estebank
2 parents c3f842b + 27bb27f commit c9279c8

13 files changed

+108
-57
lines changed

compiler/rustc_resolve/src/late/diagnostics.rs

+61-44
Original file line numberDiff line numberDiff line change
@@ -917,54 +917,71 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
917917
self.suggest_using_enum_variant(err, source, def_id, span);
918918
}
919919
(Res::Def(DefKind::Struct, def_id), _) if ns == ValueNS => {
920-
if let Some((ctor_def, ctor_vis, fields)) =
921-
self.r.struct_constructors.get(&def_id).cloned()
920+
let (ctor_def, ctor_vis, fields) =
921+
if let Some(struct_ctor) = self.r.struct_constructors.get(&def_id).cloned() {
922+
struct_ctor
923+
} else {
924+
bad_struct_syntax_suggestion(def_id);
925+
return true;
926+
};
927+
928+
let is_accessible = self.r.is_accessible_from(ctor_vis, self.parent_scope.module);
929+
if !is_expected(ctor_def) || is_accessible {
930+
return true;
931+
}
932+
933+
let field_spans = match source {
934+
// e.g. `if let Enum::TupleVariant(field1, field2) = _`
935+
PathSource::TupleStruct(_, pattern_spans) => {
936+
err.set_primary_message(
937+
"cannot match against a tuple struct which contains private fields",
938+
);
939+
940+
// Use spans of the tuple struct pattern.
941+
Some(Vec::from(pattern_spans))
942+
}
943+
// e.g. `let _ = Enum::TupleVariant(field1, field2);`
944+
_ if source.is_call() => {
945+
err.set_primary_message(
946+
"cannot initialize a tuple struct which contains private fields",
947+
);
948+
949+
// Use spans of the tuple struct definition.
950+
self.r
951+
.field_names
952+
.get(&def_id)
953+
.map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
954+
}
955+
_ => None,
956+
};
957+
958+
if let Some(spans) =
959+
field_spans.filter(|spans| spans.len() > 0 && fields.len() == spans.len())
922960
{
923-
let accessible_ctor =
924-
self.r.is_accessible_from(ctor_vis, self.parent_scope.module);
925-
if is_expected(ctor_def) && !accessible_ctor {
926-
let mut better_diag = false;
927-
if let PathSource::TupleStruct(_, pattern_spans) = source {
928-
if pattern_spans.len() > 0 && fields.len() == pattern_spans.len() {
929-
let non_visible_spans: Vec<Span> = fields
930-
.iter()
931-
.zip(pattern_spans.iter())
932-
.filter_map(|(vis, span)| {
933-
match self
934-
.r
935-
.is_accessible_from(*vis, self.parent_scope.module)
936-
{
937-
true => None,
938-
false => Some(*span),
939-
}
940-
})
941-
.collect();
942-
// Extra check to be sure
943-
if non_visible_spans.len() > 0 {
944-
let mut m: rustc_span::MultiSpan =
945-
non_visible_spans.clone().into();
946-
non_visible_spans.into_iter().for_each(|s| {
947-
m.push_span_label(s, "private field".to_string())
948-
});
949-
err.span_note(
950-
m,
951-
"constructor is not visible here due to private fields",
952-
);
953-
better_diag = true;
954-
}
955-
}
956-
}
961+
let non_visible_spans: Vec<Span> = fields
962+
.iter()
963+
.zip(spans.iter())
964+
.filter(|(vis, _)| {
965+
!self.r.is_accessible_from(**vis, self.parent_scope.module)
966+
})
967+
.map(|(_, span)| *span)
968+
.collect();
957969

958-
if !better_diag {
959-
err.span_label(
960-
span,
961-
"constructor is not visible here due to private fields".to_string(),
962-
);
963-
}
970+
if non_visible_spans.len() > 0 {
971+
let mut m: rustc_span::MultiSpan = non_visible_spans.clone().into();
972+
non_visible_spans
973+
.into_iter()
974+
.for_each(|s| m.push_span_label(s, "private field".to_string()));
975+
err.span_note(m, "constructor is not visible here due to private fields");
964976
}
965-
} else {
966-
bad_struct_syntax_suggestion(def_id);
977+
978+
return true;
967979
}
980+
981+
err.span_label(
982+
span,
983+
"constructor is not visible here due to private fields".to_string(),
984+
);
968985
}
969986
(
970987
Res::Def(

src/test/ui/issues/issue-38412.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
fn main() {
22
let Box(a) = loop { };
3-
//~^ ERROR expected tuple struct or tuple variant, found struct `Box`
3+
//~^ ERROR cannot match against a tuple struct which contains private fields
44

55
// (The below is a trick to allow compiler to infer a type for
66
// variable `a` without attempting to ascribe a type to the

src/test/ui/issues/issue-38412.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0532]: expected tuple struct or tuple variant, found struct `Box`
1+
error[E0532]: cannot match against a tuple struct which contains private fields
22
--> $DIR/issue-38412.rs:2:9
33
|
44
LL | let Box(a) = loop { };

src/test/ui/issues/issue-42944.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ mod bar {
77

88
fn foo() {
99
Bx(());
10-
//~^ ERROR expected function, tuple struct or tuple variant, found struct `Bx` [E0423]
10+
//~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
1111
}
1212
}
1313

src/test/ui/issues/issue-42944.stderr

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
error[E0423]: expected function, tuple struct or tuple variant, found struct `Bx`
1+
error[E0423]: cannot initialize a tuple struct which contains private fields
22
--> $DIR/issue-42944.rs:9:9
33
|
44
LL | Bx(());
5-
| ^^ constructor is not visible here due to private fields
5+
| ^^
6+
|
7+
note: constructor is not visible here due to private fields
8+
--> $DIR/issue-42944.rs:2:19
9+
|
10+
LL | pub struct Bx(());
11+
| ^^ private field
612

713
error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this scope
814
--> $DIR/issue-42944.rs:16:9

src/test/ui/issues/issue-75906.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
mod m {
2+
pub struct Foo { x: u8 }
3+
4+
pub struct Bar(u8);
5+
}
6+
7+
use m::{Foo, Bar};
8+
9+
fn main() {
10+
let x = Foo { x: 12 };
11+
let y = Bar(12);
12+
//~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
13+
}

src/test/ui/issues/issue-75906.stderr

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0423]: cannot initialize a tuple struct which contains private fields
2+
--> $DIR/issue-75906.rs:11:13
3+
|
4+
LL | let y = Bar(12);
5+
| ^^^
6+
|
7+
note: constructor is not visible here due to private fields
8+
--> $DIR/issue-75906.rs:4:20
9+
|
10+
LL | pub struct Bar(u8);
11+
| ^^ private field
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0423`.

src/test/ui/issues/issue-75907.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ use foo::{make_bar, Bar, Foo};
1313

1414
fn main() {
1515
let Bar(x, y, Foo(z)) = make_bar();
16-
//~^ ERROR expected tuple struct
17-
//~| ERROR expected tuple struct
16+
//~^ ERROR cannot match against a tuple struct which contains private fields
17+
//~| ERROR cannot match against a tuple struct which contains private fields
1818
}

src/test/ui/issues/issue-75907.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0532]: expected tuple struct or tuple variant, found struct `Bar`
1+
error[E0532]: cannot match against a tuple struct which contains private fields
22
--> $DIR/issue-75907.rs:15:9
33
|
44
LL | let Bar(x, y, Foo(z)) = make_bar();
@@ -12,7 +12,7 @@ LL | let Bar(x, y, Foo(z)) = make_bar();
1212
| |
1313
| private field
1414

15-
error[E0532]: expected tuple struct or tuple variant, found struct `Foo`
15+
error[E0532]: cannot match against a tuple struct which contains private fields
1616
--> $DIR/issue-75907.rs:15:19
1717
|
1818
LL | let Bar(x, y, Foo(z)) = make_bar();

src/test/ui/issues/issue-75907_b.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ use a::{make_bar, Bar};
77

88
fn main() {
99
let Bar(x, y, z) = make_bar();
10-
//~^ ERROR expected tuple struct
10+
//~^ ERROR cannot match against a tuple struct which contains private fields
1111
}

src/test/ui/issues/issue-75907_b.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0532]: expected tuple struct or tuple variant, found struct `Bar`
1+
error[E0532]: cannot match against a tuple struct which contains private fields
22
--> $DIR/issue-75907_b.rs:9:9
33
|
44
LL | let Bar(x, y, z) = make_bar();

src/test/ui/rfc-2008-non-exhaustive/struct.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ fn main() {
1818
//~^ ERROR `..` required with struct marked as non-exhaustive
1919

2020
let ts = TupleStruct(640, 480);
21-
//~^ ERROR expected function, tuple struct or tuple variant, found struct `TupleStruct` [E0423]
21+
//~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
2222

2323
let ts_explicit = structs::TupleStruct(640, 480);
2424
//~^ ERROR tuple struct constructor `TupleStruct` is private [E0603]

src/test/ui/rfc-2008-non-exhaustive/struct.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0423]: expected function, tuple struct or tuple variant, found struct `TupleStruct`
1+
error[E0423]: cannot initialize a tuple struct which contains private fields
22
--> $DIR/struct.rs:20:14
33
|
44
LL | let ts = TupleStruct(640, 480);

0 commit comments

Comments
 (0)