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:
commit
46a033958a
4 changed files with 75 additions and 8 deletions
|
@ -414,7 +414,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
|
||||||
let trait_predicate = bound_predicate.rebind(trait_predicate);
|
let trait_predicate = bound_predicate.rebind(trait_predicate);
|
||||||
let trait_predicate = self.resolve_vars_if_possible(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
|
// 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
|
// most general case ("X doesn't implement Pattern<'_>") over the case that
|
||||||
|
@ -996,12 +995,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
err.emit()
|
err.emit()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_do_not_recommend(
|
fn apply_do_not_recommend(&self, obligation: &mut PredicateObligation<'tcx>) -> bool {
|
||||||
&self,
|
|
||||||
mut trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
|
|
||||||
obligation: &'_ mut PredicateObligation<'tcx>,
|
|
||||||
) -> ty::Binder<'tcx, ty::TraitPredicate<'tcx>> {
|
|
||||||
let mut base_cause = obligation.cause.code().clone();
|
let mut base_cause = obligation.cause.code().clone();
|
||||||
|
let mut applied_do_not_recommend = false;
|
||||||
loop {
|
loop {
|
||||||
if let ObligationCauseCode::ImplDerived(ref c) = base_cause {
|
if let ObligationCauseCode::ImplDerived(ref c) = base_cause {
|
||||||
if self.tcx.has_attrs_with_path(
|
if self.tcx.has_attrs_with_path(
|
||||||
|
@ -1011,7 +1007,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
let code = (*c.derived.parent_code).clone();
|
let code = (*c.derived.parent_code).clone();
|
||||||
obligation.cause.map_code(|_| code);
|
obligation.cause.map_code(|_| code);
|
||||||
obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx);
|
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() {
|
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(
|
fn emit_specialized_closure_kind_error(
|
||||||
|
@ -1521,6 +1517,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed {
|
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 {
|
match error.code {
|
||||||
FulfillmentErrorCode::Select(ref selection_error) => self.report_selection_error(
|
FulfillmentErrorCode::Select(ref selection_error) => self.report_selection_error(
|
||||||
error.obligation.clone(),
|
error.obligation.clone(),
|
||||||
|
|
|
@ -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`.
|
|
@ -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`.
|
|
@ -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]
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue