Rollup merge of #125717 - weiznich:move/do_not_recommend_to_diganostic_namespace, r=compiler-errors

Refactor `#[diagnostic::do_not_recommend]` support

This commit refactors the `#[do_not_recommend]` support in the old parser to also apply to projection errors and not only to selection errors. This allows the attribute to be used more widely.

Part of #51992

r? `@compiler-errors`

<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.

This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using

    r​? <reviewer name>
-->
This commit is contained in:
Michael Goulet 2024-06-04 08:52:12 -04:00 committed by GitHub
commit 46a033958a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 75 additions and 8 deletions

View File

@ -414,7 +414,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
let trait_predicate = bound_predicate.rebind(trait_predicate);
let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
let trait_predicate = self.apply_do_not_recommend(trait_predicate, &mut obligation);
// Let's use the root obligation as the main message, when we care about the
// most general case ("X doesn't implement Pattern<'_>") over the case that
@ -996,12 +995,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
err.emit()
}
fn apply_do_not_recommend(
&self,
mut trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
obligation: &'_ mut PredicateObligation<'tcx>,
) -> ty::Binder<'tcx, ty::TraitPredicate<'tcx>> {
fn apply_do_not_recommend(&self, obligation: &mut PredicateObligation<'tcx>) -> bool {
let mut base_cause = obligation.cause.code().clone();
let mut applied_do_not_recommend = false;
loop {
if let ObligationCauseCode::ImplDerived(ref c) = base_cause {
if self.tcx.has_attrs_with_path(
@ -1011,7 +1007,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let code = (*c.derived.parent_code).clone();
obligation.cause.map_code(|_| code);
obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx);
trait_predicate = c.derived.parent_trait_pred.clone();
applied_do_not_recommend = true;
}
}
if let Some((parent_cause, _parent_pred)) = base_cause.parent() {
@ -1021,7 +1017,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}
trait_predicate
applied_do_not_recommend
}
fn emit_specialized_closure_kind_error(
@ -1521,6 +1517,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
#[instrument(skip(self), level = "debug")]
fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed {
let mut error = FulfillmentError {
obligation: error.obligation.clone(),
code: error.code.clone(),
root_obligation: error.root_obligation.clone(),
};
if matches!(
error.code,
FulfillmentErrorCode::Select(crate::traits::SelectionError::Unimplemented)
| FulfillmentErrorCode::Project(_)
) && self.apply_do_not_recommend(&mut error.obligation)
{
error.code = FulfillmentErrorCode::Select(SelectionError::Unimplemented);
}
match error.code {
FulfillmentErrorCode::Select(ref selection_error) => self.report_selection_error(
error.obligation.clone(),

View File

@ -0,0 +1,15 @@
error[E0277]: Very important message!
--> $DIR/type_mismatch.rs:25:14
|
LL | verify::<u8>();
| ^^ the trait `TheImportantOne` is not implemented for `u8`
|
note: required by a bound in `verify`
--> $DIR/type_mismatch.rs:22:14
|
LL | fn verify<T: TheImportantOne>() {}
| ^^^^^^^^^^^^^^^ required by this bound in `verify`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,15 @@
error[E0277]: Very important message!
--> $DIR/type_mismatch.rs:25:14
|
LL | verify::<u8>();
| ^^ the trait `TheImportantOne` is not implemented for `u8`
|
note: required by a bound in `verify`
--> $DIR/type_mismatch.rs:22:14
|
LL | fn verify<T: TheImportantOne>() {}
| ^^^^^^^^^^^^^^^ required by this bound in `verify`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,27 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
#![feature(do_not_recommend)]
#[diagnostic::on_unimplemented(message = "Very important message!")]
trait TheImportantOne {}
trait ImplementationDetail {
type Restriction;
}
#[diagnostic::do_not_recommend]
impl<T: ImplementationDetail<Restriction = ()>> TheImportantOne for T {}
// Comment out this `impl` to show the expected error message.
impl ImplementationDetail for u8 {
type Restriction = u8;
}
fn verify<T: TheImportantOne>() {}
pub fn main() {
verify::<u8>();
//~^ERROR: Very important message! [E0277]
}