Skip to content
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

Tweak E0277 highlighting and "long type" path printing #132086

Merged
merged 3 commits into from
Oct 28, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -1835,23 +1835,32 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if impl_trait_ref.references_error() {
return false;
}
let self_ty = impl_trait_ref.self_ty().to_string();
err.highlighted_help(vec![
StringPart::normal(format!(
"the trait `{}` ",
impl_trait_ref.print_trait_sugared()
)),
StringPart::highlighted("is"),
StringPart::normal(" implemented for `"),
StringPart::highlighted(impl_trait_ref.self_ty().to_string()),
if let [TypeError::Sorts(_)] = &terrs[..] {
StringPart::normal(self_ty)
} else {
StringPart::highlighted(self_ty)
},
StringPart::normal("`"),
]);

if let [TypeError::Sorts(exp_found)] = &terrs[..] {
let exp_found = self.resolve_vars_if_possible(*exp_found);
err.help(format!(
"for that trait implementation, expected `{}`, found `{}`",
exp_found.expected, exp_found.found
));
err.highlighted_help(vec![
StringPart::normal("for that trait implementation, "),
StringPart::normal("expected `"),
StringPart::highlighted(exp_found.expected.to_string()),
StringPart::normal("`, found `"),
StringPart::highlighted(exp_found.found.to_string()),
StringPart::normal("`"),
]);
jieyouxu marked this conversation as resolved.
Show resolved Hide resolved
}

true
Expand Down Expand Up @@ -2160,6 +2169,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// First, attempt to add note to this error with an async-await-specific
// message, and fall back to regular note otherwise.
if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
let mut long_ty_file = None;
Copy link
Member

Choose a reason for hiding this comment

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

Question [PATH-PREFIX 1/2]: does it make sense to pull long_ty_file to TypeErrCtxt?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jieyouxu it would. We need to pull long_ty_file all the way up as much as possible. This was the minimal patch that would address the issue we noticed.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, I see I've ran into this exact problem before in #121739 (comment)

EDIT: posted this on the wrong review comment chain.

self.note_obligation_cause_code(
obligation.cause.body_id,
err,
Expand All @@ -2168,7 +2178,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
obligation.cause.code(),
&mut vec![],
&mut Default::default(),
&mut long_ty_file,
);
if let Some(file) = long_ty_file {
err.note(format!(
"the full name for the type has been written to '{}'",
file.display(),
));
err.note("consider using `--verbose` to print the full type name to the console");
}
self.suggest_unsized_bound_if_applicable(err, obligation);
if let Some(span) = err.span.primary_span()
&& let Some(mut diag) =
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if let ObligationCauseCode::WhereClause(..)
| ObligationCauseCode::WhereClauseInExpr(..) = code
{
let mut long_ty_file = None;
self.note_obligation_cause_code(
error.obligation.cause.body_id,
&mut diag,
Expand All @@ -313,7 +314,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
code,
&mut vec![],
&mut Default::default(),
&mut long_ty_file,
);
if let Some(file) = long_ty_file {
diag.note(format!(
"the full name for the type has been written to '{}'",
file.display(),
Comment on lines +321 to +322
Copy link
Member

Choose a reason for hiding this comment

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

Discussion [PATH-PREFIX 2/2]: I believe this is one of the places where we will leak the path prefix even with -Z remap-path-prefix or -Z remap-cwd-prefix or -Z remap-path-scope=diagnostics/all. Should the file path here also go through those? If it's possible to pull the long_ty_file to TypeErrCtxt, would it be better if handling path prefix remapping happens there too?

To be clear, I'm not saying this should be done in this PR, just as a remark that this can be a potential issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a good point. We should have a single method for printing the long type paths note, properly handling that case.

));
diag.note(
"consider using `--verbose` to print the full type name to the console",
);
}
}
diag.emit()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
obligation.cause.span,
suggest_increasing_limit,
|err| {
let mut long_ty_file = None;
self.note_obligation_cause_code(
obligation.cause.body_id,
err,
Expand All @@ -152,7 +153,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
obligation.cause.code(),
&mut vec![],
&mut Default::default(),
&mut long_ty_file,
);
if let Some(file) = long_ty_file {
err.note(format!(
"the full name for the type has been written to '{}'",
file.display(),
));
err.note(
"consider using `--verbose` to print the full type name to the console",
);
}
},
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::assert_matches::debug_assert_matches;
use std::borrow::Cow;
use std::iter;
use std::path::PathBuf;

use itertools::{EitherOrBoth, Itertools};
use rustc_data_structures::fx::FxHashSet;
Expand Down Expand Up @@ -2703,6 +2704,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// Add a note for the item obligation that remains - normally a note pointing to the
// bound that introduced the obligation (e.g. `T: Send`).
debug!(?next_code);
let mut long_ty_file = None;
self.note_obligation_cause_code(
obligation.cause.body_id,
err,
Expand All @@ -2711,6 +2713,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
next_code.unwrap(),
&mut Vec::new(),
&mut Default::default(),
&mut long_ty_file,
);
}

Expand All @@ -2723,11 +2726,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
cause_code: &ObligationCauseCode<'tcx>,
obligated_types: &mut Vec<Ty<'tcx>>,
seen_requirements: &mut FxHashSet<DefId>,
long_ty_file: &mut Option<PathBuf>,
) where
T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>,
{
let mut long_ty_file = None;

let tcx = self.tcx;
let predicate = predicate.upcast(tcx);
let suggest_remove_deref = |err: &mut Diag<'_, G>, expr: &hir::Expr<'_>| {
Expand Down Expand Up @@ -2957,9 +2959,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
ObligationCauseCode::Coercion { source, target } => {
let source =
tcx.short_ty_string(self.resolve_vars_if_possible(source), &mut long_ty_file);
tcx.short_ty_string(self.resolve_vars_if_possible(source), long_ty_file);
let target =
tcx.short_ty_string(self.resolve_vars_if_possible(target), &mut long_ty_file);
tcx.short_ty_string(self.resolve_vars_if_possible(target), long_ty_file);
err.note(with_forced_trimmed_paths!(format!(
"required for the cast from `{source}` to `{target}`",
)));
Expand Down Expand Up @@ -3249,7 +3251,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
};

if !is_upvar_tys_infer_tuple {
let ty_str = tcx.short_ty_string(ty, &mut long_ty_file);
let ty_str = tcx.short_ty_string(ty, long_ty_file);
let msg = format!("required because it appears within the type `{ty_str}`");
match ty.kind() {
ty::Adt(def, _) => match tcx.opt_item_ident(def.did()) {
Expand Down Expand Up @@ -3327,6 +3329,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
&data.parent_code,
obligated_types,
seen_requirements,
long_ty_file,
)
});
} else {
Expand All @@ -3339,6 +3342,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
cause_code.peel_derives(),
obligated_types,
seen_requirements,
long_ty_file,
)
});
}
Expand All @@ -3347,8 +3351,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let mut parent_trait_pred =
self.resolve_vars_if_possible(data.derived.parent_trait_pred);
let parent_def_id = parent_trait_pred.def_id();
let self_ty_str = tcx
.short_ty_string(parent_trait_pred.skip_binder().self_ty(), &mut long_ty_file);
let self_ty_str =
tcx.short_ty_string(parent_trait_pred.skip_binder().self_ty(), long_ty_file);
let trait_name = parent_trait_pred.print_modifiers_and_trait_path().to_string();
let msg = format!("required for `{self_ty_str}` to implement `{trait_name}`");
let mut is_auto_trait = false;
Expand Down Expand Up @@ -3444,10 +3448,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
count,
pluralize!(count)
));
let self_ty = tcx.short_ty_string(
parent_trait_pred.skip_binder().self_ty(),
&mut long_ty_file,
);
let self_ty = tcx
.short_ty_string(parent_trait_pred.skip_binder().self_ty(), long_ty_file);
err.note(format!(
"required for `{self_ty}` to implement `{}`",
parent_trait_pred.print_modifiers_and_trait_path()
Expand All @@ -3463,6 +3465,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
&data.parent_code,
obligated_types,
seen_requirements,
long_ty_file,
)
});
}
Expand All @@ -3479,6 +3482,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
&data.parent_code,
obligated_types,
seen_requirements,
long_ty_file,
)
});
}
Expand All @@ -3493,6 +3497,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
nested,
obligated_types,
seen_requirements,
long_ty_file,
)
});
let mut multispan = MultiSpan::from(span);
Expand Down Expand Up @@ -3523,6 +3528,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
parent_code,
obligated_types,
seen_requirements,
long_ty_file,
)
});
}
Expand Down Expand Up @@ -3562,7 +3568,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
ObligationCauseCode::OpaqueReturnType(expr_info) => {
if let Some((expr_ty, hir_id)) = expr_info {
let expr_ty = self.tcx.short_ty_string(expr_ty, &mut long_ty_file);
let expr_ty = self.tcx.short_ty_string(expr_ty, long_ty_file);
let expr = self.infcx.tcx.hir().expect_expr(hir_id);
err.span_label(
expr.span,
Expand All @@ -3574,14 +3580,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
}

if let Some(file) = long_ty_file {
err.note(format!(
"the full name for the type has been written to '{}'",
file.display(),
));
err.note("consider using `--verbose` to print the full type name to the console");
}
}

#[instrument(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//@ only-linux
//@ compile-flags: --error-format=human --color=always
//@ error-pattern: the trait bound

trait Foo<T>: Bar<T> {}

trait Bar<T> {}

struct Struct;

impl<T, K> Foo<K> for T where T: Bar<K>
{}

impl<'a> Bar<()> for Struct {}

fn foo() -> impl Foo<i32> {
Struct
}

fn main() {}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading