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.
This commit is contained in:
Romain Perier 2025-05-25 15:15:49 +02:00
parent 6f935a044d
commit a1a3bef6f0
13 changed files with 111 additions and 5 deletions

View file

@ -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)]

View file

@ -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)]

View file

@ -812,6 +812,9 @@ lint_tykind = usage of `ty::TyKind`
lint_tykind_kind = usage of `ty::TyKind::<kind>`
.suggestion = try using `ty::<kind>` 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

View file

@ -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! {

View file

@ -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),
],
);
}

View file

@ -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 {

View file

@ -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)]

View file

@ -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;

View file

@ -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);
}

View file

@ -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,

View file

@ -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;

View file

@ -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<I: rustc_type_ir::Interner>(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
}

View file

@ -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<I: rustc_type_ir::Interner>(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