Skip to content

Commit 0cd03c9

Browse files
committed
Extract ImplSubject information
1 parent 91b5214 commit 0cd03c9

File tree

3 files changed

+52
-39
lines changed

3 files changed

+52
-39
lines changed

compiler/rustc_middle/src/hir/mod.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ pub mod nested_filter;
77
pub mod place;
88

99
use crate::ty::query::Providers;
10-
use crate::ty::TyCtxt;
10+
use crate::ty::{ImplSubject, TyCtxt};
1111
use rustc_data_structures::fingerprint::Fingerprint;
1212
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
13-
use rustc_hir::def_id::LocalDefId;
13+
use rustc_hir::def_id::{DefId, LocalDefId};
1414
use rustc_hir::*;
1515
use rustc_query_system::ich::StableHashingContext;
1616
use rustc_span::DUMMY_SP;
@@ -54,6 +54,12 @@ impl<'tcx> TyCtxt<'tcx> {
5454
pub fn parent_module(self, id: HirId) -> LocalDefId {
5555
self.parent_module_from_def_id(id.owner)
5656
}
57+
58+
pub fn impl_header(self, def_id: DefId) -> ImplSubject<'tcx> {
59+
self.impl_trait_ref(def_id)
60+
.map(ImplSubject::Trait)
61+
.unwrap_or_else(|| ImplSubject::Inherent(self.type_of(def_id)))
62+
}
5763
}
5864

5965
pub fn provide(providers: &mut Providers) {

compiler/rustc_middle/src/ty/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,12 @@ pub struct ImplHeader<'tcx> {
172172
pub predicates: Vec<Predicate<'tcx>>,
173173
}
174174

175+
#[derive(Debug)]
176+
pub enum ImplSubject<'tcx> {
177+
Trait(TraitRef<'tcx>),
178+
Inherent(Ty<'tcx>),
179+
}
180+
175181
#[derive(
176182
Copy,
177183
Clone,

compiler/rustc_trait_selection/src/traits/coherence.rs

+38-37
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use rustc_middle::traits::specialization_graph::OverlapMode;
2424
use rustc_middle::ty::fast_reject::{self, TreatParams};
2525
use rustc_middle::ty::fold::TypeFoldable;
2626
use rustc_middle::ty::subst::Subst;
27-
use rustc_middle::ty::{self, Ty, TyCtxt};
27+
use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt};
2828
use rustc_span::symbol::sym;
2929
use rustc_span::DUMMY_SP;
3030
use std::fmt::Debug;
@@ -307,46 +307,47 @@ fn negative_impl<'cx, 'tcx>(
307307
// create a parameter environment corresponding to a (placeholder) instantiation of impl1
308308
let impl1_env = tcx.param_env(impl1_def_id);
309309

310-
if let Some(impl1_trait_ref) = tcx.impl_trait_ref(impl1_def_id) {
311-
// Normalize the trait reference. The WF rules ought to ensure
312-
// that this always succeeds.
313-
let impl1_trait_ref = match traits::fully_normalize(
314-
&infcx,
315-
FulfillmentContext::new(),
316-
ObligationCause::dummy(),
317-
impl1_env,
318-
impl1_trait_ref,
319-
) {
320-
Ok(impl1_trait_ref) => impl1_trait_ref,
321-
Err(err) => {
322-
bug!("failed to fully normalize {:?}: {:?}", impl1_trait_ref, err);
323-
}
324-
};
325-
326-
// Attempt to prove that impl2 applies, given all of the above.
327-
let selcx = &mut SelectionContext::new(&infcx);
328-
let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
329-
let (impl2_trait_ref, obligations) =
330-
impl_trait_ref_and_oblig(selcx, impl1_env, impl2_def_id, impl2_substs);
331-
332-
!obligations_satisfiable(
333-
&infcx,
334-
impl1_env,
335-
impl1_def_id,
336-
impl1_trait_ref,
337-
impl2_trait_ref,
338-
obligations,
339-
)
340-
} else {
341-
let ty1 = tcx.type_of(impl1_def_id);
342-
let ty2 = tcx.type_of(impl2_def_id);
343-
344-
!obligations_satisfiable(&infcx, impl1_env, impl1_def_id, ty1, ty2, iter::empty())
310+
match tcx.impl_header(impl1_def_id) {
311+
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(
315+
&infcx,
316+
FulfillmentContext::new(),
317+
ObligationCause::dummy(),
318+
impl1_env,
319+
impl1_trait_ref,
320+
) {
321+
Ok(impl1_trait_ref) => impl1_trait_ref,
322+
Err(err) => {
323+
bug!("failed to fully normalize {:?}: {:?}", impl1_trait_ref, err);
324+
}
325+
};
326+
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);
332+
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+
}
345346
}
346347
})
347348
}
348349

349-
fn obligations_satisfiable<'cx, 'tcx, T: Debug + ToTrace<'tcx>>(
350+
fn equate<'cx, 'tcx, T: Debug + ToTrace<'tcx>>(
350351
infcx: &InferCtxt<'cx, 'tcx>,
351352
impl1_env: ty::ParamEnv<'tcx>,
352353
impl1_def_id: DefId,

0 commit comments

Comments
 (0)