diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 47ff748547a..07bf5d90b55 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1699,6 +1699,8 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option TyCtxt<'tcx> { pub fn impl_polarity(self, def_id: impl IntoQueryParam) -> ty::ImplPolarity { self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity) } + + /// Whether this is a trait implementation that has `#[diagnostic::do_not_recommend]` + pub fn do_not_recommend_impl(self, def_id: DefId) -> bool { + matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true }) + && self.impl_trait_header(def_id).is_some_and(|header| header.do_not_recommend) + } } /// Parameter attributes that can only be determined by examining the body of a function instead diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9736428e6f7..69b194045ad 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -262,6 +262,7 @@ pub struct ImplTraitHeader<'tcx> { pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>, pub polarity: ImplPolarity, pub safety: hir::Safety, + pub do_not_recommend: bool, } #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 1cee82f04ea..7f7de4a963b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -687,10 +687,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut applied_do_not_recommend = false; loop { if let ObligationCauseCode::ImplDerived(ref c) = base_cause { - if self.tcx.has_attrs_with_path( - c.impl_or_alias_def_id, - &[sym::diagnostic, sym::do_not_recommend], - ) { + if self.tcx.do_not_recommend_impl(c.impl_or_alias_def_id) { let code = (*c.derived.parent_code).clone(); obligation.cause.map_code(|_| code); obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx); @@ -1630,11 +1627,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .tcx .all_impls(def_id) // ignore `do_not_recommend` items - .filter(|def_id| { - !self - .tcx - .has_attrs_with_path(*def_id, &[sym::diagnostic, sym::do_not_recommend]) - }) + .filter(|def_id| !self.tcx.do_not_recommend_impl(*def_id)) // Ignore automatically derived impls and `!Trait` impls. .filter_map(|def_id| self.tcx.impl_trait_header(def_id)) .filter_map(|header| { @@ -1904,12 +1897,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let impl_candidates = impl_candidates .into_iter() .cloned() - .filter(|cand| { - !self.tcx.has_attrs_with_path( - cand.impl_def_id, - &[sym::diagnostic, sym::do_not_recommend], - ) - }) + .filter(|cand| !self.tcx.do_not_recommend_impl(cand.impl_def_id)) .collect::>(); let def_id = trait_ref.def_id(); diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 49fa775a0a1..de8951ef720 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -13,7 +13,6 @@ use rustc_middle::bug; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt}; use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as _}; -use rustc_span::symbol::sym; use super::delegate::SolverDelegate; use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; @@ -440,10 +439,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { source: CandidateSource::Impl(impl_def_id), result: _, } = candidate.kind() - && goal - .infcx() - .tcx - .has_attrs_with_path(impl_def_id, &[sym::diagnostic, sym::do_not_recommend]) + && goal.infcx().tcx.do_not_recommend_impl(impl_def_id) { return ControlFlow::Break(self.obligation.clone()); }