Skip to content

Commit 22b311b

Browse files
committed
Extract impl_subject_and_oglibations fn and make equate receive subjects
1 parent 64df2ee commit 22b311b

File tree

4 files changed

+93
-46
lines changed

4 files changed

+93
-46
lines changed

compiler/rustc_infer/src/infer/at.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
use super::*;
2929

3030
use rustc_middle::ty::relate::{Relate, TypeRelation};
31-
use rustc_middle::ty::Const;
31+
use rustc_middle::ty::{Const, ImplSubject};
3232

3333
pub struct At<'a, 'tcx> {
3434
pub infcx: &'a InferCtxt<'a, 'tcx>,
@@ -272,6 +272,29 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
272272
}
273273
}
274274

275+
impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> {
276+
fn to_trace(
277+
tcx: TyCtxt<'tcx>,
278+
cause: &ObligationCause<'tcx>,
279+
a_is_expected: bool,
280+
a: Self,
281+
b: Self,
282+
) -> TypeTrace<'tcx> {
283+
match (a, b) {
284+
(ImplSubject::Trait(trait_ref_a), ImplSubject::Trait(trait_ref_b)) => {
285+
ToTrace::to_trace(tcx, cause, a_is_expected, trait_ref_a, trait_ref_b)
286+
}
287+
(ImplSubject::Inherent(ty_a), ImplSubject::Inherent(ty_b)) => {
288+
ToTrace::to_trace(tcx, cause, a_is_expected, ty_a, ty_b)
289+
}
290+
(ImplSubject::Trait(_), ImplSubject::Inherent(_))
291+
| (ImplSubject::Inherent(_), ImplSubject::Trait(_)) => {
292+
bug!("can not trace TraitRef and Ty");
293+
}
294+
}
295+
}
296+
}
297+
275298
impl<'tcx> ToTrace<'tcx> for Ty<'tcx> {
276299
fn to_trace(
277300
_: TyCtxt<'tcx>,

compiler/rustc_middle/src/ty/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ use rustc_span::symbol::{kw, Ident, Symbol};
4444
use rustc_span::Span;
4545
use rustc_target::abi::Align;
4646

47+
use std::fmt::Debug;
4748
use std::hash::Hash;
4849
use std::ops::ControlFlow;
4950
use std::{fmt, str};
@@ -172,7 +173,7 @@ pub struct ImplHeader<'tcx> {
172173
pub predicates: Vec<Predicate<'tcx>>,
173174
}
174175

175-
#[derive(Debug)]
176+
#[derive(Copy, Clone, Debug, TypeFoldable)]
176177
pub enum ImplSubject<'tcx> {
177178
Trait(TraitRef<'tcx>),
178179
Inherent(Ty<'tcx>),

compiler/rustc_middle/src/ty/relate.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use crate::mir::interpret::{get_slice_bytes, ConstValue, GlobalAlloc, Scalar};
88
use crate::ty::error::{ExpectedFound, TypeError};
99
use crate::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
10-
use crate::ty::{self, Term, Ty, TyCtxt, TypeFoldable};
10+
use crate::ty::{self, ImplSubject, Term, Ty, TyCtxt, TypeFoldable};
1111
use rustc_hir as ast;
1212
use rustc_hir::def_id::DefId;
1313
use rustc_span::DUMMY_SP;
@@ -356,6 +356,30 @@ impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
356356
}
357357
}
358358

359+
impl<'tcx> Relate<'tcx> for ImplSubject<'tcx> {
360+
#[inline]
361+
fn relate<R: TypeRelation<'tcx>>(
362+
relation: &mut R,
363+
a: ImplSubject<'tcx>,
364+
b: ImplSubject<'tcx>,
365+
) -> RelateResult<'tcx, ImplSubject<'tcx>> {
366+
match (a, b) {
367+
(ImplSubject::Trait(trait_ref_a), ImplSubject::Trait(trait_ref_b)) => {
368+
let trait_ref = ty::TraitRef::relate(relation, trait_ref_a, trait_ref_b)?;
369+
Ok(ImplSubject::Trait(trait_ref))
370+
}
371+
(ImplSubject::Inherent(ty_a), ImplSubject::Inherent(ty_b)) => {
372+
let ty = Ty::relate(relation, ty_a, ty_b)?;
373+
Ok(ImplSubject::Inherent(ty))
374+
}
375+
(ImplSubject::Trait(_), ImplSubject::Inherent(_))
376+
| (ImplSubject::Inherent(_), ImplSubject::Trait(_)) => {
377+
bug!("can not relate TraitRef and Ty");
378+
}
379+
}
380+
}
381+
}
382+
359383
impl<'tcx> Relate<'tcx> for Ty<'tcx> {
360384
#[inline]
361385
fn relate<R: TypeRelation<'tcx>>(

compiler/rustc_trait_selection/src/traits/coherence.rs

+42-43
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use crate::traits::{
1717
use rustc_errors::Diagnostic;
1818
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
1919
use rustc_hir::CRATE_HIR_ID;
20-
use rustc_infer::infer::at::ToTrace;
2120
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
2221
use rustc_infer::traits::{util, TraitEngine};
2322
use rustc_middle::traits::specialization_graph::OverlapMode;
@@ -305,72 +304,72 @@ fn negative_impl<'cx, 'tcx>(
305304
// Create an infcx, taking the predicates of impl1 as assumptions:
306305
tcx.infer_ctxt().enter(|infcx| {
307306
// create a parameter environment corresponding to a (placeholder) instantiation of impl1
308-
let impl1_env = tcx.param_env(impl1_def_id);
309-
310-
match tcx.impl_subject(impl1_def_id) {
307+
let impl_env = tcx.param_env(impl1_def_id);
308+
let subject1 = match tcx.impl_subject(impl1_def_id) {
311309
ImplSubject::Trait(impl1_trait_ref) => {
312-
// Normalize the trait reference. The WF rules ought to ensure
313-
// that this always succeeds.
314-
let impl1_trait_ref = match traits::fully_normalize(
310+
match traits::fully_normalize(
315311
&infcx,
316312
FulfillmentContext::new(),
317313
ObligationCause::dummy(),
318-
impl1_env,
314+
impl_env,
319315
impl1_trait_ref,
320316
) {
321-
Ok(impl1_trait_ref) => impl1_trait_ref,
317+
Ok(impl1_trait_ref) => ImplSubject::Trait(impl1_trait_ref),
322318
Err(err) => {
323319
bug!("failed to fully normalize {:?}: {:?}", impl1_trait_ref, err);
324320
}
325-
};
321+
}
322+
}
323+
subject @ ImplSubject::Inherent(_) => subject,
324+
};
326325

327-
// Attempt to prove that impl2 applies, given all of the above.
328-
let selcx = &mut SelectionContext::new(&infcx);
329-
let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
330-
let (impl2_trait_ref, obligations) =
331-
impl_trait_ref_and_oblig(selcx, impl1_env, impl2_def_id, impl2_substs);
326+
let (subject2, obligations) =
327+
impl_subject_and_obligations(&infcx, impl_env, subject1, impl2_def_id);
332328

333-
!equate(
334-
&infcx,
335-
impl1_env,
336-
impl1_def_id,
337-
impl1_trait_ref,
338-
impl2_trait_ref,
339-
obligations,
340-
)
341-
}
342-
ImplSubject::Inherent(ty1) => {
343-
let ty2 = tcx.type_of(impl2_def_id);
344-
!equate(&infcx, impl1_env, impl1_def_id, ty1, ty2, iter::empty())
345-
}
346-
}
329+
!equate(&infcx, impl_env, impl1_def_id, subject1, subject2, obligations)
347330
})
348331
}
349332

350-
fn equate<'cx, 'tcx, T: Debug + ToTrace<'tcx>>(
333+
fn impl_subject_and_obligations<'cx, 'tcx>(
351334
infcx: &InferCtxt<'cx, 'tcx>,
352-
impl1_env: ty::ParamEnv<'tcx>,
335+
impl_env: ty::ParamEnv<'tcx>,
336+
subject1: ImplSubject<'tcx>,
337+
impl2_def_id: DefId,
338+
) -> (ImplSubject<'tcx>, Box<dyn Iterator<Item = PredicateObligation<'tcx>> + 'tcx>) {
339+
if let ImplSubject::Trait(_) = subject1 {
340+
// Attempt to prove that impl2 applies, given all of the above.
341+
let selcx = &mut SelectionContext::new(&infcx);
342+
let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
343+
let (impl2_trait_ref, obligations) =
344+
impl_trait_ref_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs);
345+
346+
(ImplSubject::Trait(impl2_trait_ref), Box::new(obligations))
347+
} else {
348+
(infcx.tcx.impl_subject(impl2_def_id), Box::new(iter::empty()))
349+
}
350+
}
351+
352+
fn equate<'cx, 'tcx>(
353+
infcx: &InferCtxt<'cx, 'tcx>,
354+
impl_env: ty::ParamEnv<'tcx>,
353355
impl1_def_id: DefId,
354-
impl1: T,
355-
impl2: T,
356+
subject1: ImplSubject<'tcx>,
357+
subject2: ImplSubject<'tcx>,
356358
obligations: impl Iterator<Item = PredicateObligation<'tcx>>,
357359
) -> bool {
358360
// do the impls unify? If not, not disjoint.
359-
let Ok(InferOk { obligations: more_obligations, .. }) = infcx
360-
.at(&ObligationCause::dummy(), impl1_env)
361-
.eq(impl1, impl2) else {
362-
debug!(
363-
"explicit_disjoint: {:?} does not unify with {:?}",
364-
impl1, impl2
365-
);
366-
return true;
367-
};
361+
let Ok(InferOk { obligations: more_obligations, .. }) =
362+
infcx.at(&ObligationCause::dummy(), impl_env).eq(subject1, subject2)
363+
else {
364+
debug!("explicit_disjoint: {:?} does not unify with {:?}", subject1, subject2);
365+
return true;
366+
};
368367

369368
let selcx = &mut SelectionContext::new(&infcx);
370369
let opt_failing_obligation = obligations
371370
.into_iter()
372371
.chain(more_obligations)
373-
.find(|o| negative_impl_exists(selcx, impl1_env, impl1_def_id, o));
372+
.find(|o| negative_impl_exists(selcx, impl_env, impl1_def_id, o));
374373

375374
if let Some(failing_obligation) = opt_failing_obligation {
376375
debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);

0 commit comments

Comments
 (0)