From 11a73f6d4dc5ea1560403ed198eda7616af2d767 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sun, 11 Feb 2024 10:43:01 +0000 Subject: [PATCH 1/6] Store impl unsafety in impl trait header --- .../rustc_hir_analysis/src/coherence/mod.rs | 8 ++-- .../src/coherence/unsafety.rs | 42 ++++++++++--------- compiler/rustc_hir_analysis/src/collect.rs | 1 + compiler/rustc_middle/src/ty/mod.rs | 1 + 4 files changed, 28 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 7f59763f2a084..f1978a0fc3555 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -132,12 +132,12 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> let mut res = tcx.ensure().specialization_graph_of(def_id); for &impl_def_id in impls { - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(); + let trait_header = tcx.impl_trait_header(impl_def_id).unwrap().instantiate_identity(); - res = res.and(check_impl(tcx, impl_def_id, trait_ref)); - res = res.and(check_object_overlap(tcx, impl_def_id, trait_ref)); + res = res.and(check_impl(tcx, impl_def_id, trait_header.trait_ref)); + res = res.and(check_object_overlap(tcx, impl_def_id, trait_header.trait_ref)); - res = res.and(unsafety::check_item(tcx, impl_def_id, trait_ref)); + res = res.and(unsafety::check_item(tcx, impl_def_id, trait_header)); res = res.and(tcx.ensure().orphan_check_impl(impl_def_id)); res = res.and(builtin::check_trait(tcx, def_id, impl_def_id)); } diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index d217d53587d56..158d010b05d37 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -2,23 +2,23 @@ //! crate or pertains to a type defined in this crate. use rustc_errors::{codes::*, struct_span_code_err}; -use rustc_hir as hir; use rustc_hir::Unsafety; -use rustc_middle::ty::{TraitRef, TyCtxt}; +use rustc_middle::ty::{ImplPolarity::*, ImplTraitHeader, TyCtxt}; use rustc_span::def_id::LocalDefId; use rustc_span::ErrorGuaranteed; pub(super) fn check_item( tcx: TyCtxt<'_>, def_id: LocalDefId, - trait_ref: TraitRef<'_>, + trait_header: ImplTraitHeader<'_>, ) -> Result<(), ErrorGuaranteed> { - let item = tcx.hir().expect_item(def_id); - let impl_ = item.expect_impl(); + let trait_ref = trait_header.trait_ref; let trait_def = tcx.trait_def(trait_ref.def_id); - let unsafe_attr = impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); - match (trait_def.unsafety, unsafe_attr, impl_.unsafety, impl_.polarity) { - (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => { + let unsafe_attr = + tcx.generics_of(def_id).params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); + match (trait_def.unsafety, unsafe_attr, trait_header.unsafety, trait_header.polarity) { + (Unsafety::Normal, None, Unsafety::Unsafe, Positive | Reservation) => { + let span = tcx.def_span(def_id); return Err(struct_span_code_err!( tcx.dcx(), tcx.def_span(def_id), @@ -27,7 +27,7 @@ pub(super) fn check_item( trait_ref.print_trait_sugared() ) .with_span_suggestion_verbose( - item.span.with_hi(item.span.lo() + rustc_span::BytePos(7)), + span.with_hi(span.lo() + rustc_span::BytePos(7)), "remove `unsafe` from this trait implementation", "", rustc_errors::Applicability::MachineApplicable, @@ -35,10 +35,11 @@ pub(super) fn check_item( .emit()); } - (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => { + (Unsafety::Unsafe, _, Unsafety::Normal, Positive | Reservation) => { + let span = tcx.def_span(def_id); return Err(struct_span_code_err!( tcx.dcx(), - tcx.def_span(def_id), + span, E0200, "the trait `{}` requires an `unsafe impl` declaration", trait_ref.print_trait_sugared() @@ -50,7 +51,7 @@ pub(super) fn check_item( trait_ref.print_trait_sugared() )) .with_span_suggestion_verbose( - item.span.shrink_to_lo(), + span.shrink_to_lo(), "add `unsafe` to this trait implementation", "unsafe ", rustc_errors::Applicability::MaybeIncorrect, @@ -58,10 +59,11 @@ pub(super) fn check_item( .emit()); } - (Unsafety::Normal, Some(attr_name), Unsafety::Normal, hir::ImplPolarity::Positive) => { + (Unsafety::Normal, Some(attr_name), Unsafety::Normal, Positive | Reservation) => { + let span = tcx.def_span(def_id); return Err(struct_span_code_err!( tcx.dcx(), - tcx.def_span(def_id), + span, E0569, "requires an `unsafe impl` declaration due to `#[{}]` attribute", attr_name @@ -73,7 +75,7 @@ pub(super) fn check_item( trait_ref.print_trait_sugared() )) .with_span_suggestion_verbose( - item.span.shrink_to_lo(), + span.shrink_to_lo(), "add `unsafe` to this trait implementation", "unsafe ", rustc_errors::Applicability::MaybeIncorrect, @@ -81,14 +83,14 @@ pub(super) fn check_item( .emit()); } - (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => { + (_, _, Unsafety::Unsafe, Negative) => { // Reported in AST validation - tcx.dcx().span_delayed_bug(item.span, "unsafe negative impl"); + tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "unsafe negative impl"); Ok(()) } - (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_)) - | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) - | (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) + (_, _, Unsafety::Normal, Negative) + | (Unsafety::Unsafe, _, Unsafety::Unsafe, Positive | Reservation) + | (Unsafety::Normal, Some(_), Unsafety::Unsafe, Positive | Reservation) | (Unsafety::Normal, None, Unsafety::Normal, _) => Ok(()), } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e8787d159ae12..4891dae47c66c 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1539,6 +1539,7 @@ fn impl_trait_header( }; ty::EarlyBinder::bind(ty::ImplTraitHeader { trait_ref, + unsafety: impl_.unsafety, polarity: polarity_of_impl(tcx, def_id, impl_, item.span) }) }) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6ee74ef2fb648..2d6c6cfbcd144 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -252,6 +252,7 @@ pub struct ImplHeader<'tcx> { pub struct ImplTraitHeader<'tcx> { pub trait_ref: ty::TraitRef<'tcx>, pub polarity: ImplPolarity, + pub unsafety: hir::Unsafety, } #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] From 55bbb054c937ea53de4e8bdc01b8c5eab82b9635 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 13 Feb 2024 09:29:31 +0000 Subject: [PATCH 2/6] Invoke `trait_def` query only once This may be a small performance boost as we have to hash less to lookup the value --- .../rustc_hir_analysis/src/coherence/mod.rs | 19 +++++++++++-------- .../src/coherence/unsafety.rs | 4 ++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index f1978a0fc3555..793458c4d8dfe 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -23,6 +23,7 @@ fn check_impl( tcx: TyCtxt<'_>, impl_def_id: LocalDefId, trait_ref: ty::TraitRef<'_>, + trait_def: &ty::TraitDef, ) -> Result<(), ErrorGuaranteed> { debug!( "(checking implementation) adding impl for trait '{:?}', item '{}'", @@ -36,19 +37,20 @@ fn check_impl( return Ok(()); } - enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id) - .and(enforce_empty_impls_for_marker_traits(tcx, impl_def_id, trait_ref.def_id)) + enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id, trait_def) + .and(enforce_empty_impls_for_marker_traits(tcx, impl_def_id, trait_ref.def_id, trait_def)) } fn enforce_trait_manually_implementable( tcx: TyCtxt<'_>, impl_def_id: LocalDefId, trait_def_id: DefId, + trait_def: &ty::TraitDef, ) -> Result<(), ErrorGuaranteed> { let impl_header_span = tcx.def_span(impl_def_id); // Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]` - if tcx.trait_def(trait_def_id).deny_explicit_impl { + if trait_def.deny_explicit_impl { let trait_name = tcx.item_name(trait_def_id); let mut err = struct_span_code_err!( tcx.dcx(), @@ -67,8 +69,7 @@ fn enforce_trait_manually_implementable( return Err(err.emit()); } - if let ty::trait_def::TraitSpecializationKind::AlwaysApplicable = - tcx.trait_def(trait_def_id).specialization_kind + if let ty::trait_def::TraitSpecializationKind::AlwaysApplicable = trait_def.specialization_kind { if !tcx.features().specialization && !tcx.features().min_specialization @@ -87,8 +88,9 @@ fn enforce_empty_impls_for_marker_traits( tcx: TyCtxt<'_>, impl_def_id: LocalDefId, trait_def_id: DefId, + trait_def: &ty::TraitDef, ) -> Result<(), ErrorGuaranteed> { - if !tcx.trait_def(trait_def_id).is_marker { + if !trait_def.is_marker { return Ok(()); } @@ -133,11 +135,12 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> for &impl_def_id in impls { let trait_header = tcx.impl_trait_header(impl_def_id).unwrap().instantiate_identity(); + let trait_def = tcx.trait_def(trait_header.trait_ref.def_id); - res = res.and(check_impl(tcx, impl_def_id, trait_header.trait_ref)); + res = res.and(check_impl(tcx, impl_def_id, trait_header.trait_ref, trait_def)); res = res.and(check_object_overlap(tcx, impl_def_id, trait_header.trait_ref)); - res = res.and(unsafety::check_item(tcx, impl_def_id, trait_header)); + res = res.and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def)); res = res.and(tcx.ensure().orphan_check_impl(impl_def_id)); res = res.and(builtin::check_trait(tcx, def_id, impl_def_id)); } diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index 158d010b05d37..688760a391269 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -3,7 +3,7 @@ use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir::Unsafety; -use rustc_middle::ty::{ImplPolarity::*, ImplTraitHeader, TyCtxt}; +use rustc_middle::ty::{ImplPolarity::*, ImplTraitHeader, TraitDef, TyCtxt}; use rustc_span::def_id::LocalDefId; use rustc_span::ErrorGuaranteed; @@ -11,9 +11,9 @@ pub(super) fn check_item( tcx: TyCtxt<'_>, def_id: LocalDefId, trait_header: ImplTraitHeader<'_>, + trait_def: &TraitDef, ) -> Result<(), ErrorGuaranteed> { let trait_ref = trait_header.trait_ref; - let trait_def = tcx.trait_def(trait_ref.def_id); let unsafe_attr = tcx.generics_of(def_id).params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); match (trait_def.unsafety, unsafe_attr, trait_header.unsafety, trait_header.polarity) { From 40b3cb0eb15528e6a5469a3d783908f4bd1cf731 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 13 Feb 2024 09:38:13 +0000 Subject: [PATCH 3/6] Don't reinvoke `trait_header` query twice --- .../src/coherence/builtin.rs | 20 +++++++++---------- .../rustc_hir_analysis/src/coherence/mod.rs | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 370c6c607d7b2..a2efa0c99a2a8 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -25,10 +25,11 @@ use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::{self, ObligationCause}; use std::collections::BTreeMap; -pub fn check_trait( - tcx: TyCtxt<'_>, +pub fn check_trait<'tcx>( + tcx: TyCtxt<'tcx>, trait_def_id: DefId, impl_def_id: LocalDefId, + impl_header: ty::ImplTraitHeader<'tcx>, ) -> Result<(), ErrorGuaranteed> { let lang_items = tcx.lang_items(); let checker = Checker { tcx, trait_def_id, impl_def_id }; @@ -40,10 +41,9 @@ pub fn check_trait( res = res.and( checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized), ); - res.and( - checker - .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn), - ) + res.and(checker.check(lang_items.dispatch_from_dyn_trait(), |tcx, id| { + visit_implementation_of_dispatch_from_dyn(tcx, id, impl_header.trait_ref) + })) } struct Checker<'tcx> { @@ -151,9 +151,10 @@ fn visit_implementation_of_coerce_unsized( tcx.at(span).ensure().coerce_unsized_info(impl_did) } -fn visit_implementation_of_dispatch_from_dyn( - tcx: TyCtxt<'_>, +fn visit_implementation_of_dispatch_from_dyn<'tcx>( + tcx: TyCtxt<'tcx>, impl_did: LocalDefId, + trait_ref: ty::TraitRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did); @@ -161,10 +162,9 @@ fn visit_implementation_of_dispatch_from_dyn( let dispatch_from_dyn_trait = tcx.require_lang_item(LangItem::DispatchFromDyn, Some(span)); - let source = tcx.type_of(impl_did).instantiate_identity(); + let source = trait_ref.self_ty(); assert!(!source.has_escaping_bound_vars()); let target = { - let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().instantiate_identity(); assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait); trait_ref.args.type_at(1) diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 793458c4d8dfe..d6281fa08f745 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -142,7 +142,7 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> res = res.and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def)); res = res.and(tcx.ensure().orphan_check_impl(impl_def_id)); - res = res.and(builtin::check_trait(tcx, def_id, impl_def_id)); + res = res.and(builtin::check_trait(tcx, def_id, impl_def_id, trait_header)); } res From 75de6cf9a3ad324779886867797a3fc53e2654a7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 13 Feb 2024 09:43:33 +0000 Subject: [PATCH 4/6] Avoid using the HIR span in the happy path --- .../rustc_hir_analysis/src/coherence/builtin.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index a2efa0c99a2a8..827eb27cbe389 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -15,7 +15,7 @@ use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt}; use rustc_infer::traits::Obligation; use rustc_middle::ty::adjustment::CoerceUnsizedInfo; use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::misc::{ type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy, @@ -95,18 +95,20 @@ fn visit_implementation_of_copy( 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); + let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did); match type_allowed_to_implement_copy(tcx, param_env, self_type, cause) { Ok(()) => Ok(()), Err(CopyImplementationError::InfringingFields(fields)) => { + let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span; Err(infringing_fields_error(tcx, fields, LangItem::Copy, impl_did, span)) } Err(CopyImplementationError::NotAnAdt) => { + let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span; Err(tcx.dcx().emit_err(errors::CopyImplOnNonAdt { span })) } Err(CopyImplementationError::HasDestructor) => { + let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span; Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span })) } } @@ -124,15 +126,16 @@ fn visit_implementation_of_const_param_ty( 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); + let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did); match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) { Ok(()) => Ok(()), Err(ConstParamTyImplementationError::InfrigingFields(fields)) => { + let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span; Err(infringing_fields_error(tcx, fields, LangItem::ConstParamTy, impl_did, span)) } Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => { + let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span; Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnNonAdt { span })) } } From 251c33ce2a60ce07d891728e0250188167c0be55 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 13 Feb 2024 10:15:29 +0000 Subject: [PATCH 5/6] Remove an `impl_polarity` call where the information is already available in the header --- .../src/coherence/builtin.rs | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 827eb27cbe389..cefecbb5ce687 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -33,11 +33,15 @@ pub fn check_trait<'tcx>( ) -> Result<(), ErrorGuaranteed> { let lang_items = tcx.lang_items(); 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( - checker.check(lang_items.const_param_ty_trait(), visit_implementation_of_const_param_ty), - ); + let mut res = checker.check(lang_items.drop_trait(), |tcx, id| { + visit_implementation_of_drop(tcx, id, impl_header) + }); + res = res.and(checker.check(lang_items.copy_trait(), |tcx, id| { + visit_implementation_of_copy(tcx, id, impl_header) + })); + res = res.and(checker.check(lang_items.const_param_ty_trait(), |tcx, id| { + visit_implementation_of_const_param_ty(tcx, id, impl_header) + })); res = res.and( checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized), ); @@ -62,12 +66,13 @@ impl<'tcx> Checker<'tcx> { } } -fn visit_implementation_of_drop( - tcx: TyCtxt<'_>, +fn visit_implementation_of_drop<'tcx>( + tcx: TyCtxt<'tcx>, impl_did: LocalDefId, + header: ty::ImplTraitHeader<'tcx>, ) -> Result<(), ErrorGuaranteed> { // Destructors only work on local ADT types. - match tcx.type_of(impl_did).instantiate_identity().kind() { + match header.trait_ref.self_ty().kind() { ty::Adt(def, _) if def.did().is_local() => return Ok(()), ty::Error(_) => return Ok(()), _ => {} @@ -78,13 +83,14 @@ fn visit_implementation_of_drop( Err(tcx.dcx().emit_err(errors::DropImplOnWrongItem { span: impl_.self_ty.span })) } -fn visit_implementation_of_copy( - tcx: TyCtxt<'_>, +fn visit_implementation_of_copy<'tcx>( + tcx: TyCtxt<'tcx>, impl_did: LocalDefId, + impl_header: ty::ImplTraitHeader<'tcx>, ) -> Result<(), ErrorGuaranteed> { debug!("visit_implementation_of_copy: impl_did={:?}", impl_did); - let self_type = tcx.type_of(impl_did).instantiate_identity(); + let self_type = impl_header.trait_ref.self_ty(); debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type); let param_env = tcx.param_env(impl_did); @@ -92,7 +98,7 @@ fn visit_implementation_of_copy( debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type); - if let ty::ImplPolarity::Negative = tcx.impl_polarity(impl_did) { + if let ty::ImplPolarity::Negative = impl_header.polarity { return Ok(()); } @@ -114,16 +120,17 @@ fn visit_implementation_of_copy( } } -fn visit_implementation_of_const_param_ty( - tcx: TyCtxt<'_>, +fn visit_implementation_of_const_param_ty<'tcx>( + tcx: TyCtxt<'tcx>, impl_did: LocalDefId, + header: ty::ImplTraitHeader<'tcx>, ) -> Result<(), ErrorGuaranteed> { - let self_type = tcx.type_of(impl_did).instantiate_identity(); + let self_type = header.trait_ref.self_ty(); assert!(!self_type.has_escaping_bound_vars()); let param_env = tcx.param_env(impl_did); - if let ty::ImplPolarity::Negative = tcx.impl_polarity(impl_did) { + if let ty::ImplPolarity::Negative = header.polarity { return Ok(()); } From 7320623f3a646bcd6eba661d14cd6f3891ede495 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 13 Feb 2024 10:23:06 +0000 Subject: [PATCH 6/6] Just pass the checker instead of individual fields --- .../src/coherence/builtin.rs | 72 +++++++++---------- 1 file changed, 33 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index cefecbb5ce687..6c3a9b747ef61 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -32,45 +32,42 @@ pub fn check_trait<'tcx>( impl_header: ty::ImplTraitHeader<'tcx>, ) -> Result<(), ErrorGuaranteed> { let lang_items = tcx.lang_items(); - let checker = Checker { tcx, trait_def_id, impl_def_id }; - let mut res = checker.check(lang_items.drop_trait(), |tcx, id| { - visit_implementation_of_drop(tcx, id, impl_header) - }); - res = res.and(checker.check(lang_items.copy_trait(), |tcx, id| { - visit_implementation_of_copy(tcx, id, impl_header) - })); - res = res.and(checker.check(lang_items.const_param_ty_trait(), |tcx, id| { - visit_implementation_of_const_param_ty(tcx, id, impl_header) - })); + let checker = Checker { tcx, trait_def_id, impl_def_id, impl_header }; + 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( + checker.check(lang_items.const_param_ty_trait(), visit_implementation_of_const_param_ty), + ); res = res.and( checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized), ); - res.and(checker.check(lang_items.dispatch_from_dyn_trait(), |tcx, id| { - visit_implementation_of_dispatch_from_dyn(tcx, id, impl_header.trait_ref) - })) + res.and( + checker + .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn), + ) } struct Checker<'tcx> { tcx: TyCtxt<'tcx>, trait_def_id: DefId, impl_def_id: LocalDefId, + impl_header: ty::ImplTraitHeader<'tcx>, } impl<'tcx> Checker<'tcx> { fn check( &self, trait_def_id: Option, - f: impl FnOnce(TyCtxt<'tcx>, LocalDefId) -> Result<(), ErrorGuaranteed>, + f: impl FnOnce(&Self) -> Result<(), ErrorGuaranteed>, ) -> Result<(), ErrorGuaranteed> { - if Some(self.trait_def_id) == trait_def_id { f(self.tcx, self.impl_def_id) } else { Ok(()) } + if Some(self.trait_def_id) == trait_def_id { f(self) } else { Ok(()) } } } -fn visit_implementation_of_drop<'tcx>( - tcx: TyCtxt<'tcx>, - impl_did: LocalDefId, - header: ty::ImplTraitHeader<'tcx>, -) -> Result<(), ErrorGuaranteed> { +fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { + let tcx = checker.tcx; + let header = checker.impl_header; + let impl_did = checker.impl_def_id; // Destructors only work on local ADT types. match header.trait_ref.self_ty().kind() { ty::Adt(def, _) if def.did().is_local() => return Ok(()), @@ -83,11 +80,10 @@ fn visit_implementation_of_drop<'tcx>( Err(tcx.dcx().emit_err(errors::DropImplOnWrongItem { span: impl_.self_ty.span })) } -fn visit_implementation_of_copy<'tcx>( - tcx: TyCtxt<'tcx>, - impl_did: LocalDefId, - impl_header: ty::ImplTraitHeader<'tcx>, -) -> Result<(), ErrorGuaranteed> { +fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { + let tcx = checker.tcx; + let impl_header = checker.impl_header; + let impl_did = checker.impl_def_id; debug!("visit_implementation_of_copy: impl_did={:?}", impl_did); let self_type = impl_header.trait_ref.self_ty(); @@ -120,11 +116,10 @@ fn visit_implementation_of_copy<'tcx>( } } -fn visit_implementation_of_const_param_ty<'tcx>( - tcx: TyCtxt<'tcx>, - impl_did: LocalDefId, - header: ty::ImplTraitHeader<'tcx>, -) -> Result<(), ErrorGuaranteed> { +fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { + let tcx = checker.tcx; + let header = checker.impl_header; + let impl_did = checker.impl_def_id; let self_type = header.trait_ref.self_ty(); assert!(!self_type.has_escaping_bound_vars()); @@ -148,10 +143,9 @@ fn visit_implementation_of_const_param_ty<'tcx>( } } -fn visit_implementation_of_coerce_unsized( - tcx: TyCtxt<'_>, - impl_did: LocalDefId, -) -> Result<(), ErrorGuaranteed> { +fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { + let tcx = checker.tcx; + let impl_did = checker.impl_def_id; debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did); // Just compute this for the side-effects, in particular reporting @@ -161,11 +155,11 @@ fn visit_implementation_of_coerce_unsized( tcx.at(span).ensure().coerce_unsized_info(impl_did) } -fn visit_implementation_of_dispatch_from_dyn<'tcx>( - tcx: TyCtxt<'tcx>, - impl_did: LocalDefId, - trait_ref: ty::TraitRef<'tcx>, -) -> Result<(), ErrorGuaranteed> { +fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { + let tcx = checker.tcx; + let header = checker.impl_header; + let impl_did = checker.impl_def_id; + let trait_ref = header.trait_ref; debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did); let span = tcx.def_span(impl_did);