Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-diagnostics/src/handlers/missing_fields.rs')
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_fields.rs57
1 files changed, 52 insertions, 5 deletions
diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs
index 050d5477f6..85368cc09f 100644
--- a/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -1,6 +1,6 @@
use either::Either;
use hir::{
- AssocItem, FindPathConfig, HirDisplay, InFile, Type,
+ AssocItem, FindPathConfig, HasVisibility, HirDisplay, InFile, Type,
db::{ExpandDatabase, HirDatabase},
sym,
};
@@ -35,7 +35,7 @@ use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, fix};
// ```
pub(crate) fn missing_fields(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Diagnostic {
let mut message = String::from("missing structure fields:\n");
- for field in &d.missed_fields {
+ for (field, _) in &d.missed_fields {
format_to!(message, "- {}\n", field.display(ctx.sema.db, ctx.edition));
}
@@ -57,7 +57,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
// `struct A(usize);`
// `let a = A { 0: () }`
// but it is uncommon usage and it should not be encouraged.
- if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) {
+ if d.missed_fields.iter().any(|(name, _)| name.as_tuple_index().is_some()) {
return None;
}
@@ -68,6 +68,12 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
let range = InFile::new(d.file, d.field_list_parent.text_range())
.original_node_file_range_rooted_opt(ctx.sema.db)?;
+ if let Some(current_module) = current_module
+ && d.missed_fields.iter().any(|(_, field)| !field.is_visible_from(ctx.db(), current_module))
+ {
+ return None;
+ }
+
let build_text_edit = |new_syntax: &SyntaxNode, old_syntax| {
let edit = {
let old_range = ctx.sema.original_range_opt(old_syntax)?;
@@ -120,7 +126,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
let field_expr = if let Some(local_candidate) = locals.get(&f.name(ctx.sema.db)) {
cov_mark::hit!(field_shorthand);
let candidate_ty = local_candidate.ty(ctx.sema.db);
- if ty.could_unify_with(ctx.sema.db, &candidate_ty) {
+ if candidate_ty.could_coerce_to(ctx.sema.db, ty) {
None
} else {
Some(generate_fill_expr(ty))
@@ -254,7 +260,7 @@ fn get_default_constructor(
#[cfg(test)]
mod tests {
- use crate::tests::{check_diagnostics, check_fix};
+ use crate::tests::{check_diagnostics, check_fix, check_no_fix};
#[test]
fn missing_record_pat_field_diagnostic() {
@@ -934,4 +940,45 @@ fn main() {
"#,
);
}
+
+ #[test]
+ fn coerce_existing_local() {
+ check_fix(
+ r#"
+struct A {
+ v: f64,
+}
+
+fn f() -> A {
+ let v = loop {};
+ A {$0}
+}
+ "#,
+ r#"
+struct A {
+ v: f64,
+}
+
+fn f() -> A {
+ let v = loop {};
+ A { v }
+}
+ "#,
+ );
+ }
+
+ #[test]
+ fn inaccessible_fields() {
+ check_no_fix(
+ r#"
+mod foo {
+ pub struct Bar { baz: i32 }
+}
+
+fn qux() {
+ foo::Bar {$0};
+}
+ "#,
+ );
+ }
}