diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 07bbaa1926edf..b46a67d08eb03 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -1,14 +1,13 @@ //! Orphan checker: every impl either implements a trait defined in this //! crate or pertains to a type defined in this crate. +use crate::errors; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_middle::ty::{self, AliasKind, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::def_id::LocalDefId; use rustc_span::Span; -use rustc_trait_selection::traits; - -use crate::errors; +use rustc_trait_selection::traits::{self, IsFirstInputType}; #[instrument(skip(tcx), level = "debug")] pub(crate) fn orphan_check_impl( @@ -288,7 +287,7 @@ fn emit_orphan_check_error<'tcx>( (Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new()); let mut sugg = None; for &(mut ty, is_target_ty) in &tys { - let span = if is_target_ty { + let span = if matches!(is_target_ty, IsFirstInputType::Yes) { // Point at `D` in `impl for C in D` self_ty_span } else { @@ -321,7 +320,8 @@ fn emit_orphan_check_error<'tcx>( } } - let is_foreign = !trait_ref.def_id.is_local() && !is_target_ty; + let is_foreign = + !trait_ref.def_id.is_local() && matches!(is_target_ty, IsFirstInputType::No); match &ty.kind() { ty::Slice(_) => { diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index f663f02f87289..0d3169cec143c 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -598,9 +598,24 @@ pub fn trait_ref_is_local_or_fundamental<'tcx>( trait_ref.def_id.krate == LOCAL_CRATE || tcx.has_attr(trait_ref.def_id, sym::fundamental) } +#[derive(Debug, Copy, Clone)] +pub enum IsFirstInputType { + No, + Yes, +} + +impl From for IsFirstInputType { + fn from(b: bool) -> IsFirstInputType { + match b { + false => IsFirstInputType::No, + true => IsFirstInputType::Yes, + } + } +} + #[derive(Debug)] pub enum OrphanCheckErr<'tcx> { - NonLocalInputType(Vec<(Ty<'tcx>, bool /* Is this the first input type? */)>), + NonLocalInputType(Vec<(Ty<'tcx>, IsFirstInputType)>), UncoveredTy(Ty<'tcx>, Option>), } @@ -751,7 +766,7 @@ struct OrphanChecker<'tcx, F> { /// Ignore orphan check failures and exclusively search for the first /// local type. search_first_local_ty: bool, - non_local_tys: Vec<(Ty<'tcx>, bool)>, + non_local_tys: Vec<(Ty<'tcx>, IsFirstInputType)>, } impl<'tcx, F, E> OrphanChecker<'tcx, F> @@ -769,7 +784,7 @@ where } fn found_non_local_ty(&mut self, t: Ty<'tcx>) -> ControlFlow> { - self.non_local_tys.push((t, self.in_self_ty)); + self.non_local_tys.push((t, self.in_self_ty.into())); ControlFlow::Continue(()) } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 9eec60ea06c21..32447aca390a4 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -42,7 +42,7 @@ use std::fmt::Debug; use std::ops::ControlFlow; pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls}; -pub use self::coherence::{OrphanCheckErr, OverlapResult}; +pub use self::coherence::{IsFirstInputType, OrphanCheckErr, OverlapResult}; pub use self::engine::{ObligationCtxt, TraitEngineExt}; pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation}; pub use self::normalize::NormalizeExt;