Remove Option from impl_trait_header

This commit is contained in:
Cameron Steffen 2025-07-22 17:05:45 -05:00
parent e60e9f0826
commit b323f567d9
24 changed files with 65 additions and 69 deletions

View file

@ -7,7 +7,7 @@ use rustc_middle::ty::TyCtxt;
fn parent_impl_or_trait_constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
let parent_id = tcx.local_parent(def_id);
match tcx.def_kind(parent_id) {
DefKind::Impl { of_trait: true } => tcx.impl_trait_header(parent_id).unwrap().constness,
DefKind::Impl { of_trait: true } => tcx.impl_trait_header(parent_id).constness,
DefKind::Trait => {
if tcx.is_const_trait(parent_id.into()) {
hir::Constness::Const

View file

@ -806,10 +806,10 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
DefKind::Impl { of_trait } => {
tcx.ensure_ok().generics_of(def_id);
tcx.ensure_ok().type_of(def_id);
tcx.ensure_ok().impl_trait_header(def_id);
tcx.ensure_ok().predicates_of(def_id);
tcx.ensure_ok().associated_items(def_id);
if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) {
if of_trait {
let impl_trait_header = tcx.impl_trait_header(def_id);
res = res.and(
tcx.ensure_ok()
.coherent_trait(impl_trait_header.trait_ref.instantiate_identity().def_id),

View file

@ -248,7 +248,7 @@ pub(super) fn check_item<'tcx>(
crate::impl_wf_check::check_impl_wf(tcx, def_id, impl_.of_trait.is_some())?;
let mut res = Ok(());
if let Some(of_trait) = impl_.of_trait {
let header = tcx.impl_trait_header(def_id).unwrap();
let header = tcx.impl_trait_header(def_id);
let is_auto = tcx.trait_is_auto(header.trait_ref.skip_binder().def_id);
if let (hir::Defaultness::Default { .. }, true) = (of_trait.defaultness, is_auto) {
let sp = of_trait.trait_ref.path.span;

View file

@ -163,7 +163,7 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed>
let mut res = tcx.ensure_ok().specialization_graph_of(def_id);
for &impl_def_id in impls {
let impl_header = tcx.impl_trait_header(impl_def_id).unwrap();
let impl_header = tcx.impl_trait_header(impl_def_id);
let trait_ref = impl_header.trait_ref.instantiate_identity();
let trait_def = tcx.trait_def(trait_ref.def_id);

View file

@ -1291,28 +1291,26 @@ pub fn suggest_impl_trait<'tcx>(
None
}
fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTraitHeader<'_>> {
fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplTraitHeader<'_> {
let icx = ItemCtxt::new(tcx, def_id);
let item = tcx.hir_expect_item(def_id);
let impl_ = item.expect_impl();
let of_trait = impl_
.of_trait
.unwrap_or_else(|| panic!("expected impl trait, found inherent impl on {def_id:?}"));
let selfty = tcx.type_of(def_id).instantiate_identity();
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
if is_rustc_reservation && impl_.of_trait.is_none() {
tcx.dcx().span_err(item.span, "reservation impls can't be inherent");
check_impl_constness(tcx, of_trait.constness, &of_trait.trait_ref);
let trait_ref = icx.lowerer().lower_impl_trait_ref(&of_trait.trait_ref, selfty);
ty::ImplTraitHeader {
trait_ref: ty::EarlyBinder::bind(trait_ref),
safety: of_trait.safety,
polarity: polarity_of_impl(tcx, of_trait, is_rustc_reservation),
constness: of_trait.constness,
}
impl_.of_trait.map(|of_trait| {
let selfty = tcx.type_of(def_id).instantiate_identity();
check_impl_constness(tcx, of_trait.constness, &of_trait.trait_ref);
let trait_ref = icx.lowerer().lower_impl_trait_ref(&of_trait.trait_ref, selfty);
ty::ImplTraitHeader {
trait_ref: ty::EarlyBinder::bind(trait_ref),
safety: of_trait.safety,
polarity: polarity_of_impl(tcx, of_trait, is_rustc_reservation),
constness: of_trait.constness,
}
})
}
fn check_impl_constness(

View file

@ -514,17 +514,15 @@ pub(super) fn impl_super_outlives(
tcx: TyCtxt<'_>,
def_id: DefId,
) -> ty::EarlyBinder<'_, ty::Clauses<'_>> {
tcx.impl_trait_header(def_id).expect("expected an impl of trait").trait_ref.map_bound(
|trait_ref| {
let clause: ty::Clause<'_> = trait_ref.upcast(tcx);
tcx.mk_clauses_from_iter(util::elaborate(tcx, [clause]).filter(|clause| {
matches!(
clause.kind().skip_binder(),
ty::ClauseKind::TypeOutlives(_) | ty::ClauseKind::RegionOutlives(_)
)
}))
},
)
tcx.impl_trait_header(def_id).trait_ref.map_bound(|trait_ref| {
let clause: ty::Clause<'_> = trait_ref.upcast(tcx);
tcx.mk_clauses_from_iter(util::elaborate(tcx, [clause]).filter(|clause| {
matches!(
clause.kind().skip_binder(),
ty::ClauseKind::TypeOutlives(_) | ty::ClauseKind::RegionOutlives(_)
)
}))
})
}
struct AssocTyToOpaque<'tcx> {

View file

@ -272,8 +272,7 @@ fn create_generic_args<'tcx>(
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
let callee_generics = tcx.generics_of(sig_id);
let parent = tcx.parent(def_id.into());
let parent_args =
tcx.impl_trait_header(parent).unwrap().trait_ref.instantiate_identity().args;
let parent_args = tcx.impl_trait_header(parent).trait_ref.instantiate_identity().args;
let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id);
let method_args = tcx.mk_args(&trait_args[callee_generics.parent_count..]);

View file

@ -473,7 +473,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
} else {
// Find all the types that have an `impl` for the trait.
tcx.all_impls(trait_def_id)
.filter_map(|impl_def_id| tcx.impl_trait_header(impl_def_id))
.map(|impl_def_id| tcx.impl_trait_header(impl_def_id))
.filter(|header| {
// Consider only accessible traits
tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)

View file

@ -1615,7 +1615,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.is_accessible_from(self.item_def_id(), tcx)
&& tcx.all_impls(*trait_def_id)
.any(|impl_def_id| {
let header = tcx.impl_trait_header(impl_def_id).unwrap();
let header = tcx.impl_trait_header(impl_def_id);
let trait_ref = header.trait_ref.instantiate(
tcx,
infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),

View file

@ -3980,11 +3980,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if self
.tcx
.all_impls(candidate.def_id)
.map(|imp_did| {
self.tcx.impl_trait_header(imp_did).expect(
"inherent impls can't be candidates, only trait impls can be",
)
})
.map(|imp_did| self.tcx.impl_trait_header(imp_did))
.filter(|header| header.polarity != ty::ImplPolarity::Positive)
.any(|header| {
let imp = header.trait_ref.instantiate_identity();

View file

@ -2115,7 +2115,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
};
let def_id = id.owner_id.to_def_id();
if of_trait && let Some(header) = tcx.impl_trait_header(def_id) {
if of_trait {
let header = tcx.impl_trait_header(def_id);
record!(self.tables.impl_trait_header[def_id] <- header);
self.tables.defaultness.set_some(def_id.index, tcx.defaultness(def_id));

View file

@ -200,8 +200,8 @@ impl EraseType for Option<mir::DestructuredConstant<'_>> {
type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()];
}
impl EraseType for Option<ty::ImplTraitHeader<'_>> {
type Result = [u8; size_of::<Option<ty::ImplTraitHeader<'static>>>()];
impl EraseType for ty::ImplTraitHeader<'_> {
type Result = [u8; size_of::<ty::ImplTraitHeader<'static>>()];
}
impl EraseType for Option<ty::EarlyBinder<'_, Ty<'_>>> {

View file

@ -1104,8 +1104,7 @@ rustc_queries! {
}
/// Given an `impl_id`, return the trait it implements along with some header information.
/// Return `None` if this is an inherent impl.
query impl_trait_header(impl_id: DefId) -> Option<ty::ImplTraitHeader<'tcx>> {
query impl_trait_header(impl_id: DefId) -> ty::ImplTraitHeader<'tcx> {
desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) }
cache_on_disk_if { impl_id.is_local() }
separate_provide_extern

View file

@ -3472,7 +3472,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Whether the trait impl is marked const. This does not consider stability or feature gates.
pub fn is_const_trait_impl(self, def_id: DefId) -> bool {
self.def_kind(def_id) == DefKind::Impl { of_trait: true }
&& self.impl_trait_header(def_id).unwrap().constness == hir::Constness::Const
&& self.impl_trait_header(def_id).constness == hir::Constness::Const
}
pub fn is_sdylib_interface_build(self) -> bool {

View file

@ -1614,8 +1614,8 @@ impl<'tcx> TyCtxt<'tcx> {
def_id1: DefId,
def_id2: DefId,
) -> Option<ImplOverlapKind> {
let impl1 = self.impl_trait_header(def_id1).unwrap();
let impl2 = self.impl_trait_header(def_id2).unwrap();
let impl1 = self.impl_trait_header(def_id1);
let impl2 = self.impl_trait_header(def_id2);
let trait_ref1 = impl1.trait_ref.skip_binder();
let trait_ref2 = impl2.trait_ref.skip_binder();
@ -1973,7 +1973,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
pub fn impl_polarity(self, def_id: impl IntoQueryParam<DefId>) -> ty::ImplPolarity {
self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity)
self.impl_trait_header(def_id).polarity
}
/// Given an `impl_id`, return the trait it implements.
@ -1981,7 +1981,7 @@ impl<'tcx> TyCtxt<'tcx> {
self,
def_id: impl IntoQueryParam<DefId>,
) -> ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>> {
self.impl_opt_trait_ref(def_id).unwrap()
self.impl_trait_header(def_id).trait_ref
}
/// Given an `impl_id`, return the trait it implements.
@ -1990,7 +1990,8 @@ impl<'tcx> TyCtxt<'tcx> {
self,
def_id: impl IntoQueryParam<DefId>,
) -> Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>> {
self.impl_trait_header(def_id).map(|header| header.trait_ref)
let def_id = def_id.into_query_param();
self.impl_is_of_trait(def_id).then(|| self.impl_trait_ref(def_id))
}
/// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
@ -2097,7 +2098,7 @@ impl<'tcx> TyCtxt<'tcx> {
let def_id: DefId = def_id.into();
match self.def_kind(def_id) {
DefKind::Impl { of_trait: true } => {
let header = self.impl_trait_header(def_id).unwrap();
let header = self.impl_trait_header(def_id);
header.constness == hir::Constness::Const
&& self.is_const_trait(header.trait_ref.skip_binder().def_id)
}

View file

@ -1568,7 +1568,7 @@ impl<'v> RootCollector<'_, 'v> {
}
}
}
DefKind::Impl { .. } => {
DefKind::Impl { of_trait: true } => {
if self.strategy == MonoItemCollectionStrategy::Eager {
create_mono_items_for_default_impls(self.tcx, id, self.output);
}
@ -1715,9 +1715,7 @@ fn create_mono_items_for_default_impls<'tcx>(
item: hir::ItemId,
output: &mut MonoItems<'tcx>,
) {
let Some(impl_) = tcx.impl_trait_header(item.owner_id) else {
return;
};
let impl_ = tcx.impl_trait_header(item.owner_id);
if matches!(impl_.polarity, ty::ImplPolarity::Negative) {
return;

View file

@ -57,7 +57,7 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>(
return false;
}
let impl_trait_header = tcx.impl_trait_header(impl_def_id).unwrap();
let impl_trait_header = tcx.impl_trait_header(impl_def_id);
let impl_polarity = impl_trait_header.polarity;
match (impl_polarity, predicate_polarity) {

View file

@ -1867,7 +1867,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
.tcx
.all_impls(trait_pred.def_id())
.filter_map(|def_id| {
let imp = self.tcx.impl_trait_header(def_id).unwrap();
let imp = self.tcx.impl_trait_header(def_id);
if imp.polarity != ty::ImplPolarity::Positive
|| !self.tcx.is_user_visible_dep(def_id.krate)
{
@ -1906,7 +1906,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// ignore `do_not_recommend` items
.filter(|def_id| !self.tcx.do_not_recommend_impl(*def_id))
// Ignore automatically derived impls and `!Trait` impls.
.filter_map(|def_id| self.tcx.impl_trait_header(def_id))
.map(|def_id| self.tcx.impl_trait_header(def_id))
.filter_map(|header| {
(header.polarity != ty::ImplPolarity::Negative
|| self.tcx.is_automatically_derived(def_id))

View file

@ -458,9 +458,7 @@ fn evaluate_host_effect_from_selection_candidate<'tcx>(
Err(_) => Err(EvaluationFailure::NoSolution),
Ok(Some(source)) => match source {
ImplSource::UserDefined(impl_) => {
if tcx.impl_trait_header(impl_.impl_def_id).unwrap().constness
!= hir::Constness::Const
{
if tcx.impl_trait_header(impl_.impl_def_id).constness != hir::Constness::Const {
return Err(EvaluationFailure::NoSolution);
}

View file

@ -604,7 +604,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Before we create the generic parameters and everything, first
// consider a "quick reject". This avoids creating more types
// and so forth that we need to.
let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap();
let impl_trait_header = self.tcx().impl_trait_header(impl_def_id);
if !drcx
.args_may_unify(obligation_args, impl_trait_header.trait_ref.skip_binder().args)
{

View file

@ -2487,7 +2487,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
impl_def_id: DefId,
obligation: &PolyTraitObligation<'tcx>,
) -> Normalized<'tcx, GenericArgsRef<'tcx>> {
let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap();
let impl_trait_header = self.tcx().impl_trait_header(impl_def_id);
match self.match_impl(impl_def_id, impl_trait_header, obligation) {
Ok(args) => args,
Err(()) => {

View file

@ -252,7 +252,7 @@ pub(super) fn specializes(
}
}
let specializing_impl_trait_header = tcx.impl_trait_header(specializing_impl_def_id).unwrap();
let specializing_impl_trait_header = tcx.impl_trait_header(specializing_impl_def_id);
// We determine whether there's a subset relationship by:
//

View file

@ -566,7 +566,11 @@ pub(crate) fn build_impl(
clean::enter_impl_trait(cx, |cx| clean_ty_generics(cx, did)),
),
};
let polarity = tcx.impl_polarity(did);
let polarity = if associated_trait.is_some() {
tcx.impl_polarity(did)
} else {
ty::ImplPolarity::Positive
};
let trait_ = associated_trait
.map(|t| clean_trait_ref_with_constraints(cx, ty::Binder::dummy(t), ThinVec::new()));
if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {

View file

@ -2934,7 +2934,11 @@ fn clean_impl<'tcx>(
trait_,
for_,
items,
polarity: tcx.impl_polarity(def_id),
polarity: if impl_.of_trait.is_some() {
tcx.impl_polarity(def_id)
} else {
ty::ImplPolarity::Positive
},
kind: if utils::has_doc_flag(tcx, def_id.to_def_id(), sym::fake_variadic) {
ImplKind::FakeVariadic
} else {