Skip to content

Commit 53a4d8e

Browse files
committed
Stop calling impl_polarity when impl_trait_ref was also called
1 parent f733e54 commit 53a4d8e

File tree

12 files changed

+91
-77
lines changed

12 files changed

+91
-77
lines changed

compiler/rustc_hir_analysis/src/astconv/mod.rs

+9-10
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

+14-10
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

+7-7
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_typeck/src/method/suggest.rs

+5-5
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_middle/src/ty/mod.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -1590,15 +1590,16 @@ impl<'tcx> TyCtxt<'tcx> {
15901590
def_id1: DefId,
15911591
def_id2: DefId,
15921592
) -> Option<ImplOverlapKind> {
1593-
let impl_trait_ref1 = self.impl_trait_ref(def_id1).unwrap().instantiate_identity();
1594-
let impl_trait_ref2 = self.impl_trait_ref(def_id2).unwrap().instantiate_identity();
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+
15951596
// If either trait impl references an error, they're allowed to overlap,
15961597
// as one of them essentially doesn't exist.
1597-
if impl_trait_ref1.references_error() || impl_trait_ref2.references_error() {
1598+
if impl1.references_error() || impl2.references_error() {
15981599
return Some(ImplOverlapKind::Permitted { marker: false });
15991600
}
16001601

1601-
match (self.impl_polarity(def_id1), self.impl_polarity(def_id2)) {
1602+
match (impl1.polarity, impl2.polarity) {
16021603
(ImplPolarity::Reservation, _) | (_, ImplPolarity::Reservation) => {
16031604
// `#[rustc_reservation_impl]` impls don't overlap with anything
16041605
return Some(ImplOverlapKind::Permitted { marker: false });
@@ -1615,7 +1616,7 @@ impl<'tcx> TyCtxt<'tcx> {
16151616
let is_marker_overlap = {
16161617
let is_marker_impl =
16171618
|trait_ref: TraitRef<'_>| -> bool { self.trait_def(trait_ref.def_id).is_marker };
1618-
is_marker_impl(impl_trait_ref1) && is_marker_impl(impl_trait_ref2)
1619+
is_marker_impl(impl1.trait_ref) && is_marker_impl(impl2.trait_ref)
16191620
};
16201621

16211622
if is_marker_overlap {

compiler/rustc_monomorphize/src/collector.rs

+6-7
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

+7-4
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

+8-7
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

+6-4
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

+8-10
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
}

0 commit comments

Comments
 (0)