Skip to content

Merge impl_polarity and impl_trait_ref queries #120919

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1671,9 +1671,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.is_accessible_from(self.item_def_id(), tcx)
&& tcx.all_impls(*trait_def_id)
.any(|impl_def_id| {
let trait_ref = tcx.impl_trait_ref(impl_def_id);
trait_ref.is_some_and(|trait_ref| {
let impl_ = trait_ref.instantiate(
let impl_header = tcx.impl_trait_header(impl_def_id);
impl_header.is_some_and(|header| {
let header = header.instantiate(
tcx,
infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
);
Expand All @@ -1685,11 +1685,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
infcx
.can_eq(
ty::ParamEnv::empty(),
impl_.self_ty(),
header.trait_ref.self_ty(),
value,
)
) && header.polarity != ty::ImplPolarity::Negative
})
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
})
})
.map(|trait_def_id| tcx.def_path_str(trait_def_id))
Expand Down Expand Up @@ -1735,13 +1734,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
} else {
// Find all the types that have an `impl` for the trait.
tcx.all_impls(trait_def_id)
.filter(|impl_def_id| {
.filter_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)
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
&& header.skip_binder().polarity != ty::ImplPolarity::Negative
})
.filter_map(|impl_def_id| tcx.impl_trait_ref(impl_def_id))
.map(|impl_| impl_.instantiate_identity().self_ty())
.map(|header| header.instantiate_identity().trait_ref.self_ty())
// We don't care about blanket impls.
.filter(|self_ty| !self_ty.has_non_region_param())
.map(|self_ty| tcx.erase_regions(self_ty).to_string())
Expand Down
24 changes: 14 additions & 10 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,8 +474,12 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
}
DefKind::Fn => {} // entirely within check_item_body
DefKind::Impl { of_trait } => {
if of_trait && let Some(impl_trait_ref) = tcx.impl_trait_ref(def_id) {
check_impl_items_against_trait(tcx, def_id, impl_trait_ref.instantiate_identity());
if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) {
check_impl_items_against_trait(
tcx,
def_id,
impl_trait_header.instantiate_identity(),
);
check_on_unimplemented(tcx, def_id);
}
}
Expand Down Expand Up @@ -666,19 +670,19 @@ pub(super) fn check_specialization_validity<'tcx>(
fn check_impl_items_against_trait<'tcx>(
tcx: TyCtxt<'tcx>,
impl_id: LocalDefId,
impl_trait_ref: ty::TraitRef<'tcx>,
impl_trait_header: ty::ImplTraitHeader<'tcx>,
) {
// If the trait reference itself is erroneous (so the compilation is going
// to fail), skip checking the items here -- the `impl_item` table in `tcx`
// isn't populated for such impls.
if impl_trait_ref.references_error() {
if impl_trait_header.references_error() {
return;
}

let impl_item_refs = tcx.associated_item_def_ids(impl_id);

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

let trait_def = tcx.trait_def(impl_trait_ref.def_id);
let trait_def = tcx.trait_def(impl_trait_header.trait_ref.def_id);

for &impl_item in impl_item_refs {
let ty_impl_item = tcx.associated_item(impl_item);
Expand All @@ -714,10 +718,10 @@ fn check_impl_items_against_trait<'tcx>(
));
}
ty::AssocKind::Fn => {
compare_impl_method(tcx, ty_impl_item, ty_trait_item, impl_trait_ref);
compare_impl_method(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref);
}
ty::AssocKind::Type => {
compare_impl_ty(tcx, ty_impl_item, ty_trait_item, impl_trait_ref);
compare_impl_ty(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref);
}
}

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

for &trait_item_id in tcx.associated_item_def_ids(impl_trait_ref.def_id) {
for &trait_item_id in tcx.associated_item_def_ids(impl_trait_header.trait_ref.def_id) {
let leaf_def = ancestors.leaf_def(tcx, trait_item_id);

let is_implemented = leaf_def
Expand Down Expand Up @@ -815,7 +819,7 @@ fn check_impl_items_against_trait<'tcx>(

if let Some(missing_items) = must_implement_one_of {
let attr_span = tcx
.get_attr(impl_trait_ref.def_id, sym::rustc_must_implement_one_of)
.get_attr(impl_trait_header.trait_ref.def_id, sym::rustc_must_implement_one_of)
.map(|attr| attr.span);

missing_items_must_implement_one_of_err(
Expand Down
15 changes: 8 additions & 7 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,9 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
// won't be allowed unless there's an *explicit* implementation of `Send`
// for `T`
hir::ItemKind::Impl(impl_) => {
let is_auto = tcx
.impl_trait_ref(def_id)
.is_some_and(|trait_ref| tcx.trait_is_auto(trait_ref.skip_binder().def_id));
let header = tcx.impl_trait_header(def_id);
let is_auto = header
.is_some_and(|header| tcx.trait_is_auto(header.skip_binder().trait_ref.def_id));
let mut res = Ok(());
if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
Expand All @@ -259,11 +259,12 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
.emit());
}
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
match tcx.impl_polarity(def_id) {
ty::ImplPolarity::Positive => {
match header.map(|h| h.skip_binder().polarity) {
// `None` means this is an inherent impl
Some(ty::ImplPolarity::Positive) | None => {
res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait));
}
ty::ImplPolarity::Negative => {
Some(ty::ImplPolarity::Negative) => {
let ast::ImplPolarity::Negative(span) = impl_.polarity else {
bug!("impl_polarity query disagrees with impl's polarity in AST");
};
Expand All @@ -280,7 +281,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
.emit());
}
}
ty::ImplPolarity::Reservation => {
Some(ty::ImplPolarity::Reservation) => {
// FIXME: what amount of WF checking do we need for reservation impls?
}
}
Expand Down
52 changes: 23 additions & 29 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@ pub fn provide(providers: &mut Providers) {
trait_def,
adt_def,
fn_sig,
impl_trait_ref,
impl_polarity,
impl_trait_header,
coroutine_kind,
coroutine_for_closure,
collect_mod_item_types,
Expand Down Expand Up @@ -598,7 +597,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
hir::ItemKind::Impl { .. } => {
tcx.ensure().generics_of(def_id);
tcx.ensure().type_of(def_id);
tcx.ensure().impl_trait_ref(def_id);
tcx.ensure().impl_trait_header(def_id);
tcx.ensure().predicates_of(def_id);
}
hir::ItemKind::Trait(..) => {
Expand Down Expand Up @@ -1323,19 +1322,20 @@ fn suggest_impl_trait<'tcx>(
None
}

fn impl_trait_ref(
fn impl_trait_header(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
) -> Option<ty::EarlyBinder<ty::ImplTraitHeader<'_>>> {
let icx = ItemCtxt::new(tcx, def_id);
let impl_ = tcx.hir().expect_item(def_id).expect_impl();
let item = tcx.hir().expect_item(def_id);
let impl_ = item.expect_impl();
impl_
.of_trait
.as_ref()
.map(|ast_trait_ref| {
let selfty = tcx.type_of(def_id).instantiate_identity();

if let Some(ErrorGuaranteed { .. }) = check_impl_constness(
let trait_ref = if let Some(ErrorGuaranteed { .. }) = check_impl_constness(
tcx,
tcx.is_const_trait_impl_raw(def_id.to_def_id()),
ast_trait_ref,
Expand All @@ -1360,9 +1360,12 @@ fn impl_trait_ref(
icx.astconv().instantiate_mono_trait_ref(trait_ref, selfty)
} else {
icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty)
}
};
ty::EarlyBinder::bind(ty::ImplTraitHeader {
trait_ref,
polarity: polarity_of_impl(tcx, def_id, impl_, item.span)
})
})
.map(ty::EarlyBinder::bind)
}

fn check_impl_constness(
Expand Down Expand Up @@ -1390,43 +1393,34 @@ fn check_impl_constness(
}))
}

fn impl_polarity(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplPolarity {
fn polarity_of_impl(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
impl_: &hir::Impl<'_>,
span: Span,
) -> ty::ImplPolarity {
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
let item = tcx.hir().expect_item(def_id);
match &item.kind {
hir::ItemKind::Impl(hir::Impl {
polarity: hir::ImplPolarity::Negative(span),
of_trait,
..
}) => {
match &impl_ {
hir::Impl { polarity: hir::ImplPolarity::Negative(span), of_trait, .. } => {
if is_rustc_reservation {
let span = span.to(of_trait.as_ref().map_or(*span, |t| t.path.span));
tcx.dcx().span_err(span, "reservation impls can't be negative");
}
ty::ImplPolarity::Negative
}
hir::ItemKind::Impl(hir::Impl {
polarity: hir::ImplPolarity::Positive,
of_trait: None,
..
}) => {
hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => {
if is_rustc_reservation {
tcx.dcx().span_err(item.span, "reservation impls can't be inherent");
tcx.dcx().span_err(span, "reservation impls can't be inherent");
}
ty::ImplPolarity::Positive
}
hir::ItemKind::Impl(hir::Impl {
polarity: hir::ImplPolarity::Positive,
of_trait: Some(_),
..
}) => {
hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: Some(_), .. } => {
if is_rustc_reservation {
ty::ImplPolarity::Reservation
} else {
ty::ImplPolarity::Positive
}
}
item => bug!("impl_polarity: {:?} not an impl", item),
}
}

Expand Down
14 changes: 9 additions & 5 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3134,12 +3134,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if self
.tcx
.all_impls(candidate.def_id)
.filter(|imp_did| {
self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
.map(|imp_did| {
self.tcx.impl_trait_header(imp_did).expect(
"inherent impls can't be candidates, only trait impls can be",
)
})
.filter(|header| {
header.skip_binder().polarity == ty::ImplPolarity::Negative
})
.any(|imp_did| {
let imp =
self.tcx.impl_trait_ref(imp_did).unwrap().instantiate_identity();
.any(|header| {
let imp = header.instantiate_identity().trait_ref;
let imp_simp =
simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup);
imp_simp.is_some_and(|s| s == simp_rcvr_ty)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_incremental/src/persist/dirty_clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const BASE_HIR: &[&str] = &[

/// `impl` implementation of struct/trait
const BASE_IMPL: &[&str] =
&[label_strs::associated_item_def_ids, label_strs::generics_of, label_strs::impl_trait_ref];
&[label_strs::associated_item_def_ids, label_strs::generics_of, label_strs::impl_trait_header];

/// DepNodes for mir_built/Optimized, which is relevant in "executable"
/// code, i.e., functions+methods
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ provide! { tcx, def_id, other, cdata,
variances_of => { table }
fn_sig => { table }
codegen_fn_attrs => { table }
impl_trait_ref => { table }
impl_trait_header => { table }
const_param_default => { table }
object_lifetime_default => { table }
thir_abstract_const => { table }
Expand All @@ -234,7 +234,6 @@ provide! { tcx, def_id, other, cdata,
unused_generic_params => { cdata.root.tables.unused_generic_params.get(cdata, def_id.index) }
def_kind => { cdata.def_kind(def_id.index) }
impl_parent => { table }
impl_polarity => { table_direct }
defaultness => { table_direct }
constness => { table_direct }
coerce_unsized_info => {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1969,10 +1969,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let def_id = id.owner_id.to_def_id();

self.tables.defaultness.set_some(def_id.index, tcx.defaultness(def_id));
self.tables.impl_polarity.set_some(def_id.index, tcx.impl_polarity(def_id));

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

let trait_ref = trait_ref.instantiate_identity();
let simplified_self_ty = fast_reject::simplify_type(
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ define_tables! {
variances_of: Table<DefIndex, LazyArray<ty::Variance>>,
fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::PolyFnSig<'static>>>>,
codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>,
impl_trait_ref: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::TraitRef<'static>>>>,
impl_trait_header: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::ImplTraitHeader<'static>>>>,
const_param_default: Table<DefIndex, LazyValue<ty::EarlyBinder<rustc_middle::ty::Const<'static>>>>,
object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>,
optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>,
Expand All @@ -433,7 +433,6 @@ define_tables! {
promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>,
thir_abstract_const: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::Const<'static>>>>,
impl_parent: Table<DefIndex, RawDefId>,
impl_polarity: Table<DefIndex, ty::ImplPolarity>,
constness: Table<DefIndex, hir::Constness>,
defaultness: Table<DefIndex, hir::Defaultness>,
// FIXME(eddyb) perhaps compute this on the fly if cheap enough?
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/query/erase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ impl EraseType for Option<mir::DestructuredConstant<'_>> {
type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()];
}

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

impl EraseType for Option<ty::EarlyBinder<Ty<'_>>> {
Expand Down
8 changes: 2 additions & 6 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -846,17 +846,13 @@ rustc_queries! {
cache_on_disk_if { true }
}

/// Given an `impl_id`, return the trait it implements.
/// 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_ref(impl_id: DefId) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> {
query impl_trait_header(impl_id: DefId) -> Option<ty::EarlyBinder<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
}
query impl_polarity(impl_id: DefId) -> ty::ImplPolarity {
desc { |tcx| "computing implementation polarity of `{}`", tcx.def_path_str(impl_id) }
separate_provide_extern
}

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