Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a711662

Browse files
committedFeb 11, 2024
Auto merge of #120919 - oli-obk:impl_polarity, r=<try>
Merge `impl_polarity` and `impl_trait_ref` queries Hopefully this is perf neutral. I wan to finish #120835 and stop using the HIR in `coherent_trait`, which should then give us a perf improvement.
2 parents 9aa232e + 1ce3522 commit a711662

File tree

22 files changed

+151
-131
lines changed

22 files changed

+151
-131
lines changed
 

‎compiler/rustc_hir_analysis/src/astconv/mod.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,9 +1671,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
16711671
.is_accessible_from(self.item_def_id(), tcx)
16721672
&& tcx.all_impls(*trait_def_id)
16731673
.any(|impl_def_id| {
1674-
let trait_ref = tcx.impl_trait_ref(impl_def_id);
1675-
trait_ref.is_some_and(|trait_ref| {
1676-
let impl_ = trait_ref.instantiate(
1674+
let impl_header = tcx.impl_trait_header(impl_def_id);
1675+
impl_header.is_some_and(|header| {
1676+
let header = header.instantiate(
16771677
tcx,
16781678
infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
16791679
);
@@ -1685,11 +1685,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
16851685
infcx
16861686
.can_eq(
16871687
ty::ParamEnv::empty(),
1688-
impl_.self_ty(),
1688+
header.trait_ref.self_ty(),
16891689
value,
1690-
)
1690+
) && header.polarity != ty::ImplPolarity::Negative
16911691
})
1692-
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
16931692
})
16941693
})
16951694
.map(|trait_def_id| tcx.def_path_str(trait_def_id))
@@ -1735,13 +1734,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
17351734
} else {
17361735
// Find all the types that have an `impl` for the trait.
17371736
tcx.all_impls(trait_def_id)
1738-
.filter(|impl_def_id| {
1737+
.filter_map(|impl_def_id| tcx.impl_trait_header(impl_def_id))
1738+
.filter(|header| {
17391739
// Consider only accessible traits
17401740
tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
1741-
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
1741+
&& header.skip_binder().polarity != ty::ImplPolarity::Negative
17421742
})
1743-
.filter_map(|impl_def_id| tcx.impl_trait_ref(impl_def_id))
1744-
.map(|impl_| impl_.instantiate_identity().self_ty())
1743+
.map(|header| header.instantiate_identity().trait_ref.self_ty())
17451744
// We don't care about blanket impls.
17461745
.filter(|self_ty| !self_ty.has_non_region_param())
17471746
.map(|self_ty| tcx.erase_regions(self_ty).to_string())

‎compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -474,8 +474,12 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
474474
}
475475
DefKind::Fn => {} // entirely within check_item_body
476476
DefKind::Impl { of_trait } => {
477-
if of_trait && let Some(impl_trait_ref) = tcx.impl_trait_ref(def_id) {
478-
check_impl_items_against_trait(tcx, def_id, impl_trait_ref.instantiate_identity());
477+
if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) {
478+
check_impl_items_against_trait(
479+
tcx,
480+
def_id,
481+
impl_trait_header.instantiate_identity(),
482+
);
479483
check_on_unimplemented(tcx, def_id);
480484
}
481485
}
@@ -666,19 +670,19 @@ pub(super) fn check_specialization_validity<'tcx>(
666670
fn check_impl_items_against_trait<'tcx>(
667671
tcx: TyCtxt<'tcx>,
668672
impl_id: LocalDefId,
669-
impl_trait_ref: ty::TraitRef<'tcx>,
673+
impl_trait_header: ty::ImplTraitHeader<'tcx>,
670674
) {
671675
// If the trait reference itself is erroneous (so the compilation is going
672676
// to fail), skip checking the items here -- the `impl_item` table in `tcx`
673677
// isn't populated for such impls.
674-
if impl_trait_ref.references_error() {
678+
if impl_trait_header.references_error() {
675679
return;
676680
}
677681

678682
let impl_item_refs = tcx.associated_item_def_ids(impl_id);
679683

680684
// Negative impls are not expected to have any items
681-
match tcx.impl_polarity(impl_id) {
685+
match impl_trait_header.polarity {
682686
ty::ImplPolarity::Reservation | ty::ImplPolarity::Positive => {}
683687
ty::ImplPolarity::Negative => {
684688
if let [first_item_ref, ..] = impl_item_refs {
@@ -695,7 +699,7 @@ fn check_impl_items_against_trait<'tcx>(
695699
}
696700
}
697701

698-
let trait_def = tcx.trait_def(impl_trait_ref.def_id);
702+
let trait_def = tcx.trait_def(impl_trait_header.trait_ref.def_id);
699703

700704
for &impl_item in impl_item_refs {
701705
let ty_impl_item = tcx.associated_item(impl_item);
@@ -714,10 +718,10 @@ fn check_impl_items_against_trait<'tcx>(
714718
));
715719
}
716720
ty::AssocKind::Fn => {
717-
compare_impl_method(tcx, ty_impl_item, ty_trait_item, impl_trait_ref);
721+
compare_impl_method(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref);
718722
}
719723
ty::AssocKind::Type => {
720-
compare_impl_ty(tcx, ty_impl_item, ty_trait_item, impl_trait_ref);
724+
compare_impl_ty(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref);
721725
}
722726
}
723727

@@ -737,7 +741,7 @@ fn check_impl_items_against_trait<'tcx>(
737741
let mut must_implement_one_of: Option<&[Ident]> =
738742
trait_def.must_implement_one_of.as_deref();
739743

740-
for &trait_item_id in tcx.associated_item_def_ids(impl_trait_ref.def_id) {
744+
for &trait_item_id in tcx.associated_item_def_ids(impl_trait_header.trait_ref.def_id) {
741745
let leaf_def = ancestors.leaf_def(tcx, trait_item_id);
742746

743747
let is_implemented = leaf_def
@@ -815,7 +819,7 @@ fn check_impl_items_against_trait<'tcx>(
815819

816820
if let Some(missing_items) = must_implement_one_of {
817821
let attr_span = tcx
818-
.get_attr(impl_trait_ref.def_id, sym::rustc_must_implement_one_of)
822+
.get_attr(impl_trait_header.trait_ref.def_id, sym::rustc_must_implement_one_of)
819823
.map(|attr| attr.span);
820824

821825
missing_items_must_implement_one_of_err(

‎compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,9 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
245245
// won't be allowed unless there's an *explicit* implementation of `Send`
246246
// for `T`
247247
hir::ItemKind::Impl(impl_) => {
248-
let is_auto = tcx
249-
.impl_trait_ref(def_id)
250-
.is_some_and(|trait_ref| tcx.trait_is_auto(trait_ref.skip_binder().def_id));
248+
let header = tcx.impl_trait_header(def_id);
249+
let is_auto = header
250+
.is_some_and(|header| tcx.trait_is_auto(header.skip_binder().trait_ref.def_id));
251251
let mut res = Ok(());
252252
if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
253253
let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
@@ -259,11 +259,11 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
259259
.emit());
260260
}
261261
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
262-
match tcx.impl_polarity(def_id) {
263-
ty::ImplPolarity::Positive => {
262+
match header.map(|h| h.skip_binder().polarity) {
263+
Some(ty::ImplPolarity::Positive) | None => {
264264
res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait));
265265
}
266-
ty::ImplPolarity::Negative => {
266+
Some(ty::ImplPolarity::Negative) => {
267267
let ast::ImplPolarity::Negative(span) = impl_.polarity else {
268268
bug!("impl_polarity query disagrees with impl's polarity in AST");
269269
};
@@ -280,7 +280,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
280280
.emit());
281281
}
282282
}
283-
ty::ImplPolarity::Reservation => {
283+
Some(ty::ImplPolarity::Reservation) => {
284284
// FIXME: what amount of WF checking do we need for reservation impls?
285285
}
286286
}

‎compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ pub fn provide(providers: &mut Providers) {
7878
trait_def,
7979
adt_def,
8080
fn_sig,
81-
impl_trait_ref,
82-
impl_polarity,
81+
impl_trait_header,
8382
coroutine_kind,
8483
coroutine_for_closure,
8584
collect_mod_item_types,
@@ -601,7 +600,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
601600
hir::ItemKind::Impl { .. } => {
602601
tcx.ensure().generics_of(def_id);
603602
tcx.ensure().type_of(def_id);
604-
tcx.ensure().impl_trait_ref(def_id);
603+
tcx.ensure().impl_trait_header(def_id);
605604
tcx.ensure().predicates_of(def_id);
606605
}
607606
hir::ItemKind::Trait(..) => {
@@ -1326,19 +1325,20 @@ fn suggest_impl_trait<'tcx>(
13261325
None
13271326
}
13281327

1329-
fn impl_trait_ref(
1328+
fn impl_trait_header(
13301329
tcx: TyCtxt<'_>,
13311330
def_id: LocalDefId,
1332-
) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
1331+
) -> Option<ty::EarlyBinder<ty::ImplTraitHeader<'_>>> {
13331332
let icx = ItemCtxt::new(tcx, def_id);
1334-
let impl_ = tcx.hir().expect_item(def_id).expect_impl();
1333+
let item = tcx.hir().expect_item(def_id);
1334+
let impl_ = item.expect_impl();
13351335
impl_
13361336
.of_trait
13371337
.as_ref()
13381338
.map(|ast_trait_ref| {
13391339
let selfty = tcx.type_of(def_id).instantiate_identity();
13401340

1341-
if let Some(ErrorGuaranteed { .. }) = check_impl_constness(
1341+
let trait_ref = if let Some(ErrorGuaranteed { .. }) = check_impl_constness(
13421342
tcx,
13431343
tcx.is_const_trait_impl_raw(def_id.to_def_id()),
13441344
ast_trait_ref,
@@ -1363,9 +1363,12 @@ fn impl_trait_ref(
13631363
icx.astconv().instantiate_mono_trait_ref(trait_ref, selfty)
13641364
} else {
13651365
icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty)
1366-
}
1366+
};
1367+
ty::EarlyBinder::bind(ty::ImplTraitHeader {
1368+
trait_ref,
1369+
polarity: polarity_of_impl_item(tcx, def_id, impl_, item.span)
1370+
})
13671371
})
1368-
.map(ty::EarlyBinder::bind)
13691372
}
13701373

13711374
fn check_impl_constness(
@@ -1393,43 +1396,34 @@ fn check_impl_constness(
13931396
}))
13941397
}
13951398

1396-
fn impl_polarity(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplPolarity {
1399+
fn polarity_of_impl_item(
1400+
tcx: TyCtxt<'_>,
1401+
def_id: LocalDefId,
1402+
impl_: &hir::Impl<'_>,
1403+
span: Span,
1404+
) -> ty::ImplPolarity {
13971405
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
1398-
let item = tcx.hir().expect_item(def_id);
1399-
match &item.kind {
1400-
hir::ItemKind::Impl(hir::Impl {
1401-
polarity: hir::ImplPolarity::Negative(span),
1402-
of_trait,
1403-
..
1404-
}) => {
1406+
match &impl_ {
1407+
hir::Impl { polarity: hir::ImplPolarity::Negative(span), of_trait, .. } => {
14051408
if is_rustc_reservation {
14061409
let span = span.to(of_trait.as_ref().map_or(*span, |t| t.path.span));
14071410
tcx.dcx().span_err(span, "reservation impls can't be negative");
14081411
}
14091412
ty::ImplPolarity::Negative
14101413
}
1411-
hir::ItemKind::Impl(hir::Impl {
1412-
polarity: hir::ImplPolarity::Positive,
1413-
of_trait: None,
1414-
..
1415-
}) => {
1414+
hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => {
14161415
if is_rustc_reservation {
1417-
tcx.dcx().span_err(item.span, "reservation impls can't be inherent");
1416+
tcx.dcx().span_err(span, "reservation impls can't be inherent");
14181417
}
14191418
ty::ImplPolarity::Positive
14201419
}
1421-
hir::ItemKind::Impl(hir::Impl {
1422-
polarity: hir::ImplPolarity::Positive,
1423-
of_trait: Some(_),
1424-
..
1425-
}) => {
1420+
hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: Some(_), .. } => {
14261421
if is_rustc_reservation {
14271422
ty::ImplPolarity::Reservation
14281423
} else {
14291424
ty::ImplPolarity::Positive
14301425
}
14311426
}
1432-
item => bug!("impl_polarity: {:?} not an impl", item),
14331427
}
14341428
}
14351429

‎compiler/rustc_hir_typeck/src/method/suggest.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3136,12 +3136,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31363136
if self
31373137
.tcx
31383138
.all_impls(candidate.def_id)
3139-
.filter(|imp_did| {
3140-
self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
3139+
.filter_map(|imp_did| self.tcx.impl_trait_header(imp_did))
3140+
.filter(|header| {
3141+
header.skip_binder().polarity == ty::ImplPolarity::Negative
31413142
})
3142-
.any(|imp_did| {
3143-
let imp =
3144-
self.tcx.impl_trait_ref(imp_did).unwrap().instantiate_identity();
3143+
.any(|header| {
3144+
let imp = header.instantiate_identity().trait_ref;
31453145
let imp_simp =
31463146
simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup);
31473147
imp_simp.is_some_and(|s| s == simp_rcvr_ty)

‎compiler/rustc_incremental/src/persist/dirty_clean.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ const BASE_HIR: &[&str] = &[
6363

6464
/// `impl` implementation of struct/trait
6565
const BASE_IMPL: &[&str] =
66-
&[label_strs::associated_item_def_ids, label_strs::generics_of, label_strs::impl_trait_ref];
66+
&[label_strs::associated_item_def_ids, label_strs::generics_of, label_strs::impl_trait_header];
6767

6868
/// DepNodes for mir_built/Optimized, which is relevant in "executable"
6969
/// code, i.e., functions+methods

‎compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ provide! { tcx, def_id, other, cdata,
215215
variances_of => { table }
216216
fn_sig => { table }
217217
codegen_fn_attrs => { table }
218-
impl_trait_ref => { table }
218+
impl_trait_header => { table }
219219
const_param_default => { table }
220220
object_lifetime_default => { table }
221221
thir_abstract_const => { table }
@@ -234,7 +234,6 @@ provide! { tcx, def_id, other, cdata,
234234
unused_generic_params => { cdata.root.tables.unused_generic_params.get(cdata, def_id.index) }
235235
def_kind => { cdata.def_kind(def_id.index) }
236236
impl_parent => { table }
237-
impl_polarity => { table_direct }
238237
defaultness => { table_direct }
239238
constness => { table_direct }
240239
coerce_unsized_info => {

‎compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1962,10 +1962,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
19621962
let def_id = id.owner_id.to_def_id();
19631963

19641964
self.tables.defaultness.set_some(def_id.index, tcx.defaultness(def_id));
1965-
self.tables.impl_polarity.set_some(def_id.index, tcx.impl_polarity(def_id));
19661965

1967-
if of_trait && let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
1968-
record!(self.tables.impl_trait_ref[def_id] <- trait_ref);
1966+
if of_trait && let Some(header) = tcx.impl_trait_header(def_id) {
1967+
record!(self.tables.impl_trait_header[def_id] <- header);
1968+
let trait_ref = header.map_bound(|h| h.trait_ref);
19691969

19701970
let trait_ref = trait_ref.instantiate_identity();
19711971
let simplified_self_ty = fast_reject::simplify_type(

‎compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ define_tables! {
423423
variances_of: Table<DefIndex, LazyArray<ty::Variance>>,
424424
fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::PolyFnSig<'static>>>>,
425425
codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>,
426-
impl_trait_ref: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::TraitRef<'static>>>>,
426+
impl_trait_header: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::ImplTraitHeader<'static>>>>,
427427
const_param_default: Table<DefIndex, LazyValue<ty::EarlyBinder<rustc_middle::ty::Const<'static>>>>,
428428
object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>,
429429
optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>,
@@ -433,7 +433,6 @@ define_tables! {
433433
promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>,
434434
thir_abstract_const: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::Const<'static>>>>,
435435
impl_parent: Table<DefIndex, RawDefId>,
436-
impl_polarity: Table<DefIndex, ty::ImplPolarity>,
437436
constness: Table<DefIndex, hir::Constness>,
438437
defaultness: Table<DefIndex, hir::Defaultness>,
439438
// FIXME(eddyb) perhaps compute this on the fly if cheap enough?

‎compiler/rustc_middle/src/query/erase.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ impl EraseType for Option<mir::DestructuredConstant<'_>> {
177177
type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()];
178178
}
179179

180-
impl EraseType for Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
181-
type Result = [u8; size_of::<Option<ty::EarlyBinder<ty::TraitRef<'static>>>>()];
180+
impl EraseType for Option<ty::EarlyBinder<ty::ImplTraitHeader<'_>>> {
181+
type Result = [u8; size_of::<Option<ty::EarlyBinder<ty::ImplTraitHeader<'static>>>>()];
182182
}
183183

184184
impl EraseType for Option<ty::EarlyBinder<Ty<'_>>> {

‎compiler/rustc_middle/src/query/mod.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -846,17 +846,13 @@ rustc_queries! {
846846
cache_on_disk_if { true }
847847
}
848848

849-
/// Given an `impl_id`, return the trait it implements.
849+
/// Given an `impl_id`, return the trait it implements along with some header information.
850850
/// Return `None` if this is an inherent impl.
851-
query impl_trait_ref(impl_id: DefId) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> {
851+
query impl_trait_header(impl_id: DefId) -> Option<ty::EarlyBinder<ty::ImplTraitHeader<'tcx>>> {
852852
desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) }
853853
cache_on_disk_if { impl_id.is_local() }
854854
separate_provide_extern
855855
}
856-
query impl_polarity(impl_id: DefId) -> ty::ImplPolarity {
857-
desc { |tcx| "computing implementation polarity of `{}`", tcx.def_path_str(impl_id) }
858-
separate_provide_extern
859-
}
860856

861857
query issue33140_self_ty(key: DefId) -> Option<ty::EarlyBinder<ty::Ty<'tcx>>> {
862858
desc { |tcx| "computing Self type wrt issue #33140 `{}`", tcx.def_path_str(key) }

‎compiler/rustc_middle/src/ty/context.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2308,6 +2308,20 @@ impl<'tcx> TyCtxt<'tcx> {
23082308
pub fn module_children_local(self, def_id: LocalDefId) -> &'tcx [ModChild] {
23092309
self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..])
23102310
}
2311+
2312+
/// Given an `impl_id`, return the trait it implements.
2313+
/// Return `None` if this is an inherent impl.
2314+
pub fn impl_trait_ref(
2315+
self,
2316+
def_id: impl IntoQueryParam<DefId>,
2317+
) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> {
2318+
Some(self.impl_trait_header(def_id)?.map_bound(|h| h.trait_ref))
2319+
}
2320+
2321+
pub fn impl_polarity(self, def_id: impl IntoQueryParam<DefId>) -> ty::ImplPolarity {
2322+
self.impl_trait_header(def_id)
2323+
.map_or(ty::ImplPolarity::Positive, |h| h.skip_binder().polarity)
2324+
}
23112325
}
23122326

23132327
/// Parameter attributes that can only be determined by examining the body of a function instead

‎compiler/rustc_middle/src/ty/mod.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ pub struct ImplHeader<'tcx> {
248248
pub predicates: Vec<Predicate<'tcx>>,
249249
}
250250

251+
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, TyEncodable, TyDecodable, HashStable)]
252+
pub struct ImplTraitHeader<'tcx> {
253+
pub trait_ref: ty::TraitRef<'tcx>,
254+
pub polarity: ImplPolarity,
255+
}
256+
251257
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
252258
pub enum ImplSubject<'tcx> {
253259
Trait(TraitRef<'tcx>),
@@ -1584,17 +1590,16 @@ impl<'tcx> TyCtxt<'tcx> {
15841590
def_id1: DefId,
15851591
def_id2: DefId,
15861592
) -> Option<ImplOverlapKind> {
1587-
let impl_trait_ref1 = self.impl_trait_ref(def_id1);
1588-
let impl_trait_ref2 = self.impl_trait_ref(def_id2);
1593+
let impl1 = self.impl_trait_header(def_id1).unwrap().instantiate_identity();
1594+
let impl2 = self.impl_trait_header(def_id2).unwrap().instantiate_identity();
1595+
15891596
// If either trait impl references an error, they're allowed to overlap,
15901597
// as one of them essentially doesn't exist.
1591-
if impl_trait_ref1.is_some_and(|tr| tr.instantiate_identity().references_error())
1592-
|| impl_trait_ref2.is_some_and(|tr| tr.instantiate_identity().references_error())
1593-
{
1598+
if impl1.references_error() || impl2.references_error() {
15941599
return Some(ImplOverlapKind::Permitted { marker: false });
15951600
}
15961601

1597-
match (self.impl_polarity(def_id1), self.impl_polarity(def_id2)) {
1602+
match (impl1.polarity, impl2.polarity) {
15981603
(ImplPolarity::Reservation, _) | (_, ImplPolarity::Reservation) => {
15991604
// `#[rustc_reservation_impl]` impls don't overlap with anything
16001605
return Some(ImplOverlapKind::Permitted { marker: false });
@@ -1609,10 +1614,9 @@ impl<'tcx> TyCtxt<'tcx> {
16091614
};
16101615

16111616
let is_marker_overlap = {
1612-
let is_marker_impl = |trait_ref: Option<EarlyBinder<TraitRef<'_>>>| -> bool {
1613-
trait_ref.is_some_and(|tr| self.trait_def(tr.skip_binder().def_id).is_marker)
1614-
};
1615-
is_marker_impl(impl_trait_ref1) && is_marker_impl(impl_trait_ref2)
1617+
let is_marker_impl =
1618+
|trait_ref: TraitRef<'_>| -> bool { self.trait_def(trait_ref.def_id).is_marker };
1619+
is_marker_impl(impl1.trait_ref) && is_marker_impl(impl2.trait_ref)
16161620
};
16171621

16181622
if is_marker_overlap {

‎compiler/rustc_middle/src/ty/parameterized.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,5 @@ parameterized_over_tcx! {
134134
ty::Predicate,
135135
ty::Clause,
136136
ty::ClauseKind,
137+
ty::ImplTraitHeader
137138
}

‎compiler/rustc_monomorphize/src/collector.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,18 +1339,17 @@ fn create_mono_items_for_default_impls<'tcx>(
13391339
item: hir::ItemId,
13401340
output: &mut MonoItems<'tcx>,
13411341
) {
1342-
let polarity = tcx.impl_polarity(item.owner_id);
1343-
if matches!(polarity, ty::ImplPolarity::Negative) {
1342+
let Some(impl_) = tcx.impl_trait_header(item.owner_id) else {
13441343
return;
1345-
}
1344+
};
13461345

1347-
if tcx.generics_of(item.owner_id).own_requires_monomorphization() {
1346+
if matches!(impl_.skip_binder().polarity, ty::ImplPolarity::Negative) {
13481347
return;
13491348
}
13501349

1351-
let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) else {
1350+
if tcx.generics_of(item.owner_id).own_requires_monomorphization() {
13521351
return;
1353-
};
1352+
}
13541353

13551354
// Lifetimes never affect trait selection, so we are allowed to eagerly
13561355
// instantiate an instance of an impl method if the impl (and method,
@@ -1368,7 +1367,7 @@ fn create_mono_items_for_default_impls<'tcx>(
13681367
}
13691368
};
13701369
let impl_args = GenericArgs::for_item(tcx, item.owner_id.to_def_id(), only_region_params);
1371-
let trait_ref = trait_ref.instantiate(tcx, impl_args);
1370+
let trait_ref = impl_.instantiate(tcx, impl_args).trait_ref;
13721371

13731372
// Unlike 'lazy' monomorphization that begins by collecting items transitively
13741373
// called by `main` or other global items, when eagerly monomorphizing impl

‎compiler/rustc_trait_selection/src/solve/trait_goals.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,18 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
3939
) -> Result<Candidate<'tcx>, NoSolution> {
4040
let tcx = ecx.tcx();
4141

42-
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
42+
let impl_trait_header = tcx.impl_trait_header(impl_def_id).unwrap();
4343
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
44-
if !drcx.args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args) {
44+
if !drcx.args_may_unify(
45+
goal.predicate.trait_ref.args,
46+
impl_trait_header.skip_binder().trait_ref.args,
47+
) {
4548
return Err(NoSolution);
4649
}
4750

48-
let impl_polarity = tcx.impl_polarity(impl_def_id);
4951
// An upper bound of the certainty of this goal, used to lower the certainty
5052
// of reservation impl to ambiguous during coherence.
53+
let impl_polarity = impl_trait_header.skip_binder().polarity;
5154
let maximal_certainty = match impl_polarity {
5255
ty::ImplPolarity::Positive | ty::ImplPolarity::Negative => {
5356
match impl_polarity == goal.predicate.polarity {
@@ -63,7 +66,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
6366

6467
ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
6568
let impl_args = ecx.fresh_args_for_item(impl_def_id);
66-
let impl_trait_ref = impl_trait_ref.instantiate(tcx, impl_args);
69+
let impl_trait_ref = impl_trait_header.instantiate(tcx, impl_args).trait_ref;
6770

6871
ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
6972
let where_clause_bounds = tcx

‎compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,13 +1980,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
19801980
.tcx
19811981
.all_impls(trait_pred.def_id())
19821982
.filter_map(|def_id| {
1983-
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative
1983+
let imp = self.tcx.impl_trait_header(def_id).unwrap().skip_binder();
1984+
if imp.polarity == ty::ImplPolarity::Negative
19841985
|| !self.tcx.is_user_visible_dep(def_id.krate)
19851986
{
19861987
return None;
19871988
}
1988-
1989-
let imp = self.tcx.impl_trait_ref(def_id).unwrap().skip_binder();
1989+
let imp = imp.trait_ref;
19901990

19911991
self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map(
19921992
|similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id },
@@ -2165,12 +2165,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
21652165
.tcx
21662166
.all_impls(def_id)
21672167
// Ignore automatically derived impls and `!Trait` impls.
2168-
.filter(|&def_id| {
2169-
self.tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative
2168+
.filter_map(|def_id| self.tcx.impl_trait_header(def_id))
2169+
.map(ty::EarlyBinder::instantiate_identity)
2170+
.filter(|header| {
2171+
header.polarity != ty::ImplPolarity::Negative
21702172
|| self.tcx.is_automatically_derived(def_id)
21712173
})
2172-
.filter_map(|def_id| self.tcx.impl_trait_ref(def_id))
2173-
.map(ty::EarlyBinder::instantiate_identity)
2174+
.map(|header| header.trait_ref)
21742175
.filter(|trait_ref| {
21752176
let self_ty = trait_ref.self_ty();
21762177
// Avoid mentioning type parameters.

‎compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -560,20 +560,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
560560
// Before we create the substitutions and everything, first
561561
// consider a "quick reject". This avoids creating more types
562562
// and so forth that we need to.
563-
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
564-
if !drcx.args_may_unify(obligation_args, impl_trait_ref.skip_binder().args) {
563+
let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap();
564+
if !drcx
565+
.args_may_unify(obligation_args, impl_trait_header.skip_binder().trait_ref.args)
566+
{
565567
return;
566568
}
567569
if self.reject_fn_ptr_impls(
568570
impl_def_id,
569571
obligation,
570-
impl_trait_ref.skip_binder().self_ty(),
572+
impl_trait_header.skip_binder().trait_ref.self_ty(),
571573
) {
572574
return;
573575
}
574576

575577
self.infcx.probe(|_| {
576-
if let Ok(_args) = self.match_impl(impl_def_id, impl_trait_ref, obligation) {
578+
if let Ok(_args) = self.match_impl(impl_def_id, impl_trait_header, obligation) {
577579
candidates.vec.push(ImplCandidate(impl_def_id));
578580
}
579581
});

‎compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2404,8 +2404,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
24042404
impl_def_id: DefId,
24052405
obligation: &PolyTraitObligation<'tcx>,
24062406
) -> Normalized<'tcx, GenericArgsRef<'tcx>> {
2407-
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
2408-
match self.match_impl(impl_def_id, impl_trait_ref, obligation) {
2407+
let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap();
2408+
match self.match_impl(impl_def_id, impl_trait_header, obligation) {
24092409
Ok(args) => args,
24102410
Err(()) => {
24112411
// FIXME: A rematch may fail when a candidate cache hit occurs
@@ -2438,7 +2438,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
24382438
fn match_impl(
24392439
&mut self,
24402440
impl_def_id: DefId,
2441-
impl_trait_ref: EarlyBinder<ty::TraitRef<'tcx>>,
2441+
impl_trait_header: EarlyBinder<ty::ImplTraitHeader<'tcx>>,
24422442
obligation: &PolyTraitObligation<'tcx>,
24432443
) -> Result<Normalized<'tcx, GenericArgsRef<'tcx>>, ()> {
24442444
let placeholder_obligation =
@@ -2447,12 +2447,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
24472447

24482448
let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id);
24492449

2450-
let impl_trait_ref = impl_trait_ref.instantiate(self.tcx(), impl_args);
2451-
if impl_trait_ref.references_error() {
2450+
let impl_trait_header = impl_trait_header.instantiate(self.tcx(), impl_args);
2451+
if impl_trait_header.references_error() {
24522452
return Err(());
24532453
}
24542454

2455-
debug!(?impl_trait_ref);
2455+
debug!(?impl_trait_header);
24562456

24572457
let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } =
24582458
ensure_sufficient_stack(|| {
@@ -2461,7 +2461,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
24612461
obligation.param_env,
24622462
obligation.cause.clone(),
24632463
obligation.recursion_depth + 1,
2464-
impl_trait_ref,
2464+
impl_trait_header.trait_ref,
24652465
)
24662466
});
24672467

@@ -2482,9 +2482,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
24822482
})?;
24832483
nested_obligations.extend(obligations);
24842484

2485-
if !self.is_intercrate()
2486-
&& self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
2487-
{
2485+
if !self.is_intercrate() && impl_trait_header.polarity == ty::ImplPolarity::Reservation {
24882486
debug!("reservation impls only apply in intercrate mode");
24892487
return Err(());
24902488
}

‎compiler/rustc_trait_selection/src/traits/specialize/mod.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
168168
}
169169
}
170170

171+
let impl1_trait_header = tcx.impl_trait_header(impl1_def_id).unwrap().instantiate_identity();
172+
171173
// We determine whether there's a subset relationship by:
172174
//
173175
// - replacing bound vars with placeholders in impl1,
@@ -181,21 +183,25 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
181183
// See RFC 1210 for more details and justification.
182184

183185
// Currently we do not allow e.g., a negative impl to specialize a positive one
184-
if tcx.impl_polarity(impl1_def_id) != tcx.impl_polarity(impl2_def_id) {
186+
if impl1_trait_header.polarity != tcx.impl_polarity(impl2_def_id) {
185187
return false;
186188
}
187189

188190
// create a parameter environment corresponding to a (placeholder) instantiation of impl1
189191
let penv = tcx.param_env(impl1_def_id);
190-
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity();
191192

192193
// Create an infcx, taking the predicates of impl1 as assumptions:
193194
let infcx = tcx.infer_ctxt().build();
194195

195196
// Attempt to prove that impl2 applies, given all of the above.
196-
fulfill_implication(&infcx, penv, impl1_trait_ref, impl1_def_id, impl2_def_id, |_, _| {
197-
ObligationCause::dummy()
198-
})
197+
fulfill_implication(
198+
&infcx,
199+
penv,
200+
impl1_trait_header.trait_ref,
201+
impl1_def_id,
202+
impl2_def_id,
203+
|_, _| ObligationCause::dummy(),
204+
)
199205
.is_ok()
200206
}
201207

‎compiler/rustc_ty_utils/src/ty.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,14 +257,15 @@ fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamE
257257
fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<'_>>> {
258258
debug!("issue33140_self_ty({:?})", def_id);
259259

260-
let trait_ref = tcx
261-
.impl_trait_ref(def_id)
260+
let impl_ = tcx
261+
.impl_trait_header(def_id)
262262
.unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id))
263263
.skip_binder();
264264

265+
let trait_ref = impl_.trait_ref;
265266
debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref);
266267

267-
let is_marker_like = tcx.impl_polarity(def_id) == ty::ImplPolarity::Positive
268+
let is_marker_like = impl_.polarity == ty::ImplPolarity::Positive
268269
&& tcx.associated_item_def_ids(trait_ref.def_id).is_empty();
269270

270271
// Check whether these impls would be ok for a marker trait.

‎tests/incremental/hashes/trait_impls.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -462,9 +462,9 @@ impl AddTypeParameterToImpl<u32> for Bar<u32> {
462462
}
463463

464464
#[cfg(not(any(cfail1,cfail4)))]
465-
#[rustc_clean(except="opt_hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail2")]
465+
#[rustc_clean(except="opt_hir_owner_nodes,generics_of,impl_trait_header", cfg="cfail2")]
466466
#[rustc_clean(cfg="cfail3")]
467-
#[rustc_clean(except="opt_hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail5")]
467+
#[rustc_clean(except="opt_hir_owner_nodes,generics_of,impl_trait_header", cfg="cfail5")]
468468
#[rustc_clean(cfg="cfail6")]
469469
impl<TTT> AddTypeParameterToImpl<TTT> for Bar<TTT> {
470470
#[rustc_clean(
@@ -493,9 +493,9 @@ impl ChangeSelfTypeOfImpl for u32 {
493493
}
494494

495495
#[cfg(not(any(cfail1,cfail4)))]
496-
#[rustc_clean(except="opt_hir_owner_nodes,impl_trait_ref", cfg="cfail2")]
496+
#[rustc_clean(except="opt_hir_owner_nodes,impl_trait_header", cfg="cfail2")]
497497
#[rustc_clean(cfg="cfail3")]
498-
#[rustc_clean(except="opt_hir_owner_nodes,impl_trait_ref", cfg="cfail5")]
498+
#[rustc_clean(except="opt_hir_owner_nodes,impl_trait_header", cfg="cfail5")]
499499
#[rustc_clean(cfg="cfail6")]
500500
impl ChangeSelfTypeOfImpl for u64 {
501501
#[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail2")]

0 commit comments

Comments
 (0)
Please sign in to comment.