From 218caa410aa38c29984be31a5229b9fa717560ee Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:13 +0200 Subject: Merging upstream version 1.68.2+dfsg1. Signed-off-by: Daniel Baumann --- .../rustc_trait_selection/src/traits/coherence.rs | 70 +++++++++++----------- 1 file changed, 34 insertions(+), 36 deletions(-) (limited to 'compiler/rustc_trait_selection/src/traits/coherence.rs') diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 899e30275..225c1050c 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -66,13 +66,13 @@ pub fn add_placeholder_note(err: &mut Diagnostic) { /// with a suitably-freshened `ImplHeader` with those types /// substituted. Otherwise, returns `None`. #[instrument(skip(tcx, skip_leak_check), level = "debug")] -pub fn overlapping_impls<'tcx>( - tcx: TyCtxt<'tcx>, +pub fn overlapping_impls( + tcx: TyCtxt<'_>, impl1_def_id: DefId, impl2_def_id: DefId, skip_leak_check: SkipLeakCheck, overlap_mode: OverlapMode, -) -> Option> { +) -> Option> { // Before doing expensive operations like entering an inference context, do // a quick check via fast_reject to tell if the impl headers could possibly // unify. @@ -80,7 +80,7 @@ pub fn overlapping_impls<'tcx>( let impl1_ref = tcx.impl_trait_ref(impl1_def_id); let impl2_ref = tcx.impl_trait_ref(impl2_def_id); let may_overlap = match (impl1_ref, impl2_ref) { - (Some(a), Some(b)) => iter::zip(a.substs, b.substs) + (Some(a), Some(b)) => iter::zip(a.skip_binder().substs, b.skip_binder().substs) .all(|(arg1, arg2)| drcx.generic_args_may_unify(arg1, arg2)), (None, None) => { let self_ty1 = tcx.type_of(impl1_def_id); @@ -126,7 +126,7 @@ fn with_fresh_ty_vars<'cx, 'tcx>( let header = ty::ImplHeader { impl_def_id, self_ty: tcx.bound_type_of(impl_def_id).subst(tcx, impl_substs), - trait_ref: tcx.bound_impl_trait_ref(impl_def_id).map(|i| i.subst(tcx, impl_substs)), + trait_ref: tcx.impl_trait_ref(impl_def_id).map(|i| i.subst(tcx, impl_substs)), predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates, }; @@ -283,7 +283,7 @@ fn implicit_negative<'cx, 'tcx>( /// Given impl1 and impl2 check if both impls are never satisfied by a common type (including /// where-clauses) If so, return true, they are disjoint and false otherwise. -fn negative_impl<'tcx>(tcx: TyCtxt<'tcx>, impl1_def_id: DefId, impl2_def_id: DefId) -> bool { +fn negative_impl(tcx: TyCtxt<'_>, impl1_def_id: DefId, impl2_def_id: DefId) -> bool { debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id); // Create an infcx, taking the predicates of impl1 as assumptions: @@ -401,12 +401,12 @@ fn resolve_negative_obligation<'tcx>( infcx.resolve_regions(&outlives_env).is_empty() } +#[instrument(level = "debug", skip(tcx), ret)] pub fn trait_ref_is_knowable<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: ty::TraitRef<'tcx>, ) -> Result<(), Conflict> { - debug!("trait_ref_is_knowable(trait_ref={:?})", trait_ref); - if orphan_check_trait_ref(tcx, trait_ref, InCrate::Remote).is_ok() { + if orphan_check_trait_ref(trait_ref, InCrate::Remote).is_ok() { // A downstream or cousin crate is allowed to implement some // substitution of this trait-ref. return Err(Conflict::Downstream); @@ -429,11 +429,9 @@ pub fn trait_ref_is_knowable<'tcx>( // and if we are an intermediate owner, then we don't care // about future-compatibility, which means that we're OK if // we are an owner. - if orphan_check_trait_ref(tcx, trait_ref, InCrate::Local).is_ok() { - debug!("trait_ref_is_knowable: orphan check passed"); + if orphan_check_trait_ref(trait_ref, InCrate::Local).is_ok() { Ok(()) } else { - debug!("trait_ref_is_knowable: nonlocal, nonfundamental, unowned"); Err(Conflict::Upstream) } } @@ -445,6 +443,7 @@ 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)] pub enum OrphanCheckErr<'tcx> { NonLocalInputType(Vec<(Ty<'tcx>, bool /* Is this the first input type? */)>), UncoveredTy(Ty<'tcx>, Option>), @@ -456,13 +455,12 @@ pub enum OrphanCheckErr<'tcx> { /// /// 1. All type parameters in `Self` must be "covered" by some local type constructor. /// 2. Some local type must appear in `Self`. +#[instrument(level = "debug", skip(tcx), ret)] pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanCheckErr<'_>> { - debug!("orphan_check({:?})", impl_def_id); - // We only except this routine to be invoked on implementations // of a trait, not inherent implementations. - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); - debug!("orphan_check: trait_ref={:?}", trait_ref); + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(); + debug!(?trait_ref); // If the *trait* is local to the crate, ok. if trait_ref.def_id.is_local() { @@ -470,7 +468,7 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe return Ok(()); } - orphan_check_trait_ref(tcx, trait_ref, InCrate::Local) + orphan_check_trait_ref(trait_ref, InCrate::Local) } /// Checks whether a trait-ref is potentially implementable by a crate. @@ -559,13 +557,11 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe /// /// Note that this function is never called for types that have both type /// parameters and inference variables. +#[instrument(level = "trace", ret)] fn orphan_check_trait_ref<'tcx>( - tcx: TyCtxt<'tcx>, trait_ref: ty::TraitRef<'tcx>, in_crate: InCrate, ) -> Result<(), OrphanCheckErr<'tcx>> { - debug!("orphan_check_trait_ref(trait_ref={:?}, in_crate={:?})", trait_ref, in_crate); - if trait_ref.needs_infer() && trait_ref.needs_subst() { bug!( "can't orphan check a trait ref with both params and inference variables {:?}", @@ -573,7 +569,7 @@ fn orphan_check_trait_ref<'tcx>( ); } - let mut checker = OrphanChecker::new(tcx, in_crate); + let mut checker = OrphanChecker::new(in_crate); match trait_ref.visit_with(&mut checker) { ControlFlow::Continue(()) => Err(OrphanCheckErr::NonLocalInputType(checker.non_local_tys)), ControlFlow::Break(OrphanCheckEarlyExit::ParamTy(ty)) => { @@ -592,7 +588,6 @@ fn orphan_check_trait_ref<'tcx>( } struct OrphanChecker<'tcx> { - tcx: TyCtxt<'tcx>, in_crate: InCrate, in_self_ty: bool, /// Ignore orphan check failures and exclusively search for the first @@ -602,9 +597,8 @@ struct OrphanChecker<'tcx> { } impl<'tcx> OrphanChecker<'tcx> { - fn new(tcx: TyCtxt<'tcx>, in_crate: InCrate) -> Self { + fn new(in_crate: InCrate) -> Self { OrphanChecker { - tcx, in_crate, in_self_ty: true, search_first_local_ty: false, @@ -614,12 +608,12 @@ impl<'tcx> OrphanChecker<'tcx> { fn found_non_local_ty(&mut self, t: Ty<'tcx>) -> ControlFlow> { self.non_local_tys.push((t, self.in_self_ty)); - ControlFlow::CONTINUE + ControlFlow::Continue(()) } fn found_param_ty(&mut self, t: Ty<'tcx>) -> ControlFlow> { if self.search_first_local_ty { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } else { ControlFlow::Break(OrphanCheckEarlyExit::ParamTy(t)) } @@ -641,7 +635,7 @@ enum OrphanCheckEarlyExit<'tcx> { impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> { type BreakTy = OrphanCheckEarlyExit<'tcx>; fn visit_region(&mut self, _r: ty::Region<'tcx>) -> ControlFlow { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { @@ -659,7 +653,7 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> { | ty::RawPtr(..) | ty::Never | ty::Tuple(..) - | ty::Projection(..) => self.found_non_local_ty(ty), + | ty::Alias(ty::Projection, ..) => self.found_non_local_ty(ty), ty::Param(..) => self.found_param_ty(ty), @@ -697,14 +691,18 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> { } } ty::Error(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)), - ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => { - self.tcx.sess.delay_span_bug( - DUMMY_SP, - format!("ty_is_local invoked on closure or generator: {:?}", ty), - ); - ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)) + ty::Closure(did, ..) | ty::Generator(did, ..) => { + if self.def_id_is_local(did) { + ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)) + } else { + self.found_non_local_ty(ty) + } } - ty::Opaque(..) => { + // This should only be created when checking whether we have to check whether some + // auto trait impl applies. There will never be multiple impls, so we can just + // act as if it were a local type here. + ty::GeneratorWitness(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)), + ty::Alias(ty::Opaque, ..) => { // This merits some explanation. // Normally, opaque types are not involved when performing // coherence checking, since it is illegal to directly @@ -749,13 +747,13 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> { /// /// This means that we can completely ignore constants during the orphan check. /// - /// See `src/test/ui/coherence/const-generics-orphan-check-ok.rs` for examples. + /// See `tests/ui/coherence/const-generics-orphan-check-ok.rs` for examples. /// /// [^1]: This might not hold for function pointers or trait objects in the future. /// As these should be quite rare as const arguments and especially rare as impl /// parameters, allowing uncovered const parameters in impls seems more useful /// than allowing `impl Trait for i32` to compile. fn visit_const(&mut self, _c: ty::Const<'tcx>) -> ControlFlow { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } -- cgit v1.2.3