diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 9b5e4e50d3ca8..81250cc9976cd 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1096,6 +1096,14 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ TEST, rustc_dump_env_program_clauses, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No ), + rustc_attr!( + TEST, rustc_dump_item_bounds, Normal, template!(Word), + WarnFollowing, EncodeCrossCrate::No + ), + rustc_attr!( + TEST, rustc_dump_predicates, Normal, template!(Word), + WarnFollowing, EncodeCrossCrate::No + ), rustc_attr!( TEST, rustc_object_lifetime_default, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs index f7323edfe4d2c..85e1c600d6da4 100644 --- a/compiler/rustc_hir_analysis/src/collect/dump.rs +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs @@ -16,3 +16,28 @@ pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) { tcx.dcx().emit_err(crate::errors::TypeOf { span: tcx.def_span(id.owner_id), ty }); } } + +pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) { + for id in tcx.hir_crate_items(()).owners() { + if tcx.has_attr(id, sym::rustc_dump_predicates) { + let preds = tcx.predicates_of(id).instantiate_identity(tcx).predicates; + let span = tcx.def_span(id); + + let mut diag = tcx.dcx().struct_span_err(span, sym::rustc_dump_predicates.as_str()); + for pred in preds { + diag.note(format!("{pred:?}")); + } + diag.emit(); + } + if tcx.has_attr(id, sym::rustc_dump_item_bounds) { + let bounds = tcx.item_bounds(id).instantiate_identity(); + let span = tcx.def_span(id); + + let mut diag = tcx.dcx().struct_span_err(span, sym::rustc_dump_item_bounds.as_str()); + for bound in bounds { + diag.note(format!("{bound:?}")); + } + diag.emit(); + } + } +} diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 6af4fdaea212f..0428abcdf24e8 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -168,6 +168,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { tcx.sess.time("outlives_dumping", || outlives::dump::inferred_outlives(tcx)); tcx.sess.time("variance_dumping", || variance::dump::variances(tcx)); collect::dump::opaque_hidden_types(tcx); + collect::dump::predicates_and_item_bounds(tcx); } // Make sure we evaluate all static and (non-associated) const items, even if unused. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f44fa1bcb4fd1..0f71c19a43f95 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1593,6 +1593,8 @@ symbols! { rustc_doc_primitive, rustc_dummy, rustc_dump_env_program_clauses, + rustc_dump_item_bounds, + rustc_dump_predicates, rustc_dump_program_clauses, rustc_dump_user_args, rustc_dump_vtable, diff --git a/tests/ui/attributes/dump-preds.rs b/tests/ui/attributes/dump-preds.rs new file mode 100644 index 0000000000000..45832aa2e77f5 --- /dev/null +++ b/tests/ui/attributes/dump-preds.rs @@ -0,0 +1,18 @@ +#![feature(rustc_attrs)] + +#[rustc_dump_predicates] +trait Trait: Iterator +//~^ ERROR rustc_dump_predicates +where + String: From +{ + #[rustc_dump_predicates] + #[rustc_dump_item_bounds] + type Assoc: std::ops::Deref + //~^ ERROR rustc_dump_predicates + //~| ERROR rustc_dump_item_bounds + where + Self::Assoc<()>: Copy; +} + +fn main() {} diff --git a/tests/ui/attributes/dump-preds.stderr b/tests/ui/attributes/dump-preds.stderr new file mode 100644 index 0000000000000..db86a8219e768 --- /dev/null +++ b/tests/ui/attributes/dump-preds.stderr @@ -0,0 +1,39 @@ +error: rustc_dump_predicates + --> $DIR/dump-preds.rs:4:1 + | +LL | trait Trait: Iterator + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<::Item as std::marker::Copy>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [] } + +error: rustc_dump_predicates + --> $DIR/dump-preds.rs:11:5 + | +LL | type Assoc: std::ops::Deref + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<::Item as std::marker::Copy>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(

, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(

, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<>::Assoc<()> as std::marker::Copy>, polarity:Positive), bound_vars: [] } + +error: rustc_dump_item_bounds + --> $DIR/dump-preds.rs:11:5 + | +LL | type Assoc: std::ops::Deref + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Binder { value: ProjectionPredicate(AliasTerm { args: [Alias(Projection, AliasTy { args: [Self/#0, T/#1, P/#2], def_id: DefId(0:5 ~ dump_preds[a6a3]::Trait::Assoc) })], def_id: DefId(2:3422 ~ core[aec8]::ops::deref::Deref::Target) }, Term::Ty(())), bound_vars: [] } + = note: Binder { value: TraitPredicate(<>::Assoc

as std::ops::Deref>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(<>::Assoc

as std::marker::Sized>, polarity:Positive), bound_vars: [] } + +error: aborting due to 3 previous errors +