From a1a3bef6f0d5f5f45f0296133d7af745dc89d7bb Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Sun, 25 May 2025 15:15:49 +0200 Subject: [PATCH] Implement lint against direct uses of rustc_type_ir in compiler crates This commit adds a lint to prevent the use of rustc_type_ir in random compiler crates, except for type system internals traits, which are explicitly allowed. Moreover, this fixes diagnostic_items() to include the CRATE_OWNER_ID, otherwise rustc_diagnostic_item attribute is ignored on the crate root. --- compiler/rustc_errors/src/lib.rs | 1 + compiler/rustc_infer/src/lib.rs | 1 + compiler/rustc_lint/messages.ftl | 3 ++ compiler/rustc_lint/src/internal.rs | 31 +++++++++++++-- compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_lint/src/lints.rs | 5 +++ compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_next_trait_solver/src/lib.rs | 1 + compiler/rustc_passes/src/diagnostic_items.rs | 4 +- compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_type_ir/src/lib.rs | 2 + .../direct-use-of-rustc-type-ir.rs | 26 +++++++++++++ .../direct-use-of-rustc-type-ir.stderr | 39 +++++++++++++++++++ 13 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 tests/ui-fulldeps/internal-lints/direct-use-of-rustc-type-ir.rs create mode 100644 tests/ui-fulldeps/internal-lints/direct-use-of-rustc-type-ir.stderr diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 9f72fc4705aea..08e4f61e6290f 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -7,6 +7,7 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +#![cfg_attr(not(bootstrap), allow(rustc::direct_use_of_rustc_type_ir))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 550707ed4bc6a..18cee03ba2e87 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -16,6 +16,7 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +#![cfg_attr(not(bootstrap), allow(rustc::direct_use_of_rustc_type_ir))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index f92f830780801..8d9f2385b710f 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -812,6 +812,9 @@ lint_tykind = usage of `ty::TyKind` lint_tykind_kind = usage of `ty::TyKind::` .suggestion = try using `ty::` directly +lint_type_ir_direct_use = do not use `rustc_type_ir` unless you are implementing type system internals + .note = use `rustc_middle::ty` instead + lint_type_ir_inherent_usage = do not use `rustc_type_ir::inherent` unless you're inside of the trait solver .note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 1805a674d68db..d8fc46aa9ab50 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -14,8 +14,8 @@ use {rustc_ast as ast, rustc_hir as hir}; use crate::lints::{ BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, - SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage, - TypeIrTraitUsage, UntranslatableDiag, + SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrDirectUse, + TypeIrInherentUsage, TypeIrTraitUsage, UntranslatableDiag, }; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; @@ -301,8 +301,18 @@ declare_tool_lint! { "usage `rustc_type_ir`-specific abstraction traits outside of trait system", report_in_external_macro: true } +declare_tool_lint! { + /// The `direct_use_of_rustc_type_ir` lint detects usage of `rustc_type_ir`. + /// + /// This module should only be used within the trait solver and some desirable + /// crates like rustc_middle. + pub rustc::DIRECT_USE_OF_RUSTC_TYPE_IR, + Allow, + "usage `rustc_type_ir` abstraction outside of trait system", + report_in_external_macro: true +} -declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_TRAITS]); +declare_lint_pass!(TypeIr => [DIRECT_USE_OF_RUSTC_TYPE_IR, NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_TRAITS]); impl<'tcx> LateLintPass<'tcx> for TypeIr { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { @@ -372,6 +382,21 @@ impl<'tcx> LateLintPass<'tcx> for TypeIr { NonGlobImportTypeIrInherent { suggestion: lo.eq_ctxt(hi).then(|| lo.to(hi)), snippet }, ); } + + fn check_path( + &mut self, + cx: &LateContext<'tcx>, + path: &rustc_hir::Path<'tcx>, + _: rustc_hir::HirId, + ) { + if let Some(seg) = path.segments.iter().find(|seg| { + seg.res + .opt_def_id() + .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::type_ir, def_id)) + }) { + cx.emit_span_lint(DIRECT_USE_OF_RUSTC_TYPE_IR, seg.ident.span, TypeIrDirectUse); + } + } } declare_tool_lint! { diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 9a1490d3eea36..20568f35a471a 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -668,6 +668,7 @@ fn register_internals(store: &mut LintStore) { LintId::of(USAGE_OF_TYPE_IR_TRAITS), LintId::of(BAD_OPT_ACCESS), LintId::of(SPAN_USE_EQ_CTXT), + LintId::of(DIRECT_USE_OF_RUSTC_TYPE_IR), ], ); } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index ae65cefda773a..abdf8e3853bfb 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -969,6 +969,11 @@ pub(crate) struct TypeIrInherentUsage; #[note] pub(crate) struct TypeIrTraitUsage; +#[derive(LintDiagnostic)] +#[diag(lint_type_ir_direct_use)] +#[note] +pub(crate) struct TypeIrDirectUse; + #[derive(LintDiagnostic)] #[diag(lint_non_glob_import_type_ir_inherent)] pub(crate) struct NonGlobImportTypeIrInherent { diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 6cb1d8c5fc4b2..c488ef9b575ba 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -28,6 +28,7 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +#![cfg_attr(not(bootstrap), allow(rustc::direct_use_of_rustc_type_ir))] #![cfg_attr(not(bootstrap), feature(sized_hierarchy))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs index 77f098e6f2649..e3f42c181fa28 100644 --- a/compiler/rustc_next_trait_solver/src/lib.rs +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -7,6 +7,7 @@ // tidy-alphabetical-start #![allow(rustc::usage_of_type_ir_inherent)] #![allow(rustc::usage_of_type_ir_traits)] +#![cfg_attr(not(bootstrap), allow(rustc::direct_use_of_rustc_type_ir))] // tidy-alphabetical-end pub mod canonicalizer; diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 17a729f422a1c..8f572af02c249 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -10,7 +10,7 @@ //! * Compiler internal types like `Ty` and `TyCtxt` use rustc_hir::diagnostic_items::DiagnosticItems; -use rustc_hir::{Attribute, OwnerId}; +use rustc_hir::{Attribute, CRATE_OWNER_ID, OwnerId}; use rustc_middle::query::{LocalCrate, Providers}; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::{DefId, LOCAL_CRATE}; @@ -67,7 +67,7 @@ fn diagnostic_items(tcx: TyCtxt<'_>, _: LocalCrate) -> DiagnosticItems { // Collect diagnostic items in this crate. let crate_items = tcx.hir_crate_items(()); - for id in crate_items.owners() { + for id in crate_items.owners().chain(std::iter::once(CRATE_OWNER_ID)) { observe_item(tcx, &mut diagnostic_items, id); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index baadff16120f3..812a254990caf 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2183,6 +2183,7 @@ symbols! { type_changing_struct_update, type_const, type_id, + type_ir, type_ir_infer_ctxt_like, type_ir_inherent, type_ir_interner, diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 792090effcff1..3863a6d7c5a85 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -1,3 +1,4 @@ +#![cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir")] // tidy-alphabetical-start #![allow(rustc::usage_of_ty_tykind)] #![allow(rustc::usage_of_type_ir_inherent)] @@ -7,6 +8,7 @@ feature(associated_type_defaults, never_type, rustc_attrs, negative_impls) )] #![cfg_attr(feature = "nightly", allow(internal_features))] +#![cfg_attr(not(bootstrap), allow(rustc::direct_use_of_rustc_type_ir))] // tidy-alphabetical-end extern crate self as rustc_type_ir; diff --git a/tests/ui-fulldeps/internal-lints/direct-use-of-rustc-type-ir.rs b/tests/ui-fulldeps/internal-lints/direct-use-of-rustc-type-ir.rs new file mode 100644 index 0000000000000..5c68df4e1e4a8 --- /dev/null +++ b/tests/ui-fulldeps/internal-lints/direct-use-of-rustc-type-ir.rs @@ -0,0 +1,26 @@ +//@ compile-flags: -Z unstable-options +//@ ignore-stage1 + +#![feature(rustc_private)] +#![deny(rustc::direct_use_of_rustc_type_ir)] + +extern crate rustc_middle; +extern crate rustc_type_ir; + +use rustc_middle::ty::*; // OK, we have to accept rustc_middle::ty::* + +// We have to deny direct import of type_ir +use rustc_type_ir::*; +//~^ ERROR: do not use `rustc_type_ir` unless you are implementing type system internals + +// We have to deny direct types usages which resolves to type_ir +fn foo(cx: I, did: I::DefId) { +//~^ ERROR: do not use `rustc_type_ir` unless you are implementing type system internals +} + +fn main() { + let _ = rustc_type_ir::InferConst::Fresh(42); +//~^ ERROR: do not use `rustc_type_ir` unless you are implementing type system internals + let _: rustc_type_ir::InferConst; +//~^ ERROR: do not use `rustc_type_ir` unless you are implementing type system internals +} diff --git a/tests/ui-fulldeps/internal-lints/direct-use-of-rustc-type-ir.stderr b/tests/ui-fulldeps/internal-lints/direct-use-of-rustc-type-ir.stderr new file mode 100644 index 0000000000000..d1716494d52e6 --- /dev/null +++ b/tests/ui-fulldeps/internal-lints/direct-use-of-rustc-type-ir.stderr @@ -0,0 +1,39 @@ +error: do not use `rustc_type_ir` unless you are implementing type system internals + --> $DIR/direct-use-of-rustc-type-ir.rs:13:5 + | +LL | use rustc_type_ir::*; + | ^^^^^^^^^^^^^ + | + = note: use `rustc_middle::ty` instead +note: the lint level is defined here + --> $DIR/direct-use-of-rustc-type-ir.rs:5:9 + | +LL | #![deny(rustc::direct_use_of_rustc_type_ir)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: do not use `rustc_type_ir` unless you are implementing type system internals + --> $DIR/direct-use-of-rustc-type-ir.rs:17:11 + | +LL | fn foo(cx: I, did: I::DefId) { + | ^^^^^^^^^^^^^ + | + = note: use `rustc_middle::ty` instead + +error: do not use `rustc_type_ir` unless you are implementing type system internals + --> $DIR/direct-use-of-rustc-type-ir.rs:22:13 + | +LL | let _ = rustc_type_ir::InferConst::Fresh(42); + | ^^^^^^^^^^^^^ + | + = note: use `rustc_middle::ty` instead + +error: do not use `rustc_type_ir` unless you are implementing type system internals + --> $DIR/direct-use-of-rustc-type-ir.rs:24:12 + | +LL | let _: rustc_type_ir::InferConst; + | ^^^^^^^^^^^^^ + | + = note: use `rustc_middle::ty` instead + +error: aborting due to 4 previous errors +