Implement lint against using Interner and InferCtxtLike in random compiler crates

This commit is contained in:
Michael Goulet 2025-03-26 04:09:07 +00:00
parent ca6dad3eab
commit 14804d1ed1
11 changed files with 82 additions and 3 deletions

View file

@ -799,6 +799,9 @@ lint_tykind_kind = usage of `ty::TyKind::<kind>`
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
lint_type_ir_trait_usage = do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` 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
lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing
.label = argument has type `{$arg_ty}`
.suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value

View file

@ -15,7 +15,7 @@ use crate::lints::{
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand,
NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag,
SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage,
UntranslatableDiag,
TypeIrTraitUsage, UntranslatableDiag,
};
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
@ -280,7 +280,7 @@ declare_tool_lint! {
}
declare_tool_lint! {
/// The `usage_of_type_ir_inherent` lint detects usage `rustc_type_ir::inherent`.
/// The `usage_of_type_ir_inherent` lint detects usage of `rustc_type_ir::inherent`.
///
/// This module should only be used within the trait solver.
pub rustc::USAGE_OF_TYPE_IR_INHERENT,
@ -289,9 +289,42 @@ declare_tool_lint! {
report_in_external_macro: true
}
declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT]);
declare_tool_lint! {
/// The `usage_of_type_ir_traits` lint detects usage of `rustc_type_ir::Interner`,
/// or `rustc_infer::InferCtxtLike`.
///
/// Methods of this trait should only be used within the type system abstraction layer,
/// and in the generic next trait solver implementation. Look for an analogously named
/// method on `TyCtxt` or `InferCtxt` (respectively).
pub rustc::USAGE_OF_TYPE_IR_TRAITS,
Allow,
"usage `rustc_type_ir`-specific abstraction traits 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]);
impl<'tcx> LateLintPass<'tcx> for TypeIr {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
let res_def_id = match expr.kind {
hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => path.res.opt_def_id(),
hir::ExprKind::Path(hir::QPath::TypeRelative(..)) | hir::ExprKind::MethodCall(..) => {
cx.typeck_results().type_dependent_def_id(expr.hir_id)
}
_ => return,
};
let Some(res_def_id) = res_def_id else {
return;
};
if let Some(assoc_item) = cx.tcx.opt_associated_item(res_def_id)
&& let Some(trait_def_id) = assoc_item.trait_container(cx.tcx)
&& (cx.tcx.is_diagnostic_item(sym::type_ir_interner, trait_def_id)
| cx.tcx.is_diagnostic_item(sym::type_ir_infer_ctxt_like, trait_def_id))
{
cx.emit_span_lint(USAGE_OF_TYPE_IR_TRAITS, expr.span, TypeIrTraitUsage);
}
}
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return };

View file

@ -645,6 +645,7 @@ fn register_internals(store: &mut LintStore) {
LintId::of(USAGE_OF_QUALIFIED_TY),
LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT),
LintId::of(USAGE_OF_TYPE_IR_INHERENT),
LintId::of(USAGE_OF_TYPE_IR_TRAITS),
LintId::of(BAD_OPT_ACCESS),
LintId::of(SPAN_USE_EQ_CTXT),
],

View file

@ -943,6 +943,11 @@ pub(crate) struct TyQualified {
#[note]
pub(crate) struct TypeIrInherentUsage;
#[derive(LintDiagnostic)]
#[diag(lint_type_ir_trait_usage)]
#[note]
pub(crate) struct TypeIrTraitUsage;
#[derive(LintDiagnostic)]
#[diag(lint_non_glob_import_type_ir_inherent)]
pub(crate) struct NonGlobImportTypeIrInherent {

View file

@ -6,6 +6,7 @@
// tidy-alphabetical-start
#![allow(rustc::usage_of_type_ir_inherent)]
#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_traits))]
// tidy-alphabetical-end
pub mod canonicalizer;

View file

@ -2118,7 +2118,9 @@ symbols! {
type_changing_struct_update,
type_const,
type_id,
type_ir_infer_ctxt_like,
type_ir_inherent,
type_ir_interner,
type_length_limit,
type_macros,
type_name,

View file

@ -102,6 +102,7 @@ impl<I: Interner> TypingMode<I> {
}
}
#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_infer_ctxt_like")]
pub trait InferCtxtLike: Sized {
type Interner: Interner;
fn cx(&self) -> Self::Interner;

View file

@ -15,6 +15,7 @@ use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesDat
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
use crate::{self as ty, search_graph};
#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_interner")]
pub trait Interner:
Sized
+ Copy

View file

@ -6,6 +6,7 @@
feature(associated_type_defaults, never_type, rustc_attrs, negative_impls)
)]
#![cfg_attr(feature = "nightly", allow(internal_features))]
#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_traits))]
// tidy-alphabetical-end
extern crate self as rustc_type_ir;

View file

@ -0,0 +1,16 @@
//@ compile-flags: -Z unstable-options
//@ ignore-stage1
#![feature(rustc_private)]
#![deny(rustc::usage_of_type_ir_traits)]
extern crate rustc_type_ir;
use rustc_type_ir::Interner;
fn foo<I: Interner>(cx: I, did: I::DefId) {
let _ = cx.trait_is_unsafe(did);
//~^ ERROR do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver
}
fn main() {}

View file

@ -0,0 +1,15 @@
error: do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver
--> $DIR/import-of-type-ir-traits.rs:12:13
|
LL | let _ = cx.trait_is_unsafe(did);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the method or struct you're looking for is likely defined somewhere else downstream in the compiler
note: the lint level is defined here
--> $DIR/import-of-type-ir-traits.rs:5:9
|
LL | #![deny(rustc::usage_of_type_ir_traits)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error