hir_analysis: add #![rustc_no_implicit_bounds]

Adds a new `rustc_attrs` attribute that stops rustc from adding any
default bounds. Useful for tests where default bounds just add noise and
make debugging harder.
This commit is contained in:
David Wood 2025-06-18 12:23:35 +00:00
parent 27733d46d7
commit b93020257e
No known key found for this signature in database
3 changed files with 16 additions and 9 deletions

View file

@ -1108,6 +1108,10 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
TEST, rustc_insignificant_dtor, Normal, template!(Word),
WarnFollowing, EncodeCrossCrate::Yes
),
rustc_attr!(
TEST, rustc_no_implicit_bounds, CrateLevel, template!(Word),
WarnFollowing, EncodeCrossCrate::No
),
rustc_attr!(
TEST, rustc_strict_coherence, Normal, template!(Word),
WarnFollowing, EncodeCrossCrate::Yes

View file

@ -5,14 +5,14 @@ use rustc_errors::codes::*;
use rustc_errors::struct_span_code_err;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
use rustc_hir::{AmbigArg, LangItem, PolyTraitRef};
use rustc_middle::bug;
use rustc_middle::ty::{
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
TypeVisitor, Upcast,
};
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw};
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
use rustc_trait_selection::traits;
use smallvec::SmallVec;
use tracing::{debug, instrument};
@ -188,6 +188,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
) {
let tcx = self.tcx();
// Skip adding any default bounds if `#![rustc_no_implicit_bounds]`
if tcx.has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) {
return;
}
let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
@ -408,24 +413,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let tcx = self.tcx();
let trait_id = tcx.lang_items().get(trait_);
if let Some(trait_id) = trait_id
&& self.do_not_provide_default_trait_bound(
trait_id,
hir_bounds,
self_ty_where_predicates,
)
&& self.should_add_default_traits(trait_id, hir_bounds, self_ty_where_predicates)
{
add_trait_bound(tcx, bounds, self_ty, trait_id, span);
}
}
fn do_not_provide_default_trait_bound<'a>(
/// Returns `true` if default trait bound should be added.
fn should_add_default_traits<'a>(
&self,
trait_def_id: DefId,
hir_bounds: &'a [hir::GenericBound<'tcx>],
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
) -> bool {
let collected = collect_bounds(hir_bounds, self_ty_where_predicates, trait_def_id);
!collected.any()
!self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any()
}
/// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any.

View file

@ -1866,6 +1866,7 @@ symbols! {
rustc_never_returns_null_ptr,
rustc_never_type_options,
rustc_no_implicit_autorefs,
rustc_no_implicit_bounds,
rustc_no_mir_inline,
rustc_nonnull_optimization_guaranteed,
rustc_nounwind,