diff options
| author | Georg Semmler <github@weiznich.de> | 2024-05-04 14:26:24 +0200 |
|---|---|---|
| committer | Georg Semmler <github@weiznich.de> | 2024-05-19 08:29:27 +0200 |
| commit | 9b45cfdbdde020682d167ffd9f512fd8401d8cfe (patch) | |
| tree | 2a40ffc0d41a681900e75d00ebeeff8a554e261f /compiler/rustc_trait_selection/src/traits | |
| parent | bfa3635df920454cdf03f6d268dfaac769375df3 (diff) | |
| download | rust-9b45cfdbdde020682d167ffd9f512fd8401d8cfe.tar.gz rust-9b45cfdbdde020682d167ffd9f512fd8401d8cfe.zip | |
Actually use the `#[do_not_recommend]` attribute if present
This change tweaks the error message generation to actually use the
`#[do_not_recommend]` attribute if present by just skipping the marked
trait impl in favour of the parent impl. It also adds a compile test for
this behaviour. Without this change the test would output the following
error:
```
error[E0277]: the trait bound `&str: Expression` is not satisfied
--> /home/weiznich/Documents/rust/rust/tests/ui/diagnostic_namespace/do_not_recommend.rs:53:15
|
LL | SelectInt.check("bar");
| ^^^^^ the trait `Expression` is not implemented for `&str`, which is required by `&str: AsExpression<Integer>`
|
= help: the following other types implement trait `Expression`:
Bound<T>
SelectInt
note: required for `&str` to implement `AsExpression<Integer>`
--> /home/weiznich/Documents/rust/rust/tests/ui/diagnostic_namespace/do_not_recommend.rs:26:13
|
LL | impl<T, ST> AsExpression<ST> for T
| ^^^^^^^^^^^^^^^^ ^
LL | where
LL | T: Expression<SqlType = ST>,
| ------------------------ unsatisfied trait bound introduced here
```
Note how that mentions `&str: Expression` before and now mentions `&str:
AsExpression<Integer>` instead which is much more helpful for users.
Open points for further changes before stabilization:
* We likely want to move the attribute to the `#[diagnostic]` namespace
to relax the guarantees given?
* How does it interact with the new trait solver?
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index d693bac90dc..20dfb5e6642 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -422,6 +422,7 @@ 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 @@ -1003,6 +1004,31 @@ 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>> { + let mut base_cause = obligation.cause.code().clone(); + loop { + if let ObligationCauseCode::ImplDerived(ref c) = base_cause { + if self.tcx.has_attr(c.impl_or_alias_def_id, sym::do_not_recommend) { + 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(); + } + } + if let Some((parent_cause, _parent_pred)) = base_cause.parent() { + base_cause = parent_cause.clone(); + } else { + break; + } + } + + trait_predicate + } + fn emit_specialized_closure_kind_error( &self, obligation: &PredicateObligation<'tcx>, |
