summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_typeck/src/coherence/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_typeck/src/coherence/mod.rs')
-rw-r--r--compiler/rustc_typeck/src/coherence/mod.rs237
1 files changed, 0 insertions, 237 deletions
diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_typeck/src/coherence/mod.rs
deleted file mode 100644
index ae9ebe590..000000000
--- a/compiler/rustc_typeck/src/coherence/mod.rs
+++ /dev/null
@@ -1,237 +0,0 @@
-// Coherence phase
-//
-// The job of the coherence phase of typechecking is to ensure that
-// each trait has at most one implementation for each type. This is
-// done by the orphan and overlap modules. Then we build up various
-// mappings. That mapping code resides here.
-
-use rustc_errors::struct_span_err;
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
-use rustc_trait_selection::traits;
-
-mod builtin;
-mod inherent_impls;
-mod inherent_impls_overlap;
-mod orphan;
-mod unsafety;
-
-fn check_impl(tcx: TyCtxt<'_>, impl_def_id: LocalDefId, trait_ref: ty::TraitRef<'_>) {
- debug!(
- "(checking implementation) adding impl for trait '{:?}', item '{}'",
- trait_ref,
- tcx.def_path_str(impl_def_id.to_def_id())
- );
-
- // Skip impls where one of the self type is an error type.
- // This occurs with e.g., resolve failures (#30589).
- if trait_ref.references_error() {
- return;
- }
-
- enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id);
- enforce_empty_impls_for_marker_traits(tcx, impl_def_id, trait_ref.def_id);
-}
-
-fn enforce_trait_manually_implementable(
- tcx: TyCtxt<'_>,
- impl_def_id: LocalDefId,
- trait_def_id: DefId,
-) {
- let did = Some(trait_def_id);
- let li = tcx.lang_items();
- let impl_header_span = tcx.def_span(impl_def_id);
-
- // Disallow *all* explicit impls of `Pointee`, `DiscriminantKind`, `Sized` and `Unsize` for now.
- if did == li.pointee_trait() {
- struct_span_err!(
- tcx.sess,
- impl_header_span,
- E0322,
- "explicit impls for the `Pointee` trait are not permitted"
- )
- .span_label(impl_header_span, "impl of `Pointee` not allowed")
- .emit();
- return;
- }
-
- if did == li.discriminant_kind_trait() {
- struct_span_err!(
- tcx.sess,
- impl_header_span,
- E0322,
- "explicit impls for the `DiscriminantKind` trait are not permitted"
- )
- .span_label(impl_header_span, "impl of `DiscriminantKind` not allowed")
- .emit();
- return;
- }
-
- if did == li.sized_trait() {
- struct_span_err!(
- tcx.sess,
- impl_header_span,
- E0322,
- "explicit impls for the `Sized` trait are not permitted"
- )
- .span_label(impl_header_span, "impl of `Sized` not allowed")
- .emit();
- return;
- }
-
- if did == li.unsize_trait() {
- struct_span_err!(
- tcx.sess,
- impl_header_span,
- E0328,
- "explicit impls for the `Unsize` trait are not permitted"
- )
- .span_label(impl_header_span, "impl of `Unsize` not allowed")
- .emit();
- return;
- }
-
- if tcx.features().unboxed_closures {
- // the feature gate allows all Fn traits
- return;
- }
-
- if let ty::trait_def::TraitSpecializationKind::AlwaysApplicable =
- tcx.trait_def(trait_def_id).specialization_kind
- {
- if !tcx.features().specialization && !tcx.features().min_specialization {
- tcx.sess
- .struct_span_err(
- impl_header_span,
- "implementing `rustc_specialization_trait` traits is unstable",
- )
- .help("add `#![feature(min_specialization)]` to the crate attributes to enable")
- .emit();
- return;
- }
- }
-}
-
-/// We allow impls of marker traits to overlap, so they can't override impls
-/// as that could make it ambiguous which associated item to use.
-fn enforce_empty_impls_for_marker_traits(
- tcx: TyCtxt<'_>,
- impl_def_id: LocalDefId,
- trait_def_id: DefId,
-) {
- if !tcx.trait_def(trait_def_id).is_marker {
- return;
- }
-
- if tcx.associated_item_def_ids(trait_def_id).is_empty() {
- return;
- }
-
- struct_span_err!(
- tcx.sess,
- tcx.def_span(impl_def_id),
- E0715,
- "impls for marker traits cannot contain items"
- )
- .emit();
-}
-
-pub fn provide(providers: &mut Providers) {
- use self::builtin::coerce_unsized_info;
- use self::inherent_impls::{crate_incoherent_impls, crate_inherent_impls, inherent_impls};
- use self::inherent_impls_overlap::crate_inherent_impls_overlap_check;
- use self::orphan::orphan_check_impl;
-
- *providers = Providers {
- coherent_trait,
- crate_inherent_impls,
- crate_incoherent_impls,
- inherent_impls,
- crate_inherent_impls_overlap_check,
- coerce_unsized_info,
- orphan_check_impl,
- ..*providers
- };
-}
-
-fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
- // Trigger building the specialization graph for the trait. This will detect and report any
- // overlap errors.
- tcx.ensure().specialization_graph_of(def_id);
-
- let impls = tcx.hir().trait_impls(def_id);
- for &impl_def_id in impls {
- let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
-
- check_impl(tcx, impl_def_id, trait_ref);
- check_object_overlap(tcx, impl_def_id, trait_ref);
-
- tcx.sess.time("unsafety_checking", || unsafety::check_item(tcx, impl_def_id));
- tcx.sess.time("orphan_checking", || tcx.ensure().orphan_check_impl(impl_def_id));
- }
-
- builtin::check_trait(tcx, def_id);
-}
-
-/// Checks whether an impl overlaps with the automatic `impl Trait for dyn Trait`.
-fn check_object_overlap<'tcx>(
- tcx: TyCtxt<'tcx>,
- impl_def_id: LocalDefId,
- trait_ref: ty::TraitRef<'tcx>,
-) {
- let trait_def_id = trait_ref.def_id;
-
- if trait_ref.references_error() {
- debug!("coherence: skipping impl {:?} with error {:?}", impl_def_id, trait_ref);
- return;
- }
-
- // check for overlap with the automatic `impl Trait for dyn Trait`
- if let ty::Dynamic(data, ..) = trait_ref.self_ty().kind() {
- // This is something like impl Trait1 for Trait2. Illegal
- // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
-
- let component_def_ids = data.iter().flat_map(|predicate| {
- match predicate.skip_binder() {
- ty::ExistentialPredicate::Trait(tr) => Some(tr.def_id),
- ty::ExistentialPredicate::AutoTrait(def_id) => Some(def_id),
- // An associated type projection necessarily comes with
- // an additional `Trait` requirement.
- ty::ExistentialPredicate::Projection(..) => None,
- }
- });
-
- for component_def_id in component_def_ids {
- if !tcx.is_object_safe(component_def_id) {
- // Without the 'object_safe_for_dispatch' feature this is an error
- // which will be reported by wfcheck. Ignore it here.
- // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
- // With the feature enabled, the trait is not implemented automatically,
- // so this is valid.
- } else {
- let mut supertrait_def_ids = traits::supertrait_def_ids(tcx, component_def_id);
- if supertrait_def_ids.any(|d| d == trait_def_id) {
- let span = tcx.def_span(impl_def_id);
- struct_span_err!(
- tcx.sess,
- span,
- E0371,
- "the object type `{}` automatically implements the trait `{}`",
- trait_ref.self_ty(),
- tcx.def_path_str(trait_def_id)
- )
- .span_label(
- span,
- format!(
- "`{}` automatically implements trait `{}`",
- trait_ref.self_ty(),
- tcx.def_path_str(trait_def_id)
- ),
- )
- .emit();
- }
- }
- }
- }
-}