mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
typeck: better diagnostics for missing inaccessible fields in struct literals/patterns
- typeck/expr: don't suggest adding fields in struct literals with inaccessible fields - typeck/pat: suggest ignoring inaccessible fields in struct patterns
This commit is contained in:
parent
eaf6f46359
commit
cda6ecfc3d
@ -1313,15 +1313,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
} else if check_completeness && !error_happened && !remaining_fields.is_empty() {
|
} else if check_completeness && !error_happened && !remaining_fields.is_empty() {
|
||||||
let no_accessible_remaining_fields = remaining_fields
|
let inaccessible_remaining_fields = remaining_fields.iter().any(|(_, (_, field))| {
|
||||||
.iter()
|
!field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx)
|
||||||
.find(|(_, (_, field))| {
|
});
|
||||||
field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx)
|
|
||||||
})
|
|
||||||
.is_none();
|
|
||||||
|
|
||||||
if no_accessible_remaining_fields {
|
if inaccessible_remaining_fields {
|
||||||
self.report_no_accessible_fields(adt_ty, span);
|
self.report_inaccessible_fields(adt_ty, span);
|
||||||
} else {
|
} else {
|
||||||
self.report_missing_fields(adt_ty, span, remaining_fields);
|
self.report_missing_fields(adt_ty, span, remaining_fields);
|
||||||
}
|
}
|
||||||
@ -1398,7 +1395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Report an error for a struct field expression when there are no visible fields.
|
/// Report an error for a struct field expression when there are invisible fields.
|
||||||
///
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
/// error: cannot construct `Foo` with struct literal syntax due to inaccessible fields
|
/// error: cannot construct `Foo` with struct literal syntax due to inaccessible fields
|
||||||
@ -1409,7 +1406,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
///
|
///
|
||||||
/// error: aborting due to previous error
|
/// error: aborting due to previous error
|
||||||
/// ```
|
/// ```
|
||||||
fn report_no_accessible_fields(&self, adt_ty: Ty<'tcx>, span: Span) {
|
fn report_inaccessible_fields(&self, adt_ty: Ty<'tcx>, span: Span) {
|
||||||
self.tcx.sess.span_err(
|
self.tcx.sess.span_err(
|
||||||
span,
|
span,
|
||||||
&format!(
|
&format!(
|
||||||
|
@ -1250,15 +1250,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit();
|
tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit();
|
||||||
}
|
}
|
||||||
} else if !etc && !unmentioned_fields.is_empty() {
|
} else if !etc && !unmentioned_fields.is_empty() {
|
||||||
let no_accessible_unmentioned_fields = !unmentioned_fields.iter().any(|(field, _)| {
|
let accessible_unmentioned_fields: Vec<_> = unmentioned_fields
|
||||||
field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx)
|
.iter()
|
||||||
});
|
.copied()
|
||||||
|
.filter(|(field, _)| {
|
||||||
|
field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
if no_accessible_unmentioned_fields {
|
if accessible_unmentioned_fields.is_empty() {
|
||||||
unmentioned_err = Some(self.error_no_accessible_fields(pat, &fields));
|
unmentioned_err = Some(self.error_no_accessible_fields(pat, &fields));
|
||||||
} else {
|
} else {
|
||||||
unmentioned_err =
|
unmentioned_err = Some(self.error_unmentioned_fields(
|
||||||
Some(self.error_unmentioned_fields(pat, &unmentioned_fields, &fields));
|
pat,
|
||||||
|
&accessible_unmentioned_fields,
|
||||||
|
accessible_unmentioned_fields.len() != unmentioned_fields.len(),
|
||||||
|
&fields,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match (inexistent_fields_err, unmentioned_err) {
|
match (inexistent_fields_err, unmentioned_err) {
|
||||||
@ -1583,17 +1591,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
&self,
|
&self,
|
||||||
pat: &Pat<'_>,
|
pat: &Pat<'_>,
|
||||||
unmentioned_fields: &[(&ty::FieldDef, Ident)],
|
unmentioned_fields: &[(&ty::FieldDef, Ident)],
|
||||||
|
have_inaccessible_fields: bool,
|
||||||
fields: &'tcx [hir::PatField<'tcx>],
|
fields: &'tcx [hir::PatField<'tcx>],
|
||||||
) -> DiagnosticBuilder<'tcx> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
|
let inaccessible = if have_inaccessible_fields { " and inaccessible fields" } else { "" };
|
||||||
let field_names = if unmentioned_fields.len() == 1 {
|
let field_names = if unmentioned_fields.len() == 1 {
|
||||||
format!("field `{}`", unmentioned_fields[0].1)
|
format!("field `{}`{}", unmentioned_fields[0].1, inaccessible)
|
||||||
} else {
|
} else {
|
||||||
let fields = unmentioned_fields
|
let fields = unmentioned_fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, name)| format!("`{}`", name))
|
.map(|(_, name)| format!("`{}`", name))
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
format!("fields {}", fields)
|
format!("fields {}{}", fields, inaccessible)
|
||||||
};
|
};
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
self.tcx.sess,
|
self.tcx.sess,
|
||||||
@ -1624,17 +1634,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
sp,
|
sp,
|
||||||
&format!(
|
&format!(
|
||||||
"include the missing field{} in the pattern",
|
"include the missing field{} in the pattern{}",
|
||||||
if len == 1 { "" } else { "s" },
|
if len == 1 { "" } else { "s" },
|
||||||
|
if have_inaccessible_fields { " and ignore the inaccessible fields" } else { "" }
|
||||||
),
|
),
|
||||||
format!(
|
format!(
|
||||||
"{}{}{}",
|
"{}{}{}{}",
|
||||||
prefix,
|
prefix,
|
||||||
unmentioned_fields
|
unmentioned_fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, name)| name.to_string())
|
.map(|(_, name)| name.to_string())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", "),
|
.join(", "),
|
||||||
|
if have_inaccessible_fields { ", .." } else { "" },
|
||||||
postfix,
|
postfix,
|
||||||
),
|
),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
pub mod foo {
|
||||||
|
pub struct Foo {
|
||||||
|
pub you_can_use_this_field: bool,
|
||||||
|
you_cant_use_this_field: bool,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
foo::Foo {};
|
||||||
|
//~^ ERROR cannot construct `Foo` with struct literal syntax due to inaccessible fields
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
error: cannot construct `Foo` with struct literal syntax due to inaccessible fields
|
||||||
|
--> $DIR/issue-87872-missing-inaccessible-field-literal.rs:9:5
|
||||||
|
|
|
||||||
|
LL | foo::Foo {};
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
#![allow(dead_code, unused_variables)]
|
||||||
|
|
||||||
|
pub mod foo {
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Foo { pub visible: bool, invisible: bool, }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let foo::Foo {} = foo::Foo::default();
|
||||||
|
//~^ ERROR pattern does not mention field `visible` and inaccessible fields
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
error[E0027]: pattern does not mention field `visible` and inaccessible fields
|
||||||
|
--> $DIR/issue-87872-missing-inaccessible-field-pattern.rs:9:9
|
||||||
|
|
|
||||||
|
LL | let foo::Foo {} = foo::Foo::default();
|
||||||
|
| ^^^^^^^^^^^ missing field `visible` and inaccessible fields
|
||||||
|
|
|
||||||
|
help: include the missing field in the pattern and ignore the inaccessible fields
|
||||||
|
|
|
||||||
|
LL | let foo::Foo { visible, .. } = foo::Foo::default();
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
help: if you don't care about this missing field, you can explicitly ignore it
|
||||||
|
|
|
||||||
|
LL | let foo::Foo { .. } = foo::Foo::default();
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0027`.
|
Loading…
Reference in New Issue
Block a user