Skip to content

Commit d26b417

Browse files
committedFeb 13, 2024
Auto merge of #120919 - oli-obk:impl_polarity, r=compiler-errors
Merge `impl_polarity` and `impl_trait_ref` queries Hopefully this is perf neutral. I want to finish #120835 and stop using the HIR in `coherent_trait`, which should then give us a perf improvement.
2 parents 0a5b998 + 74c9dff commit d26b417

File tree

22 files changed

+156
-131
lines changed

22 files changed

+156
-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
@@ -1673,9 +1673,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
16731673
.is_accessible_from(self.item_def_id(), tcx)
16741674
&& tcx.all_impls(*trait_def_id)
16751675
.any(|impl_def_id| {
1676-
let trait_ref = tcx.impl_trait_ref(impl_def_id);
1677-
trait_ref.is_some_and(|trait_ref| {
1678-
let impl_ = trait_ref.instantiate(
1676+
let impl_header = tcx.impl_trait_header(impl_def_id);
1677+
impl_header.is_some_and(|header| {
1678+
let header = header.instantiate(
16791679
tcx,
16801680
infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
16811681
);
@@ -1687,11 +1687,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
16871687
infcx
16881688
.can_eq(
16891689
ty::ParamEnv::empty(),
1690-
impl_.self_ty(),
1690+
header.trait_ref.self_ty(),
16911691
value,
1692-
)
1692+
) && header.polarity != ty::ImplPolarity::Negative
16931693
})
1694-
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
16951694
})
16961695
})
16971696
.map(|trait_def_id| tcx.def_path_str(trait_def_id))
@@ -1737,13 +1736,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
17371736
} else {
17381737
// Find all the types that have an `impl` for the trait.
17391738
tcx.all_impls(trait_def_id)
1740-
.filter(|impl_def_id| {
1739+
.filter_map(|impl_def_id| tcx.impl_trait_header(impl_def_id))
1740+
.filter(|header| {
17411741
// Consider only accessible traits
17421742
tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
1743-
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
1743+
&& header.skip_binder().polarity != ty::ImplPolarity::Negative
17441744
})
1745-
.filter_map(|impl_def_id| tcx.impl_trait_ref(impl_def_id))
1746-
.map(|impl_| impl_.instantiate_identity().self_ty())
1745+
.map(|header| header.instantiate_identity().trait_ref.self_ty())
17471746
// We don't care about blanket impls.
17481747
.filter(|self_ty| !self_ty.has_non_region_param())
17491748
.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
@@ -527,8 +527,12 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
527527
}
528528
DefKind::Fn => {} // entirely within check_item_body
529529
DefKind::Impl { of_trait } => {
530-
if of_trait && let Some(impl_trait_ref) = tcx.impl_trait_ref(def_id) {
531-
check_impl_items_against_trait(tcx, def_id, impl_trait_ref.instantiate_identity());
530+
if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) {
531+
check_impl_items_against_trait(
532+
tcx,
533+
def_id,
534+
impl_trait_header.instantiate_identity(),
535+
);
532536
check_on_unimplemented(tcx, def_id);
533537
}
534538
}
@@ -719,19 +723,19 @@ pub(super) fn check_specialization_validity<'tcx>(
719723
fn check_impl_items_against_trait<'tcx>(
720724
tcx: TyCtxt<'tcx>,
721725
impl_id: LocalDefId,
722-
impl_trait_ref: ty::TraitRef<'tcx>,
726+
impl_trait_header: ty::ImplTraitHeader<'tcx>,
723727
) {
724728
// If the trait reference itself is erroneous (so the compilation is going
725729
// to fail), skip checking the items here -- the `impl_item` table in `tcx`
726730
// isn't populated for such impls.
727-
if impl_trait_ref.references_error() {
731+
if impl_trait_header.references_error() {
728732
return;
729733
}
730734

731735
let impl_item_refs = tcx.associated_item_def_ids(impl_id);
732736

733737
// Negative impls are not expected to have any items
734-
match tcx.impl_polarity(impl_id) {
738+
match impl_trait_header.polarity {
735739
ty::ImplPolarity::Reservation | ty::ImplPolarity::Positive => {}
736740
ty::ImplPolarity::Negative => {
737741
if let [first_item_ref, ..] = impl_item_refs {
@@ -748,7 +752,7 @@ fn check_impl_items_against_trait<'tcx>(
748752
}
749753
}
750754

751-
let trait_def = tcx.trait_def(impl_trait_ref.def_id);
755+
let trait_def = tcx.trait_def(impl_trait_header.trait_ref.def_id);
752756

753757
for &impl_item in impl_item_refs {
754758
let ty_impl_item = tcx.associated_item(impl_item);
@@ -767,10 +771,10 @@ fn check_impl_items_against_trait<'tcx>(
767771
));
768772
}
769773
ty::AssocKind::Fn => {
770-
compare_impl_method(tcx, ty_impl_item, ty_trait_item, impl_trait_ref);
774+
compare_impl_method(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref);
771775
}
772776
ty::AssocKind::Type => {
773-
compare_impl_ty(tcx, ty_impl_item, ty_trait_item, impl_trait_ref);
777+
compare_impl_ty(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref);
774778
}
775779
}
776780

@@ -790,7 +794,7 @@ fn check_impl_items_against_trait<'tcx>(
790794
let mut must_implement_one_of: Option<&[Ident]> =
791795
trait_def.must_implement_one_of.as_deref();
792796

793-
for &trait_item_id in tcx.associated_item_def_ids(impl_trait_ref.def_id) {
797+
for &trait_item_id in tcx.associated_item_def_ids(impl_trait_header.trait_ref.def_id) {
794798
let leaf_def = ancestors.leaf_def(tcx, trait_item_id);
795799

796800
let is_implemented = leaf_def
@@ -868,7 +872,7 @@ fn check_impl_items_against_trait<'tcx>(
868872

869873
if let Some(missing_items) = must_implement_one_of {
870874
let attr_span = tcx
871-
.get_attr(impl_trait_ref.def_id, sym::rustc_must_implement_one_of)
875+
.get_attr(impl_trait_header.trait_ref.def_id, sym::rustc_must_implement_one_of)
872876
.map(|attr| attr.span);
873877

874878
missing_items_must_implement_one_of_err(

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

Lines changed: 8 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,12 @@ 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+
// `None` means this is an inherent impl
264+
Some(ty::ImplPolarity::Positive) | None => {
264265
res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait));
265266
}
266-
ty::ImplPolarity::Negative => {
267+
Some(ty::ImplPolarity::Negative) => {
267268
let ast::ImplPolarity::Negative(span) = impl_.polarity else {
268269
bug!("impl_polarity query disagrees with impl's polarity in AST");
269270
};
@@ -280,7 +281,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
280281
.emit());
281282
}
282283
}
283-
ty::ImplPolarity::Reservation => {
284+
Some(ty::ImplPolarity::Reservation) => {
284285
// FIXME: what amount of WF checking do we need for reservation impls?
285286
}
286287
}

‎compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,7 @@ pub fn provide(providers: &mut Providers) {
7979
trait_def,
8080
adt_def,
8181
fn_sig,
82-
impl_trait_ref,
83-
impl_polarity,
82+
impl_trait_header,
8483
coroutine_kind,
8584
coroutine_for_closure,
8685
collect_mod_item_types,
@@ -600,7 +599,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
600599
hir::ItemKind::Impl { .. } => {
601600
tcx.ensure().generics_of(def_id);
602601
tcx.ensure().type_of(def_id);
603-
tcx.ensure().impl_trait_ref(def_id);
602+
tcx.ensure().impl_trait_header(def_id);
604603
tcx.ensure().predicates_of(def_id);
605604
}
606605
hir::ItemKind::Trait(..) => {
@@ -1499,19 +1498,20 @@ fn suggest_impl_trait<'tcx>(
14991498
None
15001499
}
15011500

1502-
fn impl_trait_ref(
1501+
fn impl_trait_header(
15031502
tcx: TyCtxt<'_>,
15041503
def_id: LocalDefId,
1505-
) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
1504+
) -> Option<ty::EarlyBinder<ty::ImplTraitHeader<'_>>> {
15061505
let icx = ItemCtxt::new(tcx, def_id);
1507-
let impl_ = tcx.hir().expect_item(def_id).expect_impl();
1506+
let item = tcx.hir().expect_item(def_id);
1507+
let impl_ = item.expect_impl();
15081508
impl_
15091509
.of_trait
15101510
.as_ref()
15111511
.map(|ast_trait_ref| {
15121512
let selfty = tcx.type_of(def_id).instantiate_identity();
15131513

1514-
if let Some(ErrorGuaranteed { .. }) = check_impl_constness(
1514+
let trait_ref = if let Some(ErrorGuaranteed { .. }) = check_impl_constness(
15151515
tcx,
15161516
tcx.is_const_trait_impl_raw(def_id.to_def_id()),
15171517
ast_trait_ref,
@@ -1536,9 +1536,12 @@ fn impl_trait_ref(
15361536
icx.astconv().instantiate_mono_trait_ref(trait_ref, selfty)
15371537
} else {
15381538
icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty)
1539-
}
1539+
};
1540+
ty::EarlyBinder::bind(ty::ImplTraitHeader {
1541+
trait_ref,
1542+
polarity: polarity_of_impl(tcx, def_id, impl_, item.span)
1543+
})
15401544
})
1541-
.map(ty::EarlyBinder::bind)
15421545
}
15431546

15441547
fn check_impl_constness(
@@ -1566,43 +1569,34 @@ fn check_impl_constness(
15661569
}))
15671570
}
15681571

1569-
fn impl_polarity(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplPolarity {
1572+
fn polarity_of_impl(
1573+
tcx: TyCtxt<'_>,
1574+
def_id: LocalDefId,
1575+
impl_: &hir::Impl<'_>,
1576+
span: Span,
1577+
) -> ty::ImplPolarity {
15701578
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
1571-
let item = tcx.hir().expect_item(def_id);
1572-
match &item.kind {
1573-
hir::ItemKind::Impl(hir::Impl {
1574-
polarity: hir::ImplPolarity::Negative(span),
1575-
of_trait,
1576-
..
1577-
}) => {
1579+
match &impl_ {
1580+
hir::Impl { polarity: hir::ImplPolarity::Negative(span), of_trait, .. } => {
15781581
if is_rustc_reservation {
15791582
let span = span.to(of_trait.as_ref().map_or(*span, |t| t.path.span));
15801583
tcx.dcx().span_err(span, "reservation impls can't be negative");
15811584
}
15821585
ty::ImplPolarity::Negative
15831586
}
1584-
hir::ItemKind::Impl(hir::Impl {
1585-
polarity: hir::ImplPolarity::Positive,
1586-
of_trait: None,
1587-
..
1588-
}) => {
1587+
hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => {
15891588
if is_rustc_reservation {
1590-
tcx.dcx().span_err(item.span, "reservation impls can't be inherent");
1589+
tcx.dcx().span_err(span, "reservation impls can't be inherent");
15911590
}
15921591
ty::ImplPolarity::Positive
15931592
}
1594-
hir::ItemKind::Impl(hir::Impl {
1595-
polarity: hir::ImplPolarity::Positive,
1596-
of_trait: Some(_),
1597-
..
1598-
}) => {
1593+
hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: Some(_), .. } => {
15991594
if is_rustc_reservation {
16001595
ty::ImplPolarity::Reservation
16011596
} else {
16021597
ty::ImplPolarity::Positive
16031598
}
16041599
}
1605-
item => bug!("impl_polarity: {:?} not an impl", item),
16061600
}
16071601
}
16081602

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3134,12 +3134,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31343134
if self
31353135
.tcx
31363136
.all_impls(candidate.def_id)
3137-
.filter(|imp_did| {
3138-
self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
3137+
.map(|imp_did| {
3138+
self.tcx.impl_trait_header(imp_did).expect(
3139+
"inherent impls can't be candidates, only trait impls can be",
3140+
)
3141+
})
3142+
.filter(|header| {
3143+
header.skip_binder().polarity == ty::ImplPolarity::Negative
31393144
})
3140-
.any(|imp_did| {
3141-
let imp =
3142-
self.tcx.impl_trait_ref(imp_did).unwrap().instantiate_identity();
3145+
.any(|header| {
3146+
let imp = header.instantiate_identity().trait_ref;
31433147
let imp_simp =
31443148
simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup);
31453149
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
@@ -1969,10 +1969,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
19691969
let def_id = id.owner_id.to_def_id();
19701970

19711971
self.tables.defaultness.set_some(def_id.index, tcx.defaultness(def_id));
1972-
self.tables.impl_polarity.set_some(def_id.index, tcx.impl_polarity(def_id));
19731972

1974-
if of_trait && let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
1975-
record!(self.tables.impl_trait_ref[def_id] <- trait_ref);
1973+
if of_trait && let Some(header) = tcx.impl_trait_header(def_id) {
1974+
record!(self.tables.impl_trait_header[def_id] <- header);
1975+
let trait_ref = header.map_bound(|h| h.trait_ref);
19761976

19771977
let trait_ref = trait_ref.instantiate_identity();
19781978
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
@@ -2316,6 +2316,20 @@ impl<'tcx> TyCtxt<'tcx> {
23162316
pub fn module_children_local(self, def_id: LocalDefId) -> &'tcx [ModChild] {
23172317
self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..])
23182318
}
2319+
2320+
/// Given an `impl_id`, return the trait it implements.
2321+
/// Return `None` if this is an inherent impl.
2322+
pub fn impl_trait_ref(
2323+
self,
2324+
def_id: impl IntoQueryParam<DefId>,
2325+
) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> {
2326+
Some(self.impl_trait_header(def_id)?.map_bound(|h| h.trait_ref))
2327+
}
2328+
2329+
pub fn impl_polarity(self, def_id: impl IntoQueryParam<DefId>) -> ty::ImplPolarity {
2330+
self.impl_trait_header(def_id)
2331+
.map_or(ty::ImplPolarity::Positive, |h| h.skip_binder().polarity)
2332+
}
23192333
}
23202334

23212335
/// 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>),
@@ -1602,17 +1608,16 @@ impl<'tcx> TyCtxt<'tcx> {
16021608
def_id1: DefId,
16031609
def_id2: DefId,
16041610
) -> Option<ImplOverlapKind> {
1605-
let impl_trait_ref1 = self.impl_trait_ref(def_id1);
1606-
let impl_trait_ref2 = self.impl_trait_ref(def_id2);
1611+
let impl1 = self.impl_trait_header(def_id1).unwrap().instantiate_identity();
1612+
let impl2 = self.impl_trait_header(def_id2).unwrap().instantiate_identity();
1613+
16071614
// If either trait impl references an error, they're allowed to overlap,
16081615
// as one of them essentially doesn't exist.
1609-
if impl_trait_ref1.is_some_and(|tr| tr.instantiate_identity().references_error())
1610-
|| impl_trait_ref2.is_some_and(|tr| tr.instantiate_identity().references_error())
1611-
{
1616+
if impl1.references_error() || impl2.references_error() {
16121617
return Some(ImplOverlapKind::Permitted { marker: false });
16131618
}
16141619

1615-
match (self.impl_polarity(def_id1), self.impl_polarity(def_id2)) {
1620+
match (impl1.polarity, impl2.polarity) {
16161621
(ImplPolarity::Reservation, _) | (_, ImplPolarity::Reservation) => {
16171622
// `#[rustc_reservation_impl]` impls don't overlap with anything
16181623
return Some(ImplOverlapKind::Permitted { marker: false });
@@ -1627,10 +1632,9 @@ impl<'tcx> TyCtxt<'tcx> {
16271632
};
16281633

16291634
let is_marker_overlap = {
1630-
let is_marker_impl = |trait_ref: Option<EarlyBinder<TraitRef<'_>>>| -> bool {
1631-
trait_ref.is_some_and(|tr| self.trait_def(tr.skip_binder().def_id).is_marker)
1632-
};
1633-
is_marker_impl(impl_trait_ref1) && is_marker_impl(impl_trait_ref2)
1635+
let is_marker_impl =
1636+
|trait_ref: TraitRef<'_>| -> bool { self.trait_def(trait_ref.def_id).is_marker };
1637+
is_marker_impl(impl1.trait_ref) && is_marker_impl(impl2.trait_ref)
16341638
};
16351639

16361640
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
@@ -1347,18 +1347,17 @@ fn create_mono_items_for_default_impls<'tcx>(
13471347
item: hir::ItemId,
13481348
output: &mut MonoItems<'tcx>,
13491349
) {
1350-
let polarity = tcx.impl_polarity(item.owner_id);
1351-
if matches!(polarity, ty::ImplPolarity::Negative) {
1350+
let Some(impl_) = tcx.impl_trait_header(item.owner_id) else {
13521351
return;
1353-
}
1352+
};
13541353

1355-
if tcx.generics_of(item.owner_id).own_requires_monomorphization() {
1354+
if matches!(impl_.skip_binder().polarity, ty::ImplPolarity::Negative) {
13561355
return;
13571356
}
13581357

1359-
let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) else {
1358+
if tcx.generics_of(item.owner_id).own_requires_monomorphization() {
13601359
return;
1361-
};
1360+
}
13621361

13631362
// Lifetimes never affect trait selection, so we are allowed to eagerly
13641363
// instantiate an instance of an impl method if the impl (and method,
@@ -1376,7 +1375,7 @@ fn create_mono_items_for_default_impls<'tcx>(
13761375
}
13771376
};
13781377
let impl_args = GenericArgs::for_item(tcx, item.owner_id.to_def_id(), only_region_params);
1379-
let trait_ref = trait_ref.instantiate(tcx, impl_args);
1378+
let trait_ref = impl_.instantiate(tcx, impl_args).trait_ref;
13801379

13811380
// Unlike 'lazy' monomorphization that begins by collecting items transitively
13821381
// 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
@@ -1976,13 +1976,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
19761976
.tcx
19771977
.all_impls(trait_pred.def_id())
19781978
.filter_map(|def_id| {
1979-
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative
1979+
let imp = self.tcx.impl_trait_header(def_id).unwrap().skip_binder();
1980+
if imp.polarity == ty::ImplPolarity::Negative
19801981
|| !self.tcx.is_user_visible_dep(def_id.krate)
19811982
{
19821983
return None;
19831984
}
1984-
1985-
let imp = self.tcx.impl_trait_ref(def_id).unwrap().skip_binder();
1985+
let imp = imp.trait_ref;
19861986

19871987
self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map(
19881988
|similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id },
@@ -2161,12 +2161,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
21612161
.tcx
21622162
.all_impls(def_id)
21632163
// Ignore automatically derived impls and `!Trait` impls.
2164-
.filter(|&def_id| {
2165-
self.tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative
2164+
.filter_map(|def_id| self.tcx.impl_trait_header(def_id))
2165+
.map(ty::EarlyBinder::instantiate_identity)
2166+
.filter(|header| {
2167+
header.polarity != ty::ImplPolarity::Negative
21662168
|| self.tcx.is_automatically_derived(def_id)
21672169
})
2168-
.filter_map(|def_id| self.tcx.impl_trait_ref(def_id))
2169-
.map(ty::EarlyBinder::instantiate_identity)
2170+
.map(|header| header.trait_ref)
21702171
.filter(|trait_ref| {
21712172
let self_ty = trait_ref.self_ty();
21722173
// 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 generic parameters 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
@@ -2412,8 +2412,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
24122412
impl_def_id: DefId,
24132413
obligation: &PolyTraitObligation<'tcx>,
24142414
) -> Normalized<'tcx, GenericArgsRef<'tcx>> {
2415-
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
2416-
match self.match_impl(impl_def_id, impl_trait_ref, obligation) {
2415+
let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap();
2416+
match self.match_impl(impl_def_id, impl_trait_header, obligation) {
24172417
Ok(args) => args,
24182418
Err(()) => {
24192419
// FIXME: A rematch may fail when a candidate cache hit occurs
@@ -2446,7 +2446,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
24462446
fn match_impl(
24472447
&mut self,
24482448
impl_def_id: DefId,
2449-
impl_trait_ref: EarlyBinder<ty::TraitRef<'tcx>>,
2449+
impl_trait_header: EarlyBinder<ty::ImplTraitHeader<'tcx>>,
24502450
obligation: &PolyTraitObligation<'tcx>,
24512451
) -> Result<Normalized<'tcx, GenericArgsRef<'tcx>>, ()> {
24522452
let placeholder_obligation =
@@ -2455,12 +2455,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
24552455

24562456
let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id);
24572457

2458-
let impl_trait_ref = impl_trait_ref.instantiate(self.tcx(), impl_args);
2459-
if impl_trait_ref.references_error() {
2458+
let impl_trait_header = impl_trait_header.instantiate(self.tcx(), impl_args);
2459+
if impl_trait_header.references_error() {
24602460
return Err(());
24612461
}
24622462

2463-
debug!(?impl_trait_ref);
2463+
debug!(?impl_trait_header);
24642464

24652465
let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } =
24662466
ensure_sufficient_stack(|| {
@@ -2469,7 +2469,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
24692469
obligation.param_env,
24702470
obligation.cause.clone(),
24712471
obligation.recursion_depth + 1,
2472-
impl_trait_ref,
2472+
impl_trait_header.trait_ref,
24732473
)
24742474
});
24752475

@@ -2490,9 +2490,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
24902490
})?;
24912491
nested_obligations.extend(obligations);
24922492

2493-
if !self.is_intercrate()
2494-
&& self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
2495-
{
2493+
if !self.is_intercrate() && impl_trait_header.polarity == ty::ImplPolarity::Reservation {
24962494
debug!("reservation impls only apply in intercrate mode");
24972495
return Err(());
24982496
}

‎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.