resolve: private fields in tuple struct ctor diag
This commit 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. Signed-off-by: David Wood <david@davidtw.co>
This commit is contained in:
parent
b9a94c919b
commit
27bb27f71c
13 changed files with 110 additions and 59 deletions
|
@ -917,55 +917,72 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
self.suggest_using_enum_variant(err, source, def_id, span);
|
self.suggest_using_enum_variant(err, source, def_id, span);
|
||||||
}
|
}
|
||||||
(Res::Def(DefKind::Struct, def_id), _) if ns == ValueNS => {
|
(Res::Def(DefKind::Struct, def_id), _) if ns == ValueNS => {
|
||||||
if let Some((ctor_def, ctor_vis, fields)) =
|
let (ctor_def, ctor_vis, fields) =
|
||||||
self.r.struct_constructors.get(&def_id).cloned()
|
if let Some(struct_ctor) = self.r.struct_constructors.get(&def_id).cloned() {
|
||||||
{
|
struct_ctor
|
||||||
let accessible_ctor =
|
} else {
|
||||||
self.r.is_accessible_from(ctor_vis, self.parent_scope.module);
|
bad_struct_syntax_suggestion(def_id);
|
||||||
if is_expected(ctor_def) && !accessible_ctor {
|
return true;
|
||||||
let mut better_diag = false;
|
};
|
||||||
if let PathSource::TupleStruct(_, pattern_spans) = source {
|
|
||||||
if pattern_spans.len() > 0 && fields.len() == pattern_spans.len() {
|
let is_accessible = self.r.is_accessible_from(ctor_vis, self.parent_scope.module);
|
||||||
let non_visible_spans: Vec<Span> = fields
|
if !is_expected(ctor_def) || is_accessible {
|
||||||
.iter()
|
return true;
|
||||||
.zip(pattern_spans.iter())
|
}
|
||||||
.filter_map(|(vis, span)| {
|
|
||||||
match self
|
let field_spans = match source {
|
||||||
.r
|
// e.g. `if let Enum::TupleVariant(field1, field2) = _`
|
||||||
.is_accessible_from(*vis, self.parent_scope.module)
|
PathSource::TupleStruct(_, pattern_spans) => {
|
||||||
{
|
err.set_primary_message(
|
||||||
true => None,
|
"cannot match against a tuple struct which contains private fields",
|
||||||
false => Some(*span),
|
);
|
||||||
}
|
|
||||||
})
|
// Use spans of the tuple struct pattern.
|
||||||
.collect();
|
Some(Vec::from(pattern_spans))
|
||||||
// Extra check to be sure
|
}
|
||||||
if non_visible_spans.len() > 0 {
|
// e.g. `let _ = Enum::TupleVariant(field1, field2);`
|
||||||
let mut m: rustc_span::MultiSpan =
|
_ if source.is_call() => {
|
||||||
non_visible_spans.clone().into();
|
err.set_primary_message(
|
||||||
non_visible_spans.into_iter().for_each(|s| {
|
"cannot initialize a tuple struct which contains private fields",
|
||||||
m.push_span_label(s, "private field".to_string())
|
);
|
||||||
});
|
|
||||||
err.span_note(
|
// Use spans of the tuple struct definition.
|
||||||
m,
|
self.r
|
||||||
"constructor is not visible here due to private fields",
|
.field_names
|
||||||
);
|
.get(&def_id)
|
||||||
better_diag = true;
|
.map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
|
||||||
}
|
}
|
||||||
}
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(spans) =
|
||||||
|
field_spans.filter(|spans| spans.len() > 0 && fields.len() == spans.len())
|
||||||
|
{
|
||||||
|
let non_visible_spans: Vec<Span> = fields
|
||||||
|
.iter()
|
||||||
|
.zip(spans.iter())
|
||||||
|
.filter(|(vis, _)| {
|
||||||
|
!self.r.is_accessible_from(**vis, self.parent_scope.module)
|
||||||
|
})
|
||||||
|
.map(|(_, span)| *span)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if non_visible_spans.len() > 0 {
|
||||||
|
let mut m: rustc_span::MultiSpan = non_visible_spans.clone().into();
|
||||||
|
non_visible_spans
|
||||||
|
.into_iter()
|
||||||
|
.for_each(|s| m.push_span_label(s, "private field".to_string()));
|
||||||
|
err.span_note(m, "constructor is not visible here due to private fields");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !better_diag {
|
|
||||||
err.span_label(
|
err.span_label(
|
||||||
span,
|
span,
|
||||||
"constructor is not visible here due to private fields".to_string(),
|
"constructor is not visible here due to private fields".to_string(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bad_struct_syntax_suggestion(def_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(
|
(
|
||||||
Res::Def(
|
Res::Def(
|
||||||
DefKind::Union | DefKind::Variant | DefKind::Ctor(_, CtorKind::Fictive),
|
DefKind::Union | DefKind::Variant | DefKind::Ctor(_, CtorKind::Fictive),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
let Box(a) = loop { };
|
let Box(a) = loop { };
|
||||||
//~^ ERROR expected tuple struct or tuple variant, found struct `Box`
|
//~^ ERROR cannot match against a tuple struct which contains private fields
|
||||||
|
|
||||||
// (The below is a trick to allow compiler to infer a type for
|
// (The below is a trick to allow compiler to infer a type for
|
||||||
// variable `a` without attempting to ascribe a type to the
|
// variable `a` without attempting to ascribe a type to the
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0532]: expected tuple struct or tuple variant, found struct `Box`
|
error[E0532]: cannot match against a tuple struct which contains private fields
|
||||||
--> $DIR/issue-38412.rs:2:9
|
--> $DIR/issue-38412.rs:2:9
|
||||||
|
|
|
|
||||||
LL | let Box(a) = loop { };
|
LL | let Box(a) = loop { };
|
||||||
|
|
|
@ -7,7 +7,7 @@ mod bar {
|
||||||
|
|
||||||
fn foo() {
|
fn foo() {
|
||||||
Bx(());
|
Bx(());
|
||||||
//~^ ERROR expected function, tuple struct or tuple variant, found struct `Bx` [E0423]
|
//~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
error[E0423]: expected function, tuple struct or tuple variant, found struct `Bx`
|
error[E0423]: cannot initialize a tuple struct which contains private fields
|
||||||
--> $DIR/issue-42944.rs:9:9
|
--> $DIR/issue-42944.rs:9:9
|
||||||
|
|
|
|
||||||
LL | Bx(());
|
LL | Bx(());
|
||||||
| ^^ constructor is not visible here due to private fields
|
| ^^
|
||||||
|
|
|
||||||
|
note: constructor is not visible here due to private fields
|
||||||
|
--> $DIR/issue-42944.rs:2:19
|
||||||
|
|
|
||||||
|
LL | pub struct Bx(());
|
||||||
|
| ^^ private field
|
||||||
|
|
||||||
error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this scope
|
error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this scope
|
||||||
--> $DIR/issue-42944.rs:16:9
|
--> $DIR/issue-42944.rs:16:9
|
||||||
|
|
13
src/test/ui/issues/issue-75906.rs
Normal file
13
src/test/ui/issues/issue-75906.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
mod m {
|
||||||
|
pub struct Foo { x: u8 }
|
||||||
|
|
||||||
|
pub struct Bar(u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
use m::{Foo, Bar};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = Foo { x: 12 };
|
||||||
|
let y = Bar(12);
|
||||||
|
//~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
|
||||||
|
}
|
15
src/test/ui/issues/issue-75906.stderr
Normal file
15
src/test/ui/issues/issue-75906.stderr
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
error[E0423]: cannot initialize a tuple struct which contains private fields
|
||||||
|
--> $DIR/issue-75906.rs:11:13
|
||||||
|
|
|
||||||
|
LL | let y = Bar(12);
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
note: constructor is not visible here due to private fields
|
||||||
|
--> $DIR/issue-75906.rs:4:20
|
||||||
|
|
|
||||||
|
LL | pub struct Bar(u8);
|
||||||
|
| ^^ private field
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0423`.
|
|
@ -13,6 +13,6 @@ use foo::{make_bar, Bar, Foo};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let Bar(x, y, Foo(z)) = make_bar();
|
let Bar(x, y, Foo(z)) = make_bar();
|
||||||
//~^ ERROR expected tuple struct
|
//~^ ERROR cannot match against a tuple struct which contains private fields
|
||||||
//~| ERROR expected tuple struct
|
//~| ERROR cannot match against a tuple struct which contains private fields
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0532]: expected tuple struct or tuple variant, found struct `Bar`
|
error[E0532]: cannot match against a tuple struct which contains private fields
|
||||||
--> $DIR/issue-75907.rs:15:9
|
--> $DIR/issue-75907.rs:15:9
|
||||||
|
|
|
|
||||||
LL | let Bar(x, y, Foo(z)) = make_bar();
|
LL | let Bar(x, y, Foo(z)) = make_bar();
|
||||||
|
@ -12,7 +12,7 @@ LL | let Bar(x, y, Foo(z)) = make_bar();
|
||||||
| |
|
| |
|
||||||
| private field
|
| private field
|
||||||
|
|
||||||
error[E0532]: expected tuple struct or tuple variant, found struct `Foo`
|
error[E0532]: cannot match against a tuple struct which contains private fields
|
||||||
--> $DIR/issue-75907.rs:15:19
|
--> $DIR/issue-75907.rs:15:19
|
||||||
|
|
|
|
||||||
LL | let Bar(x, y, Foo(z)) = make_bar();
|
LL | let Bar(x, y, Foo(z)) = make_bar();
|
||||||
|
|
|
@ -7,5 +7,5 @@ use a::{make_bar, Bar};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let Bar(x, y, z) = make_bar();
|
let Bar(x, y, z) = make_bar();
|
||||||
//~^ ERROR expected tuple struct
|
//~^ ERROR cannot match against a tuple struct which contains private fields
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0532]: expected tuple struct or tuple variant, found struct `Bar`
|
error[E0532]: cannot match against a tuple struct which contains private fields
|
||||||
--> $DIR/issue-75907_b.rs:9:9
|
--> $DIR/issue-75907_b.rs:9:9
|
||||||
|
|
|
|
||||||
LL | let Bar(x, y, z) = make_bar();
|
LL | let Bar(x, y, z) = make_bar();
|
||||||
|
|
|
@ -18,7 +18,7 @@ fn main() {
|
||||||
//~^ ERROR `..` required with struct marked as non-exhaustive
|
//~^ ERROR `..` required with struct marked as non-exhaustive
|
||||||
|
|
||||||
let ts = TupleStruct(640, 480);
|
let ts = TupleStruct(640, 480);
|
||||||
//~^ ERROR expected function, tuple struct or tuple variant, found struct `TupleStruct` [E0423]
|
//~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
|
||||||
|
|
||||||
let ts_explicit = structs::TupleStruct(640, 480);
|
let ts_explicit = structs::TupleStruct(640, 480);
|
||||||
//~^ ERROR tuple struct constructor `TupleStruct` is private [E0603]
|
//~^ ERROR tuple struct constructor `TupleStruct` is private [E0603]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0423]: expected function, tuple struct or tuple variant, found struct `TupleStruct`
|
error[E0423]: cannot initialize a tuple struct which contains private fields
|
||||||
--> $DIR/struct.rs:20:14
|
--> $DIR/struct.rs:20:14
|
||||||
|
|
|
|
||||||
LL | let ts = TupleStruct(640, 480);
|
LL | let ts = TupleStruct(640, 480);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue