]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_typeck/src/check/demand.rs
Rollup merge of #99488 - luqmana:debuginfo-revisions, r=tmiasko
[rust.git] / compiler / rustc_typeck / src / check / demand.rs
index 30d7cc2e5fc6a490df12bc916d28a86e90d2d982..a2d8765289c55498ae098f049d3ea424b386a5aa 100644 (file)
@@ -348,7 +348,7 @@ fn suggest_compatible_variants(
                 }
             }
 
-            let compatible_variants: Vec<String> = expected_adt
+            let compatible_variants: Vec<(String, Option<String>)> = expected_adt
                 .variants()
                 .iter()
                 .filter(|variant| {
@@ -357,15 +357,17 @@ fn suggest_compatible_variants(
                 .filter_map(|variant| {
                     let sole_field = &variant.fields[0];
 
-                    if !sole_field.did.is_local()
-                        && !sole_field.vis.is_accessible_from(
-                            self.tcx.parent_module(expr.hir_id).to_def_id(),
-                            self.tcx,
-                        )
-                    {
+                    let field_is_local = sole_field.did.is_local();
+                    let field_is_accessible =
+                        sole_field.vis.is_accessible_from(expr.hir_id.owner.to_def_id(), self.tcx);
+
+                    if !field_is_local && !field_is_accessible {
                         return None;
                     }
 
+                    let note_about_variant_field_privacy = (field_is_local && !field_is_accessible)
+                        .then(|| format!(" (its field is private, but it's local to this crate and its privacy can be changed)"));
+
                     let sole_field_ty = sole_field.ty(self.tcx, substs);
                     if self.can_coerce(expr_ty, sole_field_ty) {
                         let variant_path =
@@ -374,9 +376,9 @@ fn suggest_compatible_variants(
                         if let Some(path) = variant_path.strip_prefix("std::prelude::")
                             && let Some((_, path)) = path.split_once("::")
                         {
-                            return Some(path.to_string());
+                            return Some((path.to_string(), note_about_variant_field_privacy));
                         }
-                        Some(variant_path)
+                        Some((variant_path, note_about_variant_field_privacy))
                     } else {
                         None
                     }
@@ -390,10 +392,13 @@ fn suggest_compatible_variants(
 
             match &compatible_variants[..] {
                 [] => { /* No variants to format */ }
-                [variant] => {
+                [(variant, note)] => {
                     // Just a single matching variant.
                     err.multipart_suggestion_verbose(
-                        &format!("try wrapping the expression in `{variant}`"),
+                        &format!(
+                            "try wrapping the expression in `{variant}`{note}",
+                            note = note.as_deref().unwrap_or("")
+                        ),
                         vec![
                             (expr.span.shrink_to_lo(), format!("{prefix}{variant}(")),
                             (expr.span.shrink_to_hi(), ")".to_string()),
@@ -408,7 +413,7 @@ fn suggest_compatible_variants(
                             "try wrapping the expression in a variant of `{}`",
                             self.tcx.def_path_str(expected_adt.did())
                         ),
-                        compatible_variants.into_iter().map(|variant| {
+                        compatible_variants.into_iter().map(|(variant, _)| {
                             vec![
                                 (expr.span.shrink_to_lo(), format!("{prefix}{variant}(")),
                                 (expr.span.shrink_to_hi(), ")".to_string()),
@@ -433,8 +438,7 @@ fn suggest_non_zero_new_unwrap(
             // In case Option<NonZero*> is wanted, but * is provided, suggest calling new
             ty::Adt(adt, substs) if tcx.is_diagnostic_item(sym::Option, adt.did()) => {
                 // Unwrap option
-                let Some(fst) = substs.first() else { return };
-                let ty::Adt(adt, _) = fst.expect_ty().kind() else { return };
+                let ty::Adt(adt, _) = substs.type_at(0).kind() else { return };
 
                 (adt, "")
             }
@@ -458,8 +462,7 @@ fn suggest_non_zero_new_unwrap(
 
         let Some((s, _)) = map
             .iter()
-            .find(|&&(s, _)| self.tcx.is_diagnostic_item(s, adt.did()))
-            .filter(|&&(_, t)| { self.can_coerce(expr_ty, t) })
+            .find(|&&(s, t)| self.tcx.is_diagnostic_item(s, adt.did()) && self.can_coerce(expr_ty, t))
             else { return };
 
         let path = self.tcx.def_path_str(adt.non_enum_variant().def_id);