}
}
- let compatible_variants: Vec<String> = expected_adt
+ let compatible_variants: Vec<(String, Option<String>)> = expected_adt
.variants()
.iter()
.filter(|variant| {
.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 =
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
}
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()),
"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()),
// 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, "")
}
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);