Skip to content

Commit ffe6487

Browse files
committed
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.
1 parent 7516912 commit ffe6487

File tree

4 files changed

+70
-8
lines changed

4 files changed

+70
-8
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
414414
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
415415
let trait_predicate = bound_predicate.rebind(trait_predicate);
416416
let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
417-
let trait_predicate = self.apply_do_not_recommend(trait_predicate, &mut obligation);
418417

419418
// Let's use the root obligation as the main message, when we care about the
420419
// most general case ("X doesn't implement Pattern<'_>") over the case that
@@ -996,12 +995,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
996995
err.emit()
997996
}
998997

999-
fn apply_do_not_recommend(
1000-
&self,
1001-
mut trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
1002-
obligation: &'_ mut PredicateObligation<'tcx>,
1003-
) -> ty::Binder<'tcx, ty::TraitPredicate<'tcx>> {
998+
fn apply_do_not_recommend(&self, obligation: &'_ mut PredicateObligation<'tcx>) -> bool {
1004999
let mut base_cause = obligation.cause.code().clone();
1000+
let mut applied_do_not_recommend = false;
10051001
loop {
10061002
if let ObligationCauseCode::ImplDerived(ref c) = base_cause {
10071003
if self.tcx.has_attrs_with_path(
@@ -1011,7 +1007,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
10111007
let code = (*c.derived.parent_code).clone();
10121008
obligation.cause.map_code(|_| code);
10131009
obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx);
1014-
trait_predicate = c.derived.parent_trait_pred.clone();
1010+
applied_do_not_recommend = true;
10151011
}
10161012
}
10171013
if let Some((parent_cause, _parent_pred)) = base_cause.parent() {
@@ -1021,7 +1017,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
10211017
}
10221018
}
10231019

1024-
trait_predicate
1020+
applied_do_not_recommend
10251021
}
10261022

10271023
fn emit_specialized_closure_kind_error(
@@ -1521,6 +1517,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
15211517

15221518
#[instrument(skip(self), level = "debug")]
15231519
fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed {
1520+
let mut error = FulfillmentError {
1521+
obligation: error.obligation.clone(),
1522+
code: error.code.clone(),
1523+
root_obligation: error.root_obligation.clone(),
1524+
};
1525+
if self.apply_do_not_recommend(&mut error.obligation) {
1526+
error.code = FulfillmentErrorCode::Select(SelectionError::Unimplemented);
1527+
}
1528+
15241529
match error.code {
15251530
FulfillmentErrorCode::Select(ref selection_error) => self.report_selection_error(
15261531
error.obligation.clone(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0277]: Very important message!
2+
--> $DIR/type_mismatch.rs:25:14
3+
|
4+
LL | verify::<u8>();
5+
| ^^ the trait `TheImportantOne` is not implemented for `u8`
6+
|
7+
note: required by a bound in `verify`
8+
--> $DIR/type_mismatch.rs:22:14
9+
|
10+
LL | fn verify<T: TheImportantOne>() {}
11+
| ^^^^^^^^^^^^^^^ required by this bound in `verify`
12+
13+
error: aborting due to 1 previous error
14+
15+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0277]: Very important message!
2+
--> $DIR/type_mismatch.rs:25:14
3+
|
4+
LL | verify::<u8>();
5+
| ^^ the trait `TheImportantOne` is not implemented for `u8`
6+
|
7+
note: required by a bound in `verify`
8+
--> $DIR/type_mismatch.rs:22:14
9+
|
10+
LL | fn verify<T: TheImportantOne>() {}
11+
| ^^^^^^^^^^^^^^^ required by this bound in `verify`
12+
13+
error: aborting due to 1 previous error
14+
15+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//@ revisions: current next
2+
//@ ignore-compare-mode-next-solver (explicit revisions)
3+
//@[next] compile-flags: -Znext-solver
4+
5+
#![feature(do_not_recommend)]
6+
7+
#[diagnostic::on_unimplemented(message = "Very important message!")]
8+
trait TheImportantOne {}
9+
10+
trait ImplementationDetail {
11+
type Restriction;
12+
}
13+
14+
#[diagnostic::do_not_recommend]
15+
impl<T: ImplementationDetail<Restriction = ()>> TheImportantOne for T {}
16+
17+
// Comment out this `impl` to show the expected error message.
18+
impl ImplementationDetail for u8 {
19+
type Restriction = u8;
20+
}
21+
22+
fn verify<T: TheImportantOne>() {}
23+
24+
pub fn main() {
25+
verify::<u8>();
26+
//~^ERROR: Very important message! [E0277]
27+
}

0 commit comments

Comments
 (0)