From 4661c83530237349621793346ca5d4d8654d0cd1 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 9 Feb 2024 09:38:22 +0000 Subject: [PATCH] Avoid accessing the HIR in the happy path of `coherent_trait` --- .../src/coherence/builtin.rs | 29 ++++++++++--------- .../rustc_hir_analysis/src/coherence/mod.rs | 3 +- .../ui/coherence/coherence-impls-copy.stderr | 24 +++++++-------- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 5a387844593..59177f14f99 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -25,9 +25,13 @@ use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::{self, ObligationCause}; use std::collections::BTreeMap; -pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) -> Result<(), ErrorGuaranteed> { +pub fn check_trait( + tcx: TyCtxt<'_>, + trait_def_id: DefId, + impl_def_id: LocalDefId, +) -> Result<(), ErrorGuaranteed> { let lang_items = tcx.lang_items(); - let checker = Checker { tcx, trait_def_id }; + let checker = Checker { tcx, trait_def_id, impl_def_id }; let mut res = checker.check(lang_items.drop_trait(), visit_implementation_of_drop); res = res.and(checker.check(lang_items.copy_trait(), visit_implementation_of_copy)); res = res.and( @@ -45,6 +49,7 @@ pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) -> Result<(), ErrorGuar struct Checker<'tcx> { tcx: TyCtxt<'tcx>, trait_def_id: DefId, + impl_def_id: LocalDefId, } impl<'tcx> Checker<'tcx> { @@ -54,9 +59,7 @@ impl<'tcx> Checker<'tcx> { { let mut res = Ok(()); if Some(self.trait_def_id) == trait_def_id { - for &impl_def_id in self.tcx.hir().trait_impls(self.trait_def_id) { - res = res.and(f(self.tcx, impl_def_id)); - } + res = res.and(f(self.tcx, self.impl_def_id)); } res } @@ -92,10 +95,10 @@ fn visit_implementation_of_copy( debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type); - let span = match tcx.hir().expect_item(impl_did).expect_impl() { - hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => return Ok(()), - hir::Impl { self_ty, .. } => self_ty.span, - }; + if let ty::ImplPolarity::Negative = tcx.impl_polarity(impl_did) { + return Ok(()); + } + let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span; let cause = traits::ObligationCause::misc(span, impl_did); match type_allowed_to_implement_copy(tcx, param_env, self_type, cause) { @@ -121,10 +124,10 @@ fn visit_implementation_of_const_param_ty( let param_env = tcx.param_env(impl_did); - let span = match tcx.hir().expect_item(impl_did).expect_impl() { - hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => return Ok(()), - impl_ => impl_.self_ty.span, - }; + if let ty::ImplPolarity::Negative = tcx.impl_polarity(impl_did) { + return Ok(()); + } + let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span; let cause = traits::ObligationCause::misc(span, impl_did); match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) { diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 8cf1f2c9407..a71ea00a044 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -133,9 +133,10 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> res = res.and(unsafety::check_item(tcx, impl_def_id)); res = res.and(tcx.ensure().orphan_check_impl(impl_def_id)); + res = res.and(builtin::check_trait(tcx, def_id, impl_def_id)); } - res.and(builtin::check_trait(tcx, def_id)) + res } /// Checks whether an impl overlaps with the automatic `impl Trait for dyn Trait`. diff --git a/tests/ui/coherence/coherence-impls-copy.stderr b/tests/ui/coherence/coherence-impls-copy.stderr index 21dbc606321..2d2c5064043 100644 --- a/tests/ui/coherence/coherence-impls-copy.stderr +++ b/tests/ui/coherence/coherence-impls-copy.stderr @@ -30,6 +30,12 @@ LL | impl Copy for &'static [NotSync] {} | = note: define and implement a trait or new type instead +error[E0206]: the trait `Copy` cannot be implemented for this type + --> $DIR/coherence-impls-copy.rs:21:15 + | +LL | impl Copy for &'static mut MyType {} + | ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration + error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/coherence-impls-copy.rs:25:1 | @@ -41,6 +47,12 @@ LL | impl Copy for (MyType, MyType) {} | = note: define and implement a trait or new type instead +error[E0206]: the trait `Copy` cannot be implemented for this type + --> $DIR/coherence-impls-copy.rs:25:15 + | +LL | impl Copy for (MyType, MyType) {} + | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration + error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/coherence-impls-copy.rs:30:1 | @@ -52,18 +64,6 @@ LL | impl Copy for [MyType] {} | = note: define and implement a trait or new type instead -error[E0206]: the trait `Copy` cannot be implemented for this type - --> $DIR/coherence-impls-copy.rs:21:15 - | -LL | impl Copy for &'static mut MyType {} - | ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration - -error[E0206]: the trait `Copy` cannot be implemented for this type - --> $DIR/coherence-impls-copy.rs:25:15 - | -LL | impl Copy for (MyType, MyType) {} - | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration - error[E0206]: the trait `Copy` cannot be implemented for this type --> $DIR/coherence-impls-copy.rs:30:15 |