Skip to content

Use tcx.short_string() in more diagnostics #144039

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1129,9 +1129,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
);
}
} else {
let trait_ =
tcx.short_string(bound.print_only_trait_path(), err.long_ty_path());
err.note(format!(
"associated {assoc_kind_str} `{assoc_ident}` could derive from `{}`",
bound.print_only_trait_path(),
"associated {assoc_kind_str} `{assoc_ident}` could derive from `{trait_}`",
));
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ hir_typeck_lossy_provenance_ptr2int =
.suggestion = use `.addr()` to obtain the address of a pointer
.help = if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead

hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}`
hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty}`

hir_typeck_naked_asm_outside_naked_fn =
the `naked_asm!` macro can only be used in functions marked with `#[unsafe(naked)]`
Expand All @@ -184,7 +184,7 @@ hir_typeck_never_type_fallback_flowing_into_unsafe_path = never type fallback af
hir_typeck_never_type_fallback_flowing_into_unsafe_union_field = never type fallback affects this union access
.help = specify the type explicitly

hir_typeck_no_associated_item = no {$item_kind} named `{$item_ident}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method ->
hir_typeck_no_associated_item = no {$item_kind} named `{$item_ident}` found for {$ty_prefix} `{$ty}`{$trait_missing_method ->
[true] {""}
*[other] {" "}in the current scope
}
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_hir_typeck/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,11 @@ pub(crate) enum ExplicitDestructorCallSugg {

#[derive(Diagnostic)]
#[diag(hir_typeck_missing_parentheses_in_range, code = E0689)]
pub(crate) struct MissingParenthesesInRange {
pub(crate) struct MissingParenthesesInRange<'tcx> {
#[primary_span]
#[label(hir_typeck_missing_parentheses_in_range)]
pub span: Span,
pub ty_str: String,
pub ty: Ty<'tcx>,
pub method_name: String,
#[subdiagnostic]
pub add_missing_parentheses: Option<AddMissingParenthesesInRange>,
Expand Down Expand Up @@ -828,13 +828,13 @@ pub(crate) struct UnlabeledCfInWhileCondition<'a> {

#[derive(Diagnostic)]
#[diag(hir_typeck_no_associated_item, code = E0599)]
pub(crate) struct NoAssociatedItem {
pub(crate) struct NoAssociatedItem<'tcx> {
#[primary_span]
pub span: Span,
pub item_kind: &'static str,
pub item_ident: Ident,
pub ty_prefix: Cow<'static, str>,
pub ty_str: String,
pub ty: Ty<'tcx>,
pub trait_missing_method: bool,
}

Expand Down
126 changes: 60 additions & 66 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,8 +375,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

fn suggest_missing_writer(&self, rcvr_ty: Ty<'tcx>, rcvr_expr: &hir::Expr<'tcx>) -> Diag<'_> {
let mut file = None;
fn suggest_missing_writer(
&self,
rcvr_ty: Ty<'tcx>,
rcvr_expr: &hir::Expr<'tcx>,
mut file: Option<PathBuf>,
) -> Diag<'_> {
let mut err = struct_span_code_err!(
self.dcx(),
rcvr_expr.span,
Expand All @@ -402,7 +406,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
self_source: SelfSource<'tcx>,
method_name: Ident,
ty_str_reported: &str,
unsatisfied_predicates: &[(
ty::Predicate<'tcx>,
Option<ty::Predicate<'tcx>>,
Option<ObligationCause<'tcx>>,
)],
ty: Ty<'tcx>,
err: &mut Diag<'_>,
) {
#[derive(Debug)]
Expand Down Expand Up @@ -565,17 +574,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut span = MultiSpan::from_span(sugg_let.span);
span.push_span_label(sugg_let.span,
format!("`{rcvr_name}` of type `{self_ty}` that has method `{method_name}` defined earlier here"));

// Don't show generic arguments when the method can't be found in any implementation (#81576).
let mut ty_str = None;
if let ty::Adt(_, generics) = ty.kind() {
if generics.len() > 0 {
let mut autoderef = self.autoderef(DUMMY_SP, ty).silence_errors();
let candidate_found = autoderef.any(|(ty, _)| {
if let ty::Adt(adt_def, _) = ty.kind() {
self.tcx.inherent_impls(adt_def.did()).into_iter().any(
|def_id| {
self.associated_value(*def_id, method_name).is_some()
},
)
} else {
false
}
});
let has_deref = autoderef.step_count() > 0;
if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
let t = with_forced_trimmed_paths!(ty.to_string());
if let Some((path_string, _)) = t.split_once('<') {
ty_str = Some(path_string.to_string());
}
}
}
}
Comment on lines +578 to +602
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is moved code from 656.


let ty =
ty_str.unwrap_or_else(|| self.tcx.short_string(ty, err.long_ty_path()));
span.push_span_label(
self.tcx.hir_span(recv_id),
format!(
"earlier `{rcvr_name}` shadowed here with type `{ty_str_reported}`"
),
format!("earlier `{rcvr_name}` shadowed here with type `{ty}`"),
);
err.span_note(
span,
format!(
"there's an earlier shadowed binding `{rcvr_name}` of type `{self_ty}` \
that has method `{method_name}` available"
that has method `{method_name}` available"
),
);
}
Expand All @@ -601,15 +637,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let tcx = self.tcx;
let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
let mut ty_file = None;
let (ty_str, short_ty_str) =
if trait_missing_method && let ty::Dynamic(predicates, _, _) = rcvr_ty.kind() {
(predicates.to_string(), with_forced_trimmed_paths!(predicates.to_string()))
} else {
(
tcx.short_string(rcvr_ty, &mut ty_file),
with_forced_trimmed_paths!(rcvr_ty.to_string()),
)
};
let is_method = mode == Mode::MethodCall;
let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
let similar_candidate = no_match_data.similar_candidate;
Expand All @@ -628,15 +655,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// We could pass the file for long types into these two, but it isn't strictly necessary
// given how targeted they are.
if let Err(guar) = self.report_failed_method_call_on_range_end(
tcx,
rcvr_ty,
source,
span,
item_ident,
&short_ty_str,
&mut ty_file,
) {
if let Err(guar) =
self.report_failed_method_call_on_range_end(tcx, rcvr_ty, source, span, item_ident)
{
return guar;
}
if let Err(guar) = self.report_failed_method_call_on_numerical_infer_var(
Expand All @@ -646,43 +667,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span,
item_kind,
item_ident,
&short_ty_str,
&mut ty_file,
) {
return guar;
}
span = item_ident.span;

// Don't show generic arguments when the method can't be found in any implementation (#81576).
let mut ty_str_reported = ty_str.clone();
if let ty::Adt(_, generics) = rcvr_ty.kind() {
if generics.len() > 0 {
let mut autoderef = self.autoderef(span, rcvr_ty).silence_errors();
let candidate_found = autoderef.any(|(ty, _)| {
if let ty::Adt(adt_def, _) = ty.kind() {
self.tcx
.inherent_impls(adt_def.did())
.into_iter()
.any(|def_id| self.associated_value(*def_id, item_ident).is_some())
} else {
false
}
});
let has_deref = autoderef.step_count() > 0;
if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
if let Some((path_string, _)) = ty_str.split_once('<') {
ty_str_reported = path_string.to_string();
}
}
}
}

let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| {
tcx.is_diagnostic_item(sym::write_macro, def_id)
|| tcx.is_diagnostic_item(sym::writeln_macro, def_id)
}) && item_ident.name == sym::write_fmt;
let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source {
self.suggest_missing_writer(rcvr_ty, rcvr_expr)
self.suggest_missing_writer(rcvr_ty, rcvr_expr, ty_file)
} else {
let mut err = self.dcx().create_err(NoAssociatedItem {
span,
Expand All @@ -694,15 +690,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
rcvr_ty.prefix_string(self.tcx)
},
ty_str: ty_str_reported.clone(),
ty: rcvr_ty,
trait_missing_method,
});

if is_method {
self.suggest_use_shadowed_binding_with_method(
source,
item_ident,
&ty_str_reported,
&unsatisfied_predicates,
rcvr_ty,
&mut err,
);
}
Expand Down Expand Up @@ -733,6 +730,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

err
};

if tcx.sess.source_map().is_multiline(sugg_span) {
err.span_label(sugg_span.with_hi(span.lo()), "");
}
Expand All @@ -749,6 +747,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

if tcx.ty_is_opaque_future(rcvr_ty) && item_ident.name == sym::poll {
let ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path());
err.help(format!(
"method `poll` found on `Pin<&mut {ty_str}>`, \
see documentation for `std::pin::Pin`"
Expand Down Expand Up @@ -1338,14 +1337,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let OnUnimplementedNote { message, label, notes, .. } = self
.err_ctxt()
.on_unimplemented_note(trait_ref, &obligation, &mut ty_file);
.on_unimplemented_note(trait_ref, &obligation, err.long_ty_path());
(message, label, notes)
})
.unwrap()
} else {
(None, None, Vec::new())
};
let primary_message = primary_message.unwrap_or_else(|| {
let ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path());
format!(
"the {item_kind} `{item_ident}` exists for {actual_prefix} `{ty_str}`, \
but its trait bounds were not satisfied"
Expand Down Expand Up @@ -1408,6 +1408,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut find_candidate_for_method = false;

let mut label_span_not_found = |err: &mut Diag<'_>| {
let ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path());
if unsatisfied_predicates.is_empty() {
err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
let is_string_or_ref_str = match rcvr_ty.kind() {
Expand Down Expand Up @@ -2519,8 +2520,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
source: SelfSource<'tcx>,
span: Span,
item_name: Ident,
ty_str: &str,
long_ty_path: &mut Option<PathBuf>,
) -> Result<(), ErrorGuaranteed> {
if let SelfSource::MethodCall(expr) = source {
for (_, parent) in tcx.hir_parent_iter(expr.hir_id).take(5) {
Expand Down Expand Up @@ -2582,18 +2581,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
if pick.is_ok() {
let range_span = parent_expr.span.with_hi(expr.span.hi());
let mut err = self.dcx().create_err(errors::MissingParenthesesInRange {
return Err(self.dcx().emit_err(errors::MissingParenthesesInRange {
span,
ty_str: ty_str.to_string(),
ty: actual,
method_name: item_name.as_str().to_string(),
add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
func_name: item_name.name.as_str().to_string(),
left: range_span.shrink_to_lo(),
right: range_span.shrink_to_hi(),
}),
});
*err.long_ty_path() = long_ty_path.take();
return Err(err.emit());
}));
}
}
}
Expand All @@ -2609,7 +2606,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: Span,
item_kind: &str,
item_name: Ident,
ty_str: &str,
long_ty_path: &mut Option<PathBuf>,
) -> Result<(), ErrorGuaranteed> {
let found_candidate = all_traits(self.tcx)
Expand Down Expand Up @@ -2642,14 +2638,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& !actual.has_concrete_skeleton()
&& let SelfSource::MethodCall(expr) = source
{
let ty_str = self.tcx.short_string(actual, long_ty_path);
let mut err = struct_span_code_err!(
self.dcx(),
span,
E0689,
"can't call {} `{}` on ambiguous numeric type `{}`",
item_kind,
item_name,
ty_str
"can't call {item_kind} `{item_name}` on ambiguous numeric type `{ty_str}`"
);
*err.long_ty_path() = long_ty_path.take();
let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3063,7 +3063,7 @@ impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> {
}
}

#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)]
pub struct TraitPredPrintModifiersAndPath<'tcx>(ty::TraitPredicate<'tcx>);

impl<'tcx> fmt::Debug for TraitPredPrintModifiersAndPath<'tcx> {
Expand Down
Loading
Loading