Rollup merge of #156676 - qaijuang:diagnostics-do-not-recommend-span, r=chenyukang

Preserve spans when hiding do_not_recommend impls

Fixes rust-lang/rust#156475 by restoring the root span only when the current refined span has wandered outside the parent obligation.
This commit is contained in:
Jonathan Brouwer
2026-05-18 03:19:45 +02:00
committed by GitHub
5 changed files with 96 additions and 3 deletions
@@ -816,6 +816,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
pub(super) fn apply_do_not_recommend(
&self,
obligation: &mut PredicateObligation<'tcx>,
root_obligation: &PredicateObligation<'tcx>,
) -> bool {
let mut base_cause = obligation.cause.code().clone();
let mut applied_do_not_recommend = false;
@@ -823,6 +824,13 @@ pub(super) fn apply_do_not_recommend(
if let ObligationCauseCode::ImplDerived(ref c) = base_cause {
if self.tcx.do_not_recommend_impl(c.impl_or_alias_def_id) {
let code = (*c.derived.parent_code).clone();
// Keep more precise spans that still point within the parent obligation,
// but do not let hidden impl details move the span outside of it.
if code == *root_obligation.cause.code()
&& !root_obligation.cause.span.contains(obligation.cause.span)
{
obligation.cause.span = root_obligation.cause.span;
}
obligation.cause.map_code(|_| code);
obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx);
applied_do_not_recommend = true;
@@ -298,7 +298,7 @@ fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuara
error.code,
FulfillmentErrorCode::Select(crate::traits::SelectionError::Unimplemented)
| FulfillmentErrorCode::Project(_)
) && self.apply_do_not_recommend(&mut error.obligation)
) && self.apply_do_not_recommend(&mut error.obligation, &error.root_obligation)
{
error.code = FulfillmentErrorCode::Select(SelectionError::Unimplemented);
}
@@ -12,6 +12,26 @@ LL | impl AsExpression<Text> for &'_ str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: for that trait implementation, expected `Text`, found `Integer`
error: aborting due to 1 previous error
error[E0277]: the trait bound `X: A` is not satisfied
--> $DIR/as_expression.rs:60:15
|
LL | X.start().foo().finish();
| ^^^ unsatisfied trait bound
|
help: the trait `A` is not implemented for `X`
--> $DIR/as_expression.rs:70:1
|
LL | struct X;
| ^^^^^^^^
note: required by a bound in `Ext::foo`
--> $DIR/as_expression.rs:79:23
|
LL | fn foo(self) -> Self
| --- required by a bound in this associated function
LL | where
LL | Self: Sized + A;
| ^ required by this bound in `Ext::foo`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.
@@ -22,6 +22,26 @@ LL | where
LL | T: AsExpression<Self::SqlType>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check`
error: aborting due to 1 previous error
error[E0277]: the trait bound `X: A` is not satisfied
--> $DIR/as_expression.rs:60:15
|
LL | X.start().foo().finish();
| ^^^ unsatisfied trait bound
|
help: the trait `A` is not implemented for `X`
--> $DIR/as_expression.rs:70:1
|
LL | struct X;
| ^^^^^^^^
note: required by a bound in `Ext::foo`
--> $DIR/as_expression.rs:79:23
|
LL | fn foo(self) -> Self
| --- required by a bound in this associated function
LL | where
LL | Self: Sized + A;
| ^ required by this bound in `Ext::foo`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.
@@ -55,4 +55,49 @@ impl<T> Foo for T where T: Expression {}
fn main() {
SelectInt.check("bar");
//~^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied
// Regression test for https://github.com/rust-lang/rust/issues/156475.
X.start().foo().finish();
//~^ ERROR the trait bound `X: A` is not satisfied
}
trait A {}
trait B {}
#[diagnostic::do_not_recommend]
impl<T: B> A for T {}
struct X;
trait Start {
fn start(self) -> Self;
}
trait Ext {
fn foo(self) -> Self
where
Self: Sized + A;
}
trait Finish {
fn finish(self);
}
impl<T> Start for T {
fn start(self) -> Self {
self
}
}
impl<T> Ext for T {
fn foo(self) -> Self
where
Self: Sized + A,
{
self
}
}
impl<T> Finish for T {
fn finish(self) {}
}