diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index d3cfd61e1956..6d731ac3f759 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -922,7 +922,6 @@ pub fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>( pub fn provide(providers: &mut ty::query::Providers) { object_safety::provide(providers); - structural_match::provide(providers); *providers = ty::query::Providers { specialization_graph_of: specialize::specialization_graph_provider, specializes: specialize::specializes, diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index 40dbe0b3ff06..4dc08e0f9dab 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -1,10 +1,5 @@ -use crate::infer::{InferCtxt, TyCtxtInferExt}; -use crate::traits::{ObligationCause, ObligationCtxt}; - use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; -use rustc_hir::lang_items::LangItem; -use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_span::Span; use std::ops::ControlFlow; @@ -59,41 +54,6 @@ pub fn search_for_adt_const_param_violation<'tcx>( .break_value() } -/// This method returns true if and only if `adt_ty` itself has been marked as -/// eligible for structural-match: namely, if it implements both -/// `StructuralPartialEq` and `StructuralEq` (which are respectively injected by -/// `#[derive(PartialEq)]` and `#[derive(Eq)]`). -/// -/// Note that this does *not* recursively check if the substructure of `adt_ty` -/// implements the traits. -fn type_marked_structural<'tcx>( - infcx: &InferCtxt<'tcx>, - adt_ty: Ty<'tcx>, - cause: ObligationCause<'tcx>, -) -> bool { - let ocx = ObligationCtxt::new(infcx); - // require `#[derive(PartialEq)]` - let structural_peq_def_id = - infcx.tcx.require_lang_item(LangItem::StructuralPeq, Some(cause.span)); - ocx.register_bound(cause.clone(), ty::ParamEnv::empty(), adt_ty, structural_peq_def_id); - // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around - // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.) - let structural_teq_def_id = - infcx.tcx.require_lang_item(LangItem::StructuralTeq, Some(cause.span)); - ocx.register_bound(cause, ty::ParamEnv::empty(), adt_ty, structural_teq_def_id); - - // We deliberately skip *reporting* fulfillment errors (via - // `report_fulfillment_errors`), for two reasons: - // - // 1. The error messages would mention `std::marker::StructuralPartialEq` - // (a trait which is solely meant as an implementation detail - // for now), and - // - // 2. We are sometimes doing future-incompatibility lints for - // now, so we do not want unconditional errors here. - ocx.select_all_or_error().is_empty() -} - /// This implements the traversal over the structure of a given type to try to /// find instances of ADTs (specifically structs or enums) that do not implement /// the structural-match traits (`StructuralPartialEq` and `StructuralEq`). @@ -249,11 +209,3 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> { }) } } - -pub fn provide(providers: &mut Providers) { - providers.has_structural_eq_impls = |tcx, ty| { - let infcx = tcx.infer_ctxt().build(); - let cause = ObligationCause::dummy(); - type_marked_structural(&infcx, ty, cause) - }; -} diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index cce5a79ddc85..7ad5cbc01ccf 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -29,6 +29,7 @@ mod layout; mod layout_sanity_check; mod needs_drop; pub mod representability; +mod structural_match; mod ty; pub fn provide(providers: &mut Providers) { @@ -42,4 +43,5 @@ pub fn provide(providers: &mut Providers) { representability::provide(providers); ty::provide(providers); instance::provide(providers); + structural_match::provide(providers); } diff --git a/compiler/rustc_ty_utils/src/structural_match.rs b/compiler/rustc_ty_utils/src/structural_match.rs new file mode 100644 index 000000000000..a55bb7e7e904 --- /dev/null +++ b/compiler/rustc_ty_utils/src/structural_match.rs @@ -0,0 +1,44 @@ +use rustc_hir::lang_items::LangItem; +use rustc_middle::ty::query::Providers; +use rustc_middle::ty::{self, Ty, TyCtxt}; + +use rustc_infer::infer::TyCtxtInferExt; +use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; + +/// This method returns true if and only if `adt_ty` itself has been marked as +/// eligible for structural-match: namely, if it implements both +/// `StructuralPartialEq` and `StructuralEq` (which are respectively injected by +/// `#[derive(PartialEq)]` and `#[derive(Eq)]`). +/// +/// Note that this does *not* recursively check if the substructure of `adt_ty` +/// implements the traits. +fn has_structural_eq_impls<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool { + let ref infcx = tcx.infer_ctxt().build(); + let cause = ObligationCause::dummy(); + + let ocx = ObligationCtxt::new(infcx); + // require `#[derive(PartialEq)]` + let structural_peq_def_id = + infcx.tcx.require_lang_item(LangItem::StructuralPeq, Some(cause.span)); + ocx.register_bound(cause.clone(), ty::ParamEnv::empty(), adt_ty, structural_peq_def_id); + // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around + // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.) + let structural_teq_def_id = + infcx.tcx.require_lang_item(LangItem::StructuralTeq, Some(cause.span)); + ocx.register_bound(cause, ty::ParamEnv::empty(), adt_ty, structural_teq_def_id); + + // We deliberately skip *reporting* fulfillment errors (via + // `report_fulfillment_errors`), for two reasons: + // + // 1. The error messages would mention `std::marker::StructuralPartialEq` + // (a trait which is solely meant as an implementation detail + // for now), and + // + // 2. We are sometimes doing future-incompatibility lints for + // now, so we do not want unconditional errors here. + ocx.select_all_or_error().is_empty() +} + +pub fn provide(providers: &mut Providers) { + providers.has_structural_eq_impls = has_structural_eq_impls; +}