Skip to content

Commit fe62bc5

Browse files
authored
Rollup merge of #124623 - lcnr:coherence-uwu, r=compiler-errors
shallow resolve in orphan check r? ``@compiler-errors`` cc #124588 (review)
2 parents 6cc3959 + c4e882f commit fe62bc5

File tree

5 files changed

+44
-36
lines changed

5 files changed

+44
-36
lines changed

Diff for: compiler/rustc_hir_analysis/src/coherence/orphan.rs

+1
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ fn orphan_check<'tcx>(
330330
};
331331

332332
let Ok(result) = traits::orphan_check_trait_ref::<!>(
333+
&infcx,
333334
trait_ref,
334335
traits::InCrate::Local { mode },
335336
lazily_normalize_ty,

Diff for: compiler/rustc_trait_selection/src/solve/assembly/mod.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use crate::solve::GoalSource;
44
use crate::solve::{inspect, EvalCtxt, SolverMode};
5-
use crate::traits::coherence;
65
use rustc_hir::def_id::DefId;
76
use rustc_infer::traits::query::NoSolution;
87
use rustc_middle::traits::solve::inspect::ProbeKind;
@@ -769,13 +768,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
769768
candidates.extend(self.probe_trait_candidate(CandidateSource::CoherenceUnknowable).enter(
770769
|ecx| {
771770
let trait_ref = goal.predicate.trait_ref(tcx);
772-
let lazily_normalize_ty = |ty| ecx.structurally_normalize_ty(goal.param_env, ty);
773-
774-
match coherence::trait_ref_is_knowable(tcx, trait_ref, lazily_normalize_ty)? {
775-
Ok(()) => Err(NoSolution),
776-
Err(_) => {
777-
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
778-
}
771+
if ecx.trait_ref_is_knowable(goal.param_env, trait_ref)? {
772+
Err(NoSolution)
773+
} else {
774+
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
779775
}
780776
},
781777
))

Diff for: compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use rustc_span::DUMMY_SP;
2727
use std::io::Write;
2828
use std::ops::ControlFlow;
2929

30+
use crate::traits::coherence;
3031
use crate::traits::vtable::{count_own_vtable_entries, prepare_vtable_segments, VtblSegment};
3132

3233
use super::inspect::ProofTreeBuilder;
@@ -942,6 +943,17 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
942943
}
943944
}
944945

946+
pub(super) fn trait_ref_is_knowable(
947+
&mut self,
948+
param_env: ty::ParamEnv<'tcx>,
949+
trait_ref: ty::TraitRef<'tcx>,
950+
) -> Result<bool, NoSolution> {
951+
let infcx = self.infcx;
952+
let lazily_normalize_ty = |ty| self.structurally_normalize_ty(param_env, ty);
953+
coherence::trait_ref_is_knowable(infcx, trait_ref, lazily_normalize_ty)
954+
.map(|is_knowable| is_knowable.is_ok())
955+
}
956+
945957
pub(super) fn can_define_opaque_ty(&self, def_id: impl Into<DefId>) -> bool {
946958
self.infcx.can_define_opaque_ty(def_id)
947959
}

Diff for: compiler/rustc_trait_selection/src/traits/coherence.rs

+26-27
Original file line numberDiff line numberDiff line change
@@ -618,19 +618,20 @@ fn try_prove_negated_where_clause<'tcx>(
618618
/// This both checks whether any downstream or sibling crates could
619619
/// implement it and whether an upstream crate can add this impl
620620
/// without breaking backwards compatibility.
621-
#[instrument(level = "debug", skip(tcx, lazily_normalize_ty), ret)]
621+
#[instrument(level = "debug", skip(infcx, lazily_normalize_ty), ret)]
622622
pub fn trait_ref_is_knowable<'tcx, E: Debug>(
623-
tcx: TyCtxt<'tcx>,
623+
infcx: &InferCtxt<'tcx>,
624624
trait_ref: ty::TraitRef<'tcx>,
625625
mut lazily_normalize_ty: impl FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>,
626626
) -> Result<Result<(), Conflict>, E> {
627-
if orphan_check_trait_ref(trait_ref, InCrate::Remote, &mut lazily_normalize_ty)?.is_ok() {
627+
if orphan_check_trait_ref(infcx, trait_ref, InCrate::Remote, &mut lazily_normalize_ty)?.is_ok()
628+
{
628629
// A downstream or cousin crate is allowed to implement some
629630
// generic parameters of this trait-ref.
630631
return Ok(Err(Conflict::Downstream));
631632
}
632633

633-
if trait_ref_is_local_or_fundamental(tcx, trait_ref) {
634+
if trait_ref_is_local_or_fundamental(infcx.tcx, trait_ref) {
634635
// This is a local or fundamental trait, so future-compatibility
635636
// is no concern. We know that downstream/cousin crates are not
636637
// allowed to implement a generic parameter of this trait ref,
@@ -648,6 +649,7 @@ pub fn trait_ref_is_knowable<'tcx, E: Debug>(
648649
// about future-compatibility, which means that we're OK if
649650
// we are an owner.
650651
if orphan_check_trait_ref(
652+
infcx,
651653
trait_ref,
652654
InCrate::Local { mode: OrphanCheckMode::Proper },
653655
&mut lazily_normalize_ty,
@@ -786,46 +788,41 @@ pub struct UncoveredTyParams<'tcx, T> {
786788
///
787789
/// Note that this function is never called for types that have both type
788790
/// parameters and inference variables.
789-
#[instrument(level = "trace", skip(lazily_normalize_ty), ret)]
791+
#[instrument(level = "trace", skip(infcx, lazily_normalize_ty), ret)]
790792
pub fn orphan_check_trait_ref<'tcx, E: Debug>(
793+
infcx: &InferCtxt<'tcx>,
791794
trait_ref: ty::TraitRef<'tcx>,
792795
in_crate: InCrate,
793796
lazily_normalize_ty: impl FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>,
794797
) -> Result<Result<(), OrphanCheckErr<'tcx, Ty<'tcx>>>, E> {
795-
if trait_ref.has_infer() && trait_ref.has_param() {
796-
bug!(
797-
"can't orphan check a trait ref with both params and inference variables {:?}",
798-
trait_ref
799-
);
798+
if trait_ref.has_param() {
799+
bug!("orphan check only expects inference variables: {trait_ref:?}");
800800
}
801801

802-
let mut checker = OrphanChecker::new(in_crate, lazily_normalize_ty);
803-
804-
// Does there exist some local type after the `ParamTy`.
805-
let search_first_local_ty = |checker: &mut OrphanChecker<'tcx, _>| {
806-
checker.search_first_local_ty = true;
807-
match trait_ref.visit_with(checker).break_value() {
808-
Some(OrphanCheckEarlyExit::LocalTy(local_ty)) => Some(local_ty),
809-
_ => None,
810-
}
811-
};
812-
802+
let mut checker = OrphanChecker::new(infcx, in_crate, lazily_normalize_ty);
813803
Ok(match trait_ref.visit_with(&mut checker) {
814804
ControlFlow::Continue(()) => Err(OrphanCheckErr::NonLocalInputType(checker.non_local_tys)),
815805
ControlFlow::Break(residual) => match residual {
816806
OrphanCheckEarlyExit::NormalizationFailure(err) => return Err(err),
817807
OrphanCheckEarlyExit::UncoveredTyParam(ty) => {
808+
// Does there exist some local type after the `ParamTy`.
809+
checker.search_first_local_ty = true;
810+
let local_ty = match trait_ref.visit_with(&mut checker).break_value() {
811+
Some(OrphanCheckEarlyExit::LocalTy(local_ty)) => Some(local_ty),
812+
_ => None,
813+
};
818814
Err(OrphanCheckErr::UncoveredTyParams(UncoveredTyParams {
819815
uncovered: ty,
820-
local_ty: search_first_local_ty(&mut checker),
816+
local_ty,
821817
}))
822818
}
823819
OrphanCheckEarlyExit::LocalTy(_) => Ok(()),
824820
},
825821
})
826822
}
827823

828-
struct OrphanChecker<'tcx, F> {
824+
struct OrphanChecker<'a, 'tcx, F> {
825+
infcx: &'a InferCtxt<'tcx>,
829826
in_crate: InCrate,
830827
in_self_ty: bool,
831828
lazily_normalize_ty: F,
@@ -834,12 +831,13 @@ struct OrphanChecker<'tcx, F> {
834831
non_local_tys: Vec<(Ty<'tcx>, IsFirstInputType)>,
835832
}
836833

837-
impl<'tcx, F, E> OrphanChecker<'tcx, F>
834+
impl<'a, 'tcx, F, E> OrphanChecker<'a, 'tcx, F>
838835
where
839836
F: FnOnce(Ty<'tcx>) -> Result<Ty<'tcx>, E>,
840837
{
841-
fn new(in_crate: InCrate, lazily_normalize_ty: F) -> Self {
838+
fn new(infcx: &'a InferCtxt<'tcx>, in_crate: InCrate, lazily_normalize_ty: F) -> Self {
842839
OrphanChecker {
840+
infcx,
843841
in_crate,
844842
in_self_ty: true,
845843
lazily_normalize_ty,
@@ -878,7 +876,7 @@ enum OrphanCheckEarlyExit<'tcx, E> {
878876
LocalTy(Ty<'tcx>),
879877
}
880878

881-
impl<'tcx, F, E> TypeVisitor<TyCtxt<'tcx>> for OrphanChecker<'tcx, F>
879+
impl<'a, 'tcx, F, E> TypeVisitor<TyCtxt<'tcx>> for OrphanChecker<'a, 'tcx, F>
882880
where
883881
F: FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>,
884882
{
@@ -889,6 +887,7 @@ where
889887
}
890888

891889
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
890+
let ty = self.infcx.shallow_resolve(ty);
892891
let ty = match (self.lazily_normalize_ty)(ty) {
893892
Ok(norm_ty) if norm_ty.is_ty_var() => ty,
894893
Ok(norm_ty) => norm_ty,
@@ -1149,7 +1148,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
11491148
};
11501149

11511150
infcx.probe(|_| {
1152-
match trait_ref_is_knowable(infcx.tcx, trait_ref, lazily_normalize_ty) {
1151+
match trait_ref_is_knowable(infcx, trait_ref, lazily_normalize_ty) {
11531152
Err(()) => {}
11541153
Ok(Ok(())) => warn!("expected an unknowable trait ref: {trait_ref:?}"),
11551154
Ok(Err(conflict)) => {

Diff for: compiler/rustc_trait_selection/src/traits/select/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1497,7 +1497,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14971497
// bound regions.
14981498
let trait_ref = predicate.skip_binder().trait_ref;
14991499

1500-
coherence::trait_ref_is_knowable::<!>(self.tcx(), trait_ref, |ty| Ok(ty)).unwrap()
1500+
coherence::trait_ref_is_knowable::<!>(self.infcx, trait_ref, |ty| Ok(ty)).unwrap()
15011501
}
15021502

15031503
/// Returns `true` if the global caches can be used.

0 commit comments

Comments
 (0)