Rollup merge of #138964 - compiler-errors:usage-of-interner, r=lcnr

Implement lint against using Interner and InferCtxtLike in random compiler crates

Often `Interner` defines similar methods to `TyCtxt` (but often simplified due to the simpler API surface of the type system layer for the new solver), which people will either unintentionally or intentionally import and use. Let's discourage that.

r? lcnr
This commit is contained in:
Stuart Cook 2025-03-27 15:57:24 +11:00 committed by GitHub
commit cb39217d44
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 139 additions and 47 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 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 .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 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}` .label = argument has type `{$arg_ty}`
.suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value .suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value

View File

@ -1,24 +1,21 @@
//! Some lints that are only useful in the compiler or crates that use compiler internals, such as //! Some lints that are only useful in the compiler or crates that use compiler internals, such as
//! Clippy. //! Clippy.
use rustc_ast as ast; use rustc_hir::HirId;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{
AmbigArg, BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat,
PatExpr, PatExprKind, PatKind, Path, PathSegment, QPath, Ty, TyKind,
};
use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy}; use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::hygiene::{ExpnKind, MacroKind};
use rustc_span::{Span, sym}; use rustc_span::{Span, sym};
use tracing::debug; use tracing::debug;
use {rustc_ast as ast, rustc_hir as hir};
use crate::lints::{ use crate::lints::{
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand,
NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag,
SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage, SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage,
UntranslatableDiag, TypeIrTraitUsage, UntranslatableDiag,
}; };
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
@ -37,9 +34,12 @@ declare_tool_lint! {
declare_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]); declare_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]);
impl LateLintPass<'_> for DefaultHashTypes { impl LateLintPass<'_> for DefaultHashTypes {
fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) { fn check_path(&mut self, cx: &LateContext<'_>, path: &hir::Path<'_>, hir_id: HirId) {
let Res::Def(rustc_hir::def::DefKind::Struct, def_id) = path.res else { return }; let Res::Def(rustc_hir::def::DefKind::Struct, def_id) = path.res else { return };
if matches!(cx.tcx.hir_node(hir_id), Node::Item(Item { kind: ItemKind::Use(..), .. })) { if matches!(
cx.tcx.hir_node(hir_id),
hir::Node::Item(hir::Item { kind: hir::ItemKind::Use(..), .. })
) {
// Don't lint imports, only actual usages. // Don't lint imports, only actual usages.
return; return;
} }
@ -60,10 +60,10 @@ impl LateLintPass<'_> for DefaultHashTypes {
/// get the `DefId` and `GenericArgsRef` of the function. /// get the `DefId` and `GenericArgsRef` of the function.
fn typeck_results_of_method_fn<'tcx>( fn typeck_results_of_method_fn<'tcx>(
cx: &LateContext<'tcx>, cx: &LateContext<'tcx>,
expr: &Expr<'_>, expr: &hir::Expr<'_>,
) -> Option<(Span, DefId, ty::GenericArgsRef<'tcx>)> { ) -> Option<(Span, DefId, ty::GenericArgsRef<'tcx>)> {
match expr.kind { match expr.kind {
ExprKind::MethodCall(segment, ..) hir::ExprKind::MethodCall(segment, ..)
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) => if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) =>
{ {
Some((segment.ident.span, def_id, cx.typeck_results().node_args(expr.hir_id))) Some((segment.ident.span, def_id, cx.typeck_results().node_args(expr.hir_id)))
@ -102,7 +102,7 @@ declare_tool_lint! {
declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]); declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]);
impl LateLintPass<'_> for QueryStability { impl LateLintPass<'_> for QueryStability {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
let Some((span, def_id, args)) = typeck_results_of_method_fn(cx, expr) else { return }; let Some((span, def_id, args)) = typeck_results_of_method_fn(cx, expr) else { return };
if let Ok(Some(instance)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, args) if let Ok(Some(instance)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, args)
{ {
@ -164,21 +164,25 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
} }
} }
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx, AmbigArg>) { fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, hir::AmbigArg>) {
match &ty.kind { match &ty.kind {
TyKind::Path(QPath::Resolved(_, path)) => { hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
if lint_ty_kind_usage(cx, &path.res) { if lint_ty_kind_usage(cx, &path.res) {
let span = match cx.tcx.parent_hir_node(ty.hir_id) { let span = match cx.tcx.parent_hir_node(ty.hir_id) {
Node::PatExpr(PatExpr { kind: PatExprKind::Path(qpath), .. }) hir::Node::PatExpr(hir::PatExpr {
| Node::Pat(Pat { kind: hir::PatExprKind::Path(qpath),
kind: PatKind::TupleStruct(qpath, ..) | PatKind::Struct(qpath, ..),
.. ..
}) })
| Node::Expr( | hir::Node::Pat(hir::Pat {
Expr { kind: ExprKind::Path(qpath), .. } kind:
| &Expr { kind: ExprKind::Struct(qpath, ..), .. }, hir::PatKind::TupleStruct(qpath, ..) | hir::PatKind::Struct(qpath, ..),
..
})
| hir::Node::Expr(
hir::Expr { kind: hir::ExprKind::Path(qpath), .. }
| &hir::Expr { kind: hir::ExprKind::Struct(qpath, ..), .. },
) => { ) => {
if let QPath::TypeRelative(qpath_ty, ..) = qpath if let hir::QPath::TypeRelative(qpath_ty, ..) = qpath
&& qpath_ty.hir_id == ty.hir_id && qpath_ty.hir_id == ty.hir_id
{ {
Some(path.span) Some(path.span)
@ -223,7 +227,7 @@ fn lint_ty_kind_usage(cx: &LateContext<'_>, res: &Res) -> bool {
} }
} }
fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option<String> { fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &hir::Path<'_>) -> Option<String> {
match &path.res { match &path.res {
Res::Def(_, def_id) => { Res::Def(_, def_id) => {
if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(*def_id) { if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(*def_id) {
@ -244,13 +248,17 @@ fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option<String> {
None None
} }
fn gen_args(segment: &PathSegment<'_>) -> String { fn gen_args(segment: &hir::PathSegment<'_>) -> String {
if let Some(args) = &segment.args { if let Some(args) = &segment.args {
let lifetimes = args let lifetimes = args
.args .args
.iter() .iter()
.filter_map(|arg| { .filter_map(|arg| {
if let GenericArg::Lifetime(lt) = arg { Some(lt.ident.to_string()) } else { None } if let hir::GenericArg::Lifetime(lt) = arg {
Some(lt.ident.to_string())
} else {
None
}
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -272,7 +280,7 @@ declare_tool_lint! {
} }
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. /// This module should only be used within the trait solver.
pub rustc::USAGE_OF_TYPE_IR_INHERENT, pub rustc::USAGE_OF_TYPE_IR_INHERENT,
@ -281,10 +289,43 @@ declare_tool_lint! {
report_in_external_macro: true 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 { impl<'tcx> LateLintPass<'tcx> for TypeIr {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { 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 }; let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return };
let is_mod_inherent = |def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id); let is_mod_inherent = |def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id);
@ -394,15 +435,15 @@ declare_tool_lint! {
declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL]); declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL]);
impl LateLintPass<'_> for Diagnostics { impl LateLintPass<'_> for Diagnostics {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
let collect_args_tys_and_spans = |args: &[Expr<'_>], reserve_one_extra: bool| { let collect_args_tys_and_spans = |args: &[hir::Expr<'_>], reserve_one_extra: bool| {
let mut result = Vec::with_capacity(args.len() + usize::from(reserve_one_extra)); let mut result = Vec::with_capacity(args.len() + usize::from(reserve_one_extra));
result.extend(args.iter().map(|arg| (cx.typeck_results().expr_ty(arg), arg.span))); result.extend(args.iter().map(|arg| (cx.typeck_results().expr_ty(arg), arg.span)));
result result
}; };
// Only check function calls and method calls. // Only check function calls and method calls.
let (span, def_id, fn_gen_args, arg_tys_and_spans) = match expr.kind { let (span, def_id, fn_gen_args, arg_tys_and_spans) = match expr.kind {
ExprKind::Call(callee, args) => { hir::ExprKind::Call(callee, args) => {
match cx.typeck_results().node_type(callee.hir_id).kind() { match cx.typeck_results().node_type(callee.hir_id).kind() {
&ty::FnDef(def_id, fn_gen_args) => { &ty::FnDef(def_id, fn_gen_args) => {
(callee.span, def_id, fn_gen_args, collect_args_tys_and_spans(args, false)) (callee.span, def_id, fn_gen_args, collect_args_tys_and_spans(args, false))
@ -410,7 +451,7 @@ impl LateLintPass<'_> for Diagnostics {
_ => return, // occurs for fns passed as args _ => return, // occurs for fns passed as args
} }
} }
ExprKind::MethodCall(_segment, _recv, args, _span) => { hir::ExprKind::MethodCall(_segment, _recv, args, _span) => {
let Some((span, def_id, fn_gen_args)) = typeck_results_of_method_fn(cx, expr) let Some((span, def_id, fn_gen_args)) = typeck_results_of_method_fn(cx, expr)
else { else {
return; return;
@ -514,8 +555,8 @@ impl Diagnostics {
let mut is_inside_appropriate_impl = false; let mut is_inside_appropriate_impl = false;
for (_hir_id, parent) in cx.tcx.hir_parent_iter(current_id) { for (_hir_id, parent) in cx.tcx.hir_parent_iter(current_id) {
debug!(?parent); debug!(?parent);
if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) = parent
&& let Impl { of_trait: Some(of_trait), .. } = impl_ && let hir::Impl { of_trait: Some(of_trait), .. } = impl_
&& let Some(def_id) = of_trait.trait_def_id() && let Some(def_id) = of_trait.trait_def_id()
&& let Some(name) = cx.tcx.get_diagnostic_name(def_id) && let Some(name) = cx.tcx.get_diagnostic_name(def_id)
&& matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic) && matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic)
@ -543,8 +584,8 @@ declare_tool_lint! {
declare_lint_pass!(BadOptAccess => [BAD_OPT_ACCESS]); declare_lint_pass!(BadOptAccess => [BAD_OPT_ACCESS]);
impl LateLintPass<'_> for BadOptAccess { impl LateLintPass<'_> for BadOptAccess {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
let ExprKind::Field(base, target) = expr.kind else { return }; let hir::ExprKind::Field(base, target) = expr.kind else { return };
let Some(adt_def) = cx.typeck_results().expr_ty(base).ty_adt_def() else { return }; let Some(adt_def) = cx.typeck_results().expr_ty(base).ty_adt_def() else { return };
// Skip types without `#[rustc_lint_opt_ty]` - only so that the rest of the lint can be // Skip types without `#[rustc_lint_opt_ty]` - only so that the rest of the lint can be
// avoided. // avoided.
@ -581,9 +622,12 @@ declare_tool_lint! {
declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]); declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]);
impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt { impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) {
if let ExprKind::Binary(BinOp { node: BinOpKind::Eq | BinOpKind::Ne, .. }, lhs, rhs) = if let hir::ExprKind::Binary(
expr.kind hir::BinOp { node: hir::BinOpKind::Eq | hir::BinOpKind::Ne, .. },
lhs,
rhs,
) = expr.kind
{ {
if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) { if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) {
cx.emit_span_lint(SPAN_USE_EQ_CTXT, expr.span, SpanUseEqCtxtDiag); cx.emit_span_lint(SPAN_USE_EQ_CTXT, expr.span, SpanUseEqCtxtDiag);
@ -592,9 +636,9 @@ impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt {
} }
} }
fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
match &expr.kind { match &expr.kind {
ExprKind::MethodCall(..) => cx hir::ExprKind::MethodCall(..) => cx
.typeck_results() .typeck_results()
.type_dependent_def_id(expr.hir_id) .type_dependent_def_id(expr.hir_id)
.is_some_and(|call_did| cx.tcx.is_diagnostic_item(sym::SpanCtxt, call_did)), .is_some_and(|call_did| cx.tcx.is_diagnostic_item(sym::SpanCtxt, call_did)),
@ -617,11 +661,11 @@ declare_lint_pass!(SymbolInternStringLiteral => [SYMBOL_INTERN_STRING_LITERAL]);
impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral { impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
if let ExprKind::Call(path, [arg]) = expr.kind if let hir::ExprKind::Call(path, [arg]) = expr.kind
&& let ExprKind::Path(ref qpath) = path.kind && let hir::ExprKind::Path(ref qpath) = path.kind
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
&& cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id) && cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id)
&& let ExprKind::Lit(kind) = arg.kind && let hir::ExprKind::Lit(kind) = arg.kind
&& let rustc_ast::LitKind::Str(_, _) = kind.node && let rustc_ast::LitKind::Str(_, _) = kind.node
{ {
cx.emit_span_lint( cx.emit_span_lint(

View File

@ -645,6 +645,7 @@ fn register_internals(store: &mut LintStore) {
LintId::of(USAGE_OF_QUALIFIED_TY), LintId::of(USAGE_OF_QUALIFIED_TY),
LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT), LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT),
LintId::of(USAGE_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(BAD_OPT_ACCESS),
LintId::of(SPAN_USE_EQ_CTXT), LintId::of(SPAN_USE_EQ_CTXT),
], ],

View File

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

View File

@ -225,8 +225,8 @@ use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion};
use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::print::{shrunk_instance_name, with_no_trimmed_paths}; use rustc_middle::ty::print::{shrunk_instance_name, with_no_trimmed_paths};
use rustc_middle::ty::{ use rustc_middle::ty::{
self, GenericArgs, GenericParamDefKind, Instance, InstanceKind, Interner, Ty, TyCtxt, self, GenericArgs, GenericParamDefKind, Instance, InstanceKind, Ty, TyCtxt, TypeFoldable,
TypeFoldable, TypeVisitableExt, VtblEntry, TypeVisitableExt, VtblEntry,
}; };
use rustc_middle::util::Providers; use rustc_middle::util::Providers;
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
@ -967,7 +967,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) ->
{ {
// `#[rustc_force_inline]` items should never be codegened. This should be caught by // `#[rustc_force_inline]` items should never be codegened. This should be caught by
// the MIR validator. // the MIR validator.
tcx.delay_bug("attempt to codegen `#[rustc_force_inline]` item"); tcx.dcx().delayed_bug("attempt to codegen `#[rustc_force_inline]` item");
} }
if def_id.is_local() { if def_id.is_local() {

View File

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

View File

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

View File

@ -16,7 +16,7 @@ use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode}; use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_type_ir::{Interner, elaborate}; use rustc_type_ir::elaborate;
use tracing::{debug, instrument, trace}; use tracing::{debug, instrument, trace};
use super::SelectionCandidate::*; use super::SelectionCandidate::*;
@ -802,7 +802,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::UnsafeBinder(_) => { | ty::UnsafeBinder(_) => {
// Only consider auto impls of unsafe traits when there are // Only consider auto impls of unsafe traits when there are
// no unsafe fields. // no unsafe fields.
if self.tcx().trait_is_unsafe(def_id) && self_ty.has_unsafe_fields() { if self.tcx().trait_def(def_id).safety.is_unsafe()
&& self_ty.has_unsafe_fields()
{
return; return;
} }

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 { pub trait InferCtxtLike: Sized {
type Interner: Interner; type Interner: Interner;
fn cx(&self) -> Self::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::visit::{Flags, TypeSuperVisitable, TypeVisitable};
use crate::{self as ty, search_graph}; use crate::{self as ty, search_graph};
#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_interner")]
pub trait Interner: pub trait Interner:
Sized Sized
+ Copy + Copy

View File

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